[
  {
    "path": ".gitignore",
    "content": "# Dotenv file\n.env\n\n# Mac\n.DS_Store\n\n# IDE\n.idea/\n\n# Cache / Env\nvenv/\n__pycache__/\n\n# Large files\n*.pyc\n*.zip\n*.csv\n\n# Compiler files\ncontracts/cache/\ncontracts/out/\n\n# Ignores development broadcast logs\n!/broadcast\n/broadcast/*/31337/\n/broadcast/**/dry-run/\n\n# Docs\ndocs/\n\n# Test scripts\nscripts/"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"contracts/lib/forge-std\"]\n\tpath = contracts/lib/forge-std\n\turl = https://github.com/foundry-rs/forge-std\n[submodule \"contracts/lib/openzeppelin-contracts\"]\n\tpath = contracts/lib/openzeppelin-contracts\n\turl = https://github.com/OpenZeppelin/openzeppelin-contracts\n"
  },
  {
    "path": "README.md",
    "content": "# Whack-A-Mole\n\n<p align=\"center\">\n    <img src = \"https://github.com/solidquant/whack-a-mole/assets/134243834/841a91df-728b-489b-b4af-4af948c03c35\" width=\"450px\">\n</p>\n\nThe image is of Dugtrio from Pokemon.\n\n*And the banner is... Pokemon. I'm a Pokemon fan, what more can I say?*\n\n---\n\n### What the heck?\n\nWhack-A-Mole is a CEX-DEX arbitrage bot written in Python.\n\nArbitrage strategies are like the global Whack-A-Mole game played in parallel.\n\nMultiple players participate to find the mole that pops up, and jump to capture that opportunity.\n\nWho knows who'll win...\n\nWhat we know for certain is that you'll need a fast pair of eyes on the market at all times,\nand an extra fast execution engine to capture the moment without latency.\n\nWill our beloved Python be able to accomplish this? We'll see 😎\n\n### Example Strategy #1: DEX arbitrage\n\nThe **main** branch is likely to go through a lot of changes, so to run an example that runs without breaking,\nyou should switch to the **examples/strategy/dex_arb_base** branch before running **main.py**. Run:\n\n```\ngit checkout examples/strategy/dex_arb_base\n```\n\n### Example Strategy #2: CEX-DEX arbitrage\n\n#### You said this is a CEX-DEX arbitrage bot, where the f is it?\n\nI know...🥲 I'm still actively researching the CEX-DEX arbitrage space.\n\nEveryone interested in the process can go visit my other repository which is actually a derivative of Whack-A-Mole:\n\nhttps://github.com/solidquant/cex-dex-arb-research\n\nThis research template is an attempt to find alphas within the crypto space.\n\nYou can focus on DEX only arbs, CEX only arbs, and also CEX-DEX arbs using this template.\n\n### 🛠 Recent Updates (2023.08.08):\n\n1. **asyncio error**: added nest_asyncio\n2. **.env error**: added some randomly generated sample private keys, addresses for people that want a complete testing environment\n3. **requirements.txt**: web3, flashbots, websockets often times have conflicting versions. You sometimes need to delete their fields in the requirements.txt file and install them manually\n4. **Telegram bot**: updated the code so that the bot runs without having to set the Telegram token in .env\n\nNow with these issues resolved, you can easily test this bot out. It is set to debug, and the private keys are set at random,\nso you don't need to worry! Just run:\n\n```python\nimport asyncio\nimport nest_asyncio\n\nfrom strategies.dex_arb_base import main\n\n\nif __name__ == '__main__':\n    nest_asyncio.apply()\n    asyncio.run(main())\n```\n\nThis code is in **main.py**.\n\n```bash\npython main.py\n```\n\n---\n\nCheck out my blog post describing in detail what this project attempts to do, and how you can use it.\n\n[Go to blog 👉](https://medium.com/@solidquant/how-i-built-my-first-mev-arbitrage-bot-introducing-whack-a-mole-66d91657152e)\n\n---\n\n⚡️ For readers that want to talk about MEV and any other quant related stuff with people, please join my Discord! There’s currently no one on the Discord server, so it’s not too active yet, but I hope to meet new people there! 🌎🪐\n\nhttps://discord.com/invite/e6KpjTQP98"
  },
  {
    "path": "abi/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]"
  },
  {
    "path": "abi/UniswapV2Pool.json",
    "content": "[{\"inputs\":[],\"payable\":false,\"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\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0In\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1In\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0Out\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1Out\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"Swap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint112\",\"name\":\"reserve0\",\"type\":\"uint112\"},{\"indexed\":false,\"internalType\":\"uint112\",\"name\":\"reserve1\",\"type\":\"uint112\"}],\"name\":\"Sync\",\"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\"},{\"constant\":true,\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MINIMUM_LIQUIDITY\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"PERMIT_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"burn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getReserves\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"_reserve0\",\"type\":\"uint112\"},{\"internalType\":\"uint112\",\"name\":\"_reserve1\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"_blockTimestampLast\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token1\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"kLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"price0CumulativeLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"price1CumulativeLast\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"skim\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0Out\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Out\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"swap\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"sync\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"token0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"token1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
  },
  {
    "path": "abi/UniswapV2Router2.json",
    "content": "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_WETH\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountADesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenDesired\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"addLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveOut\",\"type\":\"uint256\"}],\"name\":\"getAmountIn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveOut\",\"type\":\"uint256\"}],\"name\":\"getAmountOut\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"}],\"name\":\"getAmountsIn\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"}],\"name\":\"getAmountsOut\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveB\",\"type\":\"uint256\"}],\"name\":\"quote\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"removeLiquidityETHSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountToken\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountTokenMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountETHMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountETH\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenA\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenB\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"liquidity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountAMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountBMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"approveMax\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"removeLiquidityWithPermit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountA\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountB\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapETHForExactTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactETHForTokensSupportingFeeOnTransferTokens\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForETHSupportingFeeOnTransferTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapExactTokensForTokensSupportingFeeOnTransferTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMax\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapTokensForExactETH\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMax\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapTokensForExactTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]"
  },
  {
    "path": "abi/UniswapV3Pool.json",
    "content": "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"name\":\"Burn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"name\":\"Collect\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"name\":\"CollectProtocol\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paid0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"paid1\",\"type\":\"uint256\"}],\"name\":\"Flash\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"observationCardinalityNextOld\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"observationCardinalityNextNew\",\"type\":\"uint16\"}],\"name\":\"IncreaseObservationCardinalityNext\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"},{\"indexed\":false,\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"}],\"name\":\"Initialize\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"indexed\":true,\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol0Old\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol1Old\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol0New\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"feeProtocol1New\",\"type\":\"uint8\"}],\"name\":\"SetFeeProtocol\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"amount0\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"amount1\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"liquidity\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"}],\"name\":\"Swap\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"}],\"name\":\"burn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"uint128\",\"name\":\"amount0Requested\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Requested\",\"type\":\"uint128\"}],\"name\":\"collect\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"amount0Requested\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1Requested\",\"type\":\"uint128\"}],\"name\":\"collectProtocol\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"amount0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"amount1\",\"type\":\"uint128\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint24\",\"name\":\"\",\"type\":\"uint24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGrowthGlobal0X128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGrowthGlobal1X128\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"flash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"observationCardinalityNext\",\"type\":\"uint16\"}],\"name\":\"increaseObservationCardinalityNext\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidity\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxLiquidityPerTick\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount0\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"observations\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"blockTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"int56\",\"name\":\"tickCumulative\",\"type\":\"int56\"},{\"internalType\":\"uint160\",\"name\":\"secondsPerLiquidityCumulativeX128\",\"type\":\"uint160\"},{\"internalType\":\"bool\",\"name\":\"initialized\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"secondsAgos\",\"type\":\"uint32[]\"}],\"name\":\"observe\",\"outputs\":[{\"internalType\":\"int56[]\",\"name\":\"tickCumulatives\",\"type\":\"int56[]\"},{\"internalType\":\"uint160[]\",\"name\":\"secondsPerLiquidityCumulativeX128s\",\"type\":\"uint160[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"positions\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"liquidity\",\"type\":\"uint128\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthInside0LastX128\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthInside1LastX128\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"tokensOwed0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"tokensOwed1\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolFees\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"token0\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"token1\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"feeProtocol0\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"feeProtocol1\",\"type\":\"uint8\"}],\"name\":\"setFeeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slot0\",\"outputs\":[{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96\",\"type\":\"uint160\"},{\"internalType\":\"int24\",\"name\":\"tick\",\"type\":\"int24\"},{\"internalType\":\"uint16\",\"name\":\"observationIndex\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"observationCardinality\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"observationCardinalityNext\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"feeProtocol\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"unlocked\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"}],\"name\":\"snapshotCumulativesInside\",\"outputs\":[{\"internalType\":\"int56\",\"name\":\"tickCumulativeInside\",\"type\":\"int56\"},{\"internalType\":\"uint160\",\"name\":\"secondsPerLiquidityInsideX128\",\"type\":\"uint160\"},{\"internalType\":\"uint32\",\"name\":\"secondsInside\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"zeroForOne\",\"type\":\"bool\"},{\"internalType\":\"int256\",\"name\":\"amountSpecified\",\"type\":\"int256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"swap\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"amount0\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int16\",\"name\":\"\",\"type\":\"int16\"}],\"name\":\"tickBitmap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tickSpacing\",\"outputs\":[{\"internalType\":\"int24\",\"name\":\"\",\"type\":\"int24\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int24\",\"name\":\"\",\"type\":\"int24\"}],\"name\":\"ticks\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"liquidityGross\",\"type\":\"uint128\"},{\"internalType\":\"int128\",\"name\":\"liquidityNet\",\"type\":\"int128\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthOutside0X128\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeGrowthOutside1X128\",\"type\":\"uint256\"},{\"internalType\":\"int56\",\"name\":\"tickCumulativeOutside\",\"type\":\"int56\"},{\"internalType\":\"uint160\",\"name\":\"secondsPerLiquidityOutsideX128\",\"type\":\"uint160\"},{\"internalType\":\"uint32\",\"name\":\"secondsOutside\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"initialized\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token0\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token1\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]"
  },
  {
    "path": "abi/UniswapV3Quoter2.json",
    "content": "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_WETH9\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH9\",\"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\":\"bytes\",\"name\":\"path\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"}],\"name\":\"quoteExactInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint160[]\",\"name\":\"sqrtPriceX96AfterList\",\"type\":\"uint160[]\"},{\"internalType\":\"uint32[]\",\"name\":\"initializedTicksCrossedList\",\"type\":\"uint32[]\"},{\"internalType\":\"uint256\",\"name\":\"gasEstimate\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\"}],\"internalType\":\"struct IQuoterV2.QuoteExactInputSingleParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"quoteExactInputSingle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96After\",\"type\":\"uint160\"},{\"internalType\":\"uint32\",\"name\":\"initializedTicksCrossed\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasEstimate\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"path\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"quoteExactOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint160[]\",\"name\":\"sqrtPriceX96AfterList\",\"type\":\"uint160[]\"},{\"internalType\":\"uint32[]\",\"name\":\"initializedTicksCrossedList\",\"type\":\"uint32[]\"},{\"internalType\":\"uint256\",\"name\":\"gasEstimate\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\"}],\"internalType\":\"struct IQuoterV2.QuoteExactOutputSingleParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"quoteExactOutputSingle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceX96After\",\"type\":\"uint160\"},{\"internalType\":\"uint32\",\"name\":\"initializedTicksCrossed\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"gasEstimate\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"path\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]"
  },
  {
    "path": "abi/UniswapV3SwapRouter2.json",
    "content": "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_factoryV2\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"factoryV3\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_positionManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_WETH9\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"WETH9\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"approveMax\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"approveMaxMinusOne\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"approveZeroThenMax\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"approveZeroThenMaxMinusOne\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"callPositionManager\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"paths\",\"type\":\"bytes[]\"},{\"internalType\":\"uint128[]\",\"name\":\"amounts\",\"type\":\"uint128[]\"},{\"internalType\":\"uint24\",\"name\":\"maximumTickDivergence\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"secondsAgo\",\"type\":\"uint32\"}],\"name\":\"checkOracleSlippage\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"path\",\"type\":\"bytes\"},{\"internalType\":\"uint24\",\"name\":\"maximumTickDivergence\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"secondsAgo\",\"type\":\"uint32\"}],\"name\":\"checkOracleSlippage\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"path\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinimum\",\"type\":\"uint256\"}],\"internalType\":\"struct IV3SwapRouter.ExactInputParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"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\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMinimum\",\"type\":\"uint256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\"}],\"internalType\":\"struct IV3SwapRouter.ExactInputSingleParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactInputSingle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"path\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaximum\",\"type\":\"uint256\"}],\"internalType\":\"struct IV3SwapRouter.ExactOutputParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"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\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMaximum\",\"type\":\"uint256\"},{\"internalType\":\"uint160\",\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\"}],\"internalType\":\"struct IV3SwapRouter.ExactOutputSingleParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"exactOutputSingle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"factoryV2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"getApprovalType\",\"outputs\":[{\"internalType\":\"enum IApproveAndCall.ApprovalType\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"}],\"internalType\":\"struct IApproveAndCall.IncreaseLiquidityParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"increaseLiquidity\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token0\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token1\",\"type\":\"address\"},{\"internalType\":\"uint24\",\"name\":\"fee\",\"type\":\"uint24\"},{\"internalType\":\"int24\",\"name\":\"tickLower\",\"type\":\"int24\"},{\"internalType\":\"int24\",\"name\":\"tickUpper\",\"type\":\"int24\"},{\"internalType\":\"uint256\",\"name\":\"amount0Min\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount1Min\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"internalType\":\"struct IApproveAndCall.MintParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"previousBlockhash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"positionManager\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"pull\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"refundETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermitAllowed\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermitAllowedIfNecessary\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"selfPermitIfNecessary\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"swapExactTokensForTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountInMax\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"path\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"swapTokensForExactTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"}],\"name\":\"sweepToken\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeBips\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"feeRecipient\",\"type\":\"address\"}],\"name\":\"sweepTokenWithFee\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeBips\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"feeRecipient\",\"type\":\"address\"}],\"name\":\"sweepTokenWithFee\",\"outputs\":[],\"stateMutability\":\"payable\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"unwrapWETH9\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"}],\"name\":\"unwrapWETH9\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeBips\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"feeRecipient\",\"type\":\"address\"}],\"name\":\"unwrapWETH9WithFee\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountMinimum\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeBips\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"feeRecipient\",\"type\":\"address\"}],\"name\":\"unwrapWETH9WithFee\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"wrapETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]"
  },
  {
    "path": "abi/WETH.json",
    "content": "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"guy\",\"type\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"src\",\"type\":\"address\"},{\"name\":\"dst\",\"type\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"dst\",\"type\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"src\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"}]"
  },
  {
    "path": "addresses/__init__.py",
    "content": "from addresses.arbitrum import TOKENS as ARBITRUM_TOKENS\nfrom addresses.arbitrum import POOLS as ARBITRUM_POOLS\n\nfrom addresses.ethereum import TOKENS as ETHEREUM_TOKENS\nfrom addresses.ethereum import POOLS as ETHEREUM_POOLS\nfrom addresses.ethereum import SIMULATION_HANDLERS as ETHEREUM_SIMULATION_HANDLERS\nfrom addresses.ethereum import EXECUTION_HANDLERS as ETHEREUM_EXECUTION_HANDLERS\n\nfrom addresses.polygon import TOKENS as POLYGON_TOKENS\nfrom addresses.polygon import POOLS as POLYGON_POOLS\n"
  },
  {
    "path": "addresses/arbitrum.py",
    "content": "EXCHANGE = 'arbitrum'\n\nTOKENS = {\n    'ETH': ['0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', 18],\n    'USDT': ['0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', 6],\n    'USDC': ['0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', 6],\n    'BTC': ['0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f', 8],\n    'ARB': ['0x912CE59144191C1204E64559FE8253a0e49E6548', 18],\n}\n\ncolumns = ['chain', 'exchange', 'version', 'name', 'address', 'fee', 'token0', 'token1']\n\nPOOLS = [\n    ['uniswap', 3, 'ETH/USDC', '0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443', 500, 'ETH', 'USDC'],\n    ['uniswap', 3, 'BTC/ETH', '0x2f5e87C9312fa29aed5c179E456625D79015299c', 500, 'BTC', 'ETH'],\n    ['uniswap', 3, 'ETH/USDT', '0x641C00A822e8b671738d32a431a4Fb6074E5c79d', 500, 'ETH', 'USDT'],\n    ['uniswap', 3, 'USDT/USDC', '0x8c9D230D45d6CfeE39a6680Fb7CB7E8DE7Ea8E71', 100, 'USDT', 'USDC'],\n]\n\nPOOLS = [dict(zip(columns, [EXCHANGE] + pool)) for pool in POOLS]\n"
  },
  {
    "path": "addresses/ethereum.py",
    "content": "EXCHANGE = 'ethereum'\n\nTOKENS = {\n    'ETH': ['0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 18],\n    'USDT': ['0xdAC17F958D2ee523a2206206994597C13D831ec7', 6],\n    'USDC': ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6],\n    'BTC': ['0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8],\n    'DAI': ['0x6B175474E89094C44Da98b954EedeAC495271d0F', 18],\n    'PEPE': ['0x6982508145454Ce325dDbE47a25d4ec3d2311933', 18],\n}\n\ncolumns = ['chain', 'exchange', 'version', 'name', 'address', 'fee', 'token0', 'token1']\n\nPOOLS = [\n    ['uniswap', 3, 'ETH/USDT', '0x11b815efB8f581194ae79006d24E0d814B7697F6', 500, 'ETH', 'USDT'],\n    ['uniswap', 3, 'USDC/USDT', '0x3416cF6C708Da44DB2624D63ea0AAef7113527C6', 100, 'USDC', 'USDT'],\n    ['uniswap', 3, 'BTC/ETH', '0x4585FE77225b41b697C938B018E2Ac67Ac5a20c0', 500, 'BTC', 'ETH'],\n    ['uniswap', 3, 'DAI/USDC', '0x5777d92f208679DB4b9778590Fa3CAB3aC9e2168', 100, 'DAI', 'USDC'],\n    ['uniswap', 3, 'PEPE/ETH', '0x11950d141EcB863F01007AdD7D1A342041227b58', 3000, 'PEPE', 'ETH'],\n\n    ['uniswap', 2, 'ETH/USDT', '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852', 3000, 'ETH', 'USDT'],\n    ['uniswap', 2, 'USDC/ETH', '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc', 3000, 'USDC', 'ETH'],\n    ['uniswap', 2, 'DAI/USDC', '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5', 3000, 'DAI', 'USDC'],\n    ['uniswap', 2, 'PEPE/ETH', '0xA43fe16908251ee70EF74718545e4FE6C5cCEc9f', 3000, 'PEPE', 'ETH'],\n\n    ['sushiswap', 3, 'ETH/USDT', '0x72c2178E082feDB13246877B5aA42ebcE1b72218', 500, 'ETH', 'USDT'],\n    ['sushiswap', 3, 'USDC/ETH', '0x35644Fb61aFBc458bf92B15AdD6ABc1996Be5014', 500, 'USDC', 'ETH'],\n    ['sushiswap', 3, 'BTC/ETH', '0x801CCFae9d2C77893B545E8D0E4637C055CD26cB', 500, 'BTC', 'ETH'],\n    ['sushiswap', 3, 'USDC/USDT', '0xfA6e8E97ecECDC36302eCA534f63439b1E79487B', 100, 'USDC', 'USDT'],\n    ['sushiswap', 3, 'DAI/USDC', '0x31ac258B911Af9a0d2669ebDFC4e39D92e96b772', 100, 'DAI', 'USDC'],\n\n    ['sushiswap', 2, 'BTC/ETH', '0xCEfF51756c56CeFFCA006cD410B03FFC46dd3a58', 3000, 'BTC', 'ETH'],\n    ['sushiswap', 2, 'ETH/USDT', '0x06da0fd433C1A5d7a4faa01111c044910A184553', 3000, 'ETH', 'USDT'],\n    ['sushiswap', 2, 'USDC/ETH', '0x397FF1542f962076d0BFE58eA045FfA2d347ACa0', 3000, 'USDC', 'ETH'],\n    ['sushiswap', 2, 'DAI/ETH', '0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f', 3000, 'DAI', 'ETH'],\n]\n\nPOOLS = [dict(zip(columns, [EXCHANGE] + pool)) for pool in POOLS]\n\nSIMULATION_HANDLERS = {\n    'uniswap_v2': '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f',    # factory\n    'sushiswap_v2': '0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac',  # factory\n    'uniswap_v3': '0x61fFE014bA17989E743c5F6cB21bF9697530B21e',    # quoterv2\n    'sushiswap_v3': '0x64e8802FE490fa7cc61d3463958199161Bb608A7',  # quoterv2\n}\n\nEXECUTION_HANDLERS = {\n    'uniswap_v2': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',    # router2\n    'sushiswap_v2': '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F',  # router2\n    'uniswap_v3': '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45',    # swap router2\n    'sushiswap_v3': '',  # TODO: Sushiswap V3 doesn't have SwapRouter2, needs to use pool contract\n}"
  },
  {
    "path": "addresses/polygon.py",
    "content": "EXCHANGE = 'polygon'\n\nTOKENS = {\n    'ETH': ['0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', 18],\n    'USDT': ['0xc2132D05D31c914a87C6611C10748AEb04B58e8F', 6],\n    'USDC': ['0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', 6],\n    'BTC': ['0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6', 8],\n    'MATIC': ['0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', 18],\n}\n\ncolumns = ['chain', 'exchange', 'version', 'name', 'address', 'fee', 'token0', 'token1']\n\nPOOLS = [\n    ['uniswap', 3, 'USDC/ETH', '0x45dDa9cb7c25131DF268515131f647d726f50608', 500, 'USDC', 'ETH'],\n    ['uniswap', 3, 'BTC/ETH', '0x50eaEDB835021E4A108B7290636d62E9765cc6d7', 500, 'BTC', 'ETH'],\n    ['uniswap', 3, 'USDC/USDT', '0xDaC8A8E6DBf8c690ec6815e0fF03491B2770255D', 100, 'USDC', 'USDT'],\n    ['uniswap', 3, 'MATIC/USDC', '0xA374094527e1673A86dE625aa59517c5dE346d32', 500, 'MATIC', 'USDC'],\n]\n\nPOOLS = [dict(zip(columns, [EXCHANGE] + pool)) for pool in POOLS]\n"
  },
  {
    "path": "configs.py",
    "content": "import os\nfrom dotenv import load_dotenv\n\nfrom addresses import (\n    ETHEREUM_TOKENS,\n    POLYGON_TOKENS,\n    ARBITRUM_TOKENS,\n\n    ETHEREUM_POOLS,\n    POLYGON_POOLS,\n    ARBITRUM_POOLS,\n\n    ETHEREUM_SIMULATION_HANDLERS,\n    ETHEREUM_EXECUTION_HANDLERS,\n)\n\nload_dotenv(override=True)\n\nRPC_ENDPOINTS = {\n    'ethereum': os.getenv('ETHEREUM_HTTP_RPC_URL'),\n    'polygon': os.getenv('POLYGON_HTTP_RPC_URL'),\n    'arbitrum': os.getenv('ARBITRUM_HTTP_RPC_URL'),\n}\n\nWS_ENDPOINTS = {\n    'ethereum': os.getenv('ETHEREUM_WS_RPC_URL'),\n    'polygon': os.getenv('POLYGON_WS_RPC_URL'),\n    'arbitrum': os.getenv('ARBITRUM_WS_RPC_URL'),\n}\n\nTOKENS = {\n    'ethereum': ETHEREUM_TOKENS,\n    'polygon': POLYGON_TOKENS,\n    'arbitrum': ARBITRUM_TOKENS,\n}\n\nPOOLS = ETHEREUM_POOLS + POLYGON_POOLS + ARBITRUM_POOLS\n\nSIMULATION_HANDLERS = {\n    'ethereum': ETHEREUM_SIMULATION_HANDLERS,\n}\n\nEXECUTION_HANDLERS = {\n    'ethereum': ETHEREUM_EXECUTION_HANDLERS,\n}\n"
  },
  {
    "path": "contracts/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": "contracts/src/SimulatorV1.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"openzeppelin-contracts/contracts/utils/math/SafeMath.sol\";\n\nimport \"./protocols/uniswap/UniswapV2Library.sol\";\nimport \"./protocols/uniswap/IQuoterV2.sol\";\nimport \"./protocols/curve/ICurvePool.sol\";\n\n// Deployment gas: 610,194\n// With optimizations: 773,502\ncontract SimulatorV1 {\n    using SafeMath for uint256;\n\n    struct SwapParams {\n        uint8 protocol; // 0 (UniswapV2), 1 (UniswapV3), 2 (Curve Finance)\n        address handler; // UniswapV2: Factory, UniswapV3: Quoter, Curve: Pool\n        address tokenIn;\n        address tokenOut;\n        uint24 fee; // only used in Uniswap V3\n        uint256 amount; // amount in (1 USDC = 1,000,000 / 1 MATIC = 1 * 10 ** 18)\n    }\n\n    constructor() {}\n\n    function simulateSwapIn(\n        SwapParams[] calldata paramsArray\n    ) public returns (uint256) {\n        uint256 amountOut;\n        uint256 paramsArrayLength = paramsArray.length;\n\n        for (uint256 i; i < paramsArrayLength; ) {\n            SwapParams memory params = paramsArray[i];\n\n            if (amountOut == 0) {\n                amountOut = params.amount;\n            } else {\n                params.amount = amountOut;\n            }\n\n            if (params.protocol == 0) {\n                amountOut = simulateUniswapV2SwapIn(params);\n            } else if (params.protocol == 1) {\n                amountOut = simulateUniswapV3SwapIn(params);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        return amountOut;\n    }\n\n    function simulateUniswapV2SwapIn(\n        SwapParams memory params\n    ) public view returns (uint256 amountOut) {\n        (uint reserveIn, uint reserveOut) = UniswapV2Library.getReserves(\n            params.handler,\n            params.tokenIn,\n            params.tokenOut\n        );\n        amountOut = UniswapV2Library.getAmountOut(\n            params.amount,\n            reserveIn,\n            reserveOut\n        );\n    }\n\n    function simulateUniswapV3SwapIn(\n        SwapParams memory params\n    ) public returns (uint256 amountOut) {\n        IQuoterV2 quoter = IQuoterV2(params.handler);\n        IQuoterV2.QuoteExactInputSingleParams memory quoterParams;\n        quoterParams.tokenIn = params.tokenIn;\n        quoterParams.tokenOut = params.tokenOut;\n        quoterParams.amountIn = params.amount;\n        quoterParams.fee = params.fee;\n        quoterParams.sqrtPriceLimitX96 = 0;\n        (amountOut, , , ) = quoter.quoteExactInputSingle(quoterParams);\n    }\n\n    function simulateCurveSwapIn(\n        SwapParams memory params\n    ) public returns (uint256 amountOut) {\n        ICurvePool pool = ICurvePool(params.handler);\n\n        int128 i;\n        int128 j;\n\n        int128 coinIdx;\n\n        while (i == j) {\n            address coin = pool.coins(coinIdx);\n\n            if (coin == params.tokenIn) {\n                i = coinIdx;\n            } else if (coin == params.tokenOut) {\n                j = coinIdx;\n            }\n\n            if (i != j) {\n                break;\n            }\n\n            unchecked {\n                ++coinIdx;\n            }\n        }\n\n        amountOut = pool.get_dy(i, j, params.amount);\n    }\n}\n"
  },
  {
    "path": "contracts/src/WhackAMoleBotV1.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"openzeppelin-contracts/contracts/utils/math/SafeMath.sol\";\nimport \"openzeppelin-contracts/contracts/token/erc20/IERC20.sol\";\nimport \"openzeppelin-contracts/contracts/token/erc20/utils/SafeERC20.sol\";\n\nimport \"./protocols/uniswap/IUniswapV2Router.sol\";\nimport \"./protocols/uniswap/IUniswapV3SwapRouter.sol\";\n\n// Deployment gas: 1,004,388\ncontract WhackAMoleBotV1 {\n    using SafeERC20 for IERC20;\n\n    address internal immutable owner;\n\n    struct SwapParams {\n        uint8 protocol;\n        address handler;\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        uint256 amount;\n    }\n\n    error Unauthorized();\n    error TradeFailed();\n\n    constructor() {\n        owner = msg.sender;\n    }\n\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    function _checkOwner() internal view virtual {\n        if (msg.sender != owner) {\n            revert Unauthorized();\n        }\n    }\n\n    function recoverTokens(address[] calldata tokens) public payable onlyOwner {\n        uint length = tokens.length;\n\n        for (uint i; i < length; ) {\n            address token = tokens[i];\n            IERC20(token).safeTransfer(\n                msg.sender,\n                IERC20(token).balanceOf(address(this))\n            );\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    // 2 tokens, 2 protocols: 142,582 gas\n    function approveHandlers(\n        address[] calldata tokens,\n        address[] calldata protocols\n    ) public payable {\n        // Used to allow Routers from Uniswap V2, Uniswap V3, etc.\n        // the access to tokens held by this contract\n        uint maxInt = type(uint256).max;\n\n        uint tokensLength = tokens.length;\n        uint protocolsLength = protocols.length;\n\n        for (uint i; i < tokensLength; ) {\n            IERC20 token = IERC20(tokens[i]);\n            for (uint j; j < protocolsLength; ) {\n                address protocol = protocols[j];\n                token.safeApprove(protocol, maxInt);\n\n                unchecked {\n                    ++j;\n                }\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function whack(\n        SwapParams[] calldata paramsArray,\n        uint256 minAmountOut\n    ) public payable onlyOwner returns (uint256) {\n        uint256 amountOut;\n        uint256 paramsArrayLength = paramsArray.length;\n\n        for (uint256 i; i < paramsArrayLength; ) {\n            SwapParams memory params = paramsArray[i];\n\n            if (amountOut == 0) {\n                amountOut = params.amount;\n            } else {\n                params.amount = amountOut;\n            }\n\n            if (params.protocol == 0) {\n                amountOut = uniswapV2Swap(params);\n            } else if (params.protocol == 1) {\n                amountOut = uniswapV3Swap(params);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n\n        if (amountOut < minAmountOut) {\n            revert TradeFailed();\n        }\n\n        return amountOut;\n    }\n\n    function uniswapV2Swap(\n        SwapParams memory params\n    ) internal returns (uint256 amountOut) {\n        address[] memory path;\n        path = new address[](2);\n        path[0] = params.tokenIn;\n        path[1] = params.tokenOut;\n\n        uint[] memory amounts = IUniswapV2Router(params.handler)\n            .swapExactTokensForTokens(\n                params.amount,\n                0,\n                path,\n                address(this),\n                block.timestamp\n            );\n\n        return amounts[1];\n    }\n\n    function uniswapV3Swap(\n        SwapParams memory params\n    ) internal returns (uint256 amountOut) {\n        // Sushiswap V3 doesn't have SwapRouter, needs to reimplement this to use Pools\n        ISwapRouter.ExactInputSingleParams memory singleParams = ISwapRouter\n            .ExactInputSingleParams({\n                tokenIn: params.tokenIn,\n                tokenOut: params.tokenOut,\n                fee: params.fee,\n                recipient: address(this),\n                deadline: block.timestamp,\n                amountIn: params.amount,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            });\n\n        amountOut = ISwapRouter(params.handler).exactInputSingle(singleParams);\n    }\n}\n"
  },
  {
    "path": "contracts/src/lib/SafeTransfer.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"../protocols/IERC20.sol\";\n\nlibrary SafeTransfer {\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        (bool s, ) = address(token).call(\n            abi.encodeWithSelector(\n                IERC20.transferFrom.selector,\n                from,\n                to,\n                value\n            )\n        );\n        require(s, \"safeTransferFrom failed\");\n    }\n\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        (bool s, ) = address(token).call(\n            abi.encodeWithSelector(IERC20.transfer.selector, to, value)\n        );\n        require(s, \"safeTransfer failed\");\n    }\n\n    function safeApprove(IERC20 token, address to, uint256 value) internal {\n        (bool s, ) = address(token).call(\n            abi.encodeWithSelector(IERC20.approve.selector, to, value)\n        );\n        require(s, \"safeApprove failed\");\n    }\n\n    function safeTransferETH(address to, uint256 value) internal {\n        (bool s, ) = to.call{value: value}(new bytes(0));\n        require(s, \"safeTransferETH failed\");\n    }\n}\n"
  },
  {
    "path": "contracts/src/protocols/IERC20.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface IERC20 {\n    function totalSupply() external view returns (uint);\n\n    function balanceOf(address account) external view returns (uint);\n\n    function transfer(address recipient, uint amount) external returns (bool);\n\n    function allowance(\n        address owner,\n        address spender\n    ) external view returns (uint);\n\n    function approve(address spender, uint amount) external returns (bool);\n\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint amount\n    ) external returns (bool);\n\n    event Transfer(address indexed from, address indexed to, uint value);\n    event Approval(address indexed owner, address indexed spender, uint value);\n}\n"
  },
  {
    "path": "contracts/src/protocols/IWETH.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"./IERC20.sol\";\n\ninterface IWETH is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint amount) external;\n}\n"
  },
  {
    "path": "contracts/src/protocols/curve/ICurvePool.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface ICurvePool {\n    function get_virtual_price() external returns (uint256 out);\n\n    function add_liquidity(\n        uint256[2] calldata amounts,\n        uint256 deadline\n    ) external;\n\n    function get_dy(\n        int128 i,\n        int128 j,\n        uint256 dx\n    ) external returns (uint256 out);\n\n    function get_dy_underlying(\n        int128 i,\n        int128 j,\n        uint256 dx\n    ) external returns (uint256 out);\n\n    function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external;\n\n    function exchange(\n        int128 i,\n        int128 j,\n        uint256 dx,\n        uint256 min_dy,\n        uint256 deadline\n    ) external;\n\n    function exchange_underlying(\n        int128 i,\n        int128 j,\n        uint256 dx,\n        uint256 min_dy\n    ) external;\n\n    function exchange_underlying(\n        int128 i,\n        int128 j,\n        uint256 dx,\n        uint256 min_dy,\n        uint256 deadline\n    ) external;\n\n    function remove_liquidity(\n        uint256 _amount,\n        uint256 deadline,\n        uint256[2] calldata min_amounts\n    ) external;\n\n    function remove_liquidity_imbalance(\n        uint256[2] calldata amounts,\n        uint256 deadline\n    ) external;\n\n    function commit_new_parameters(\n        int128 amplification,\n        int128 new_fee,\n        int128 new_admin_fee\n    ) external;\n\n    function apply_new_parameters() external;\n\n    function revert_new_parameters() external;\n\n    function commit_transfer_ownership(address _owner) external;\n\n    function apply_transfer_ownership() external;\n\n    function revert_transfer_ownership() external;\n\n    function withdraw_admin_fees() external;\n\n    function coins(int128 arg0) external returns (address out);\n\n    function underlying_coins(int128 arg0) external returns (address out);\n\n    function balances(int128 arg0) external returns (uint256 out);\n\n    function A() external returns (int128 out);\n\n    function fee() external returns (int128 out);\n\n    function admin_fee() external returns (int128 out);\n\n    function owner() external returns (address out);\n\n    function admin_actions_deadline() external returns (uint256 out);\n\n    function transfer_ownership_deadline() external returns (uint256 out);\n\n    function future_A() external returns (int128 out);\n\n    function future_fee() external returns (int128 out);\n\n    function future_admin_fee() external returns (int128 out);\n\n    function future_owner() external returns (address out);\n}\n"
  },
  {
    "path": "contracts/src/protocols/uniswap/IQuoterV2.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\npragma abicoder v2;\n\n/// @title QuoterV2 Interface\n/// @notice Supports quoting the calculated amounts from exact input or exact output swaps.\n/// @notice For each pool also tells you the number of initialized ticks crossed and the sqrt price of the pool after the swap.\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 IQuoterV2 {\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    /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\n    /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\n    /// @return gasEstimate The estimate of the gas that the swap consumes\n    function quoteExactInput(bytes memory path, uint256 amountIn)\n        external\n        returns (\n            uint256 amountOut,\n            uint160[] memory sqrtPriceX96AfterList,\n            uint32[] memory initializedTicksCrossedList,\n            uint256 gasEstimate\n        );\n\n    struct QuoteExactInputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint256 amountIn;\n        uint24 fee;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// @notice Returns the amount out received for a given exact input but for a swap of a single pool\n    /// @param params The params for the quote, encoded as `QuoteExactInputSingleParams`\n    /// tokenIn The token being swapped in\n    /// tokenOut The token being swapped out\n    /// fee The fee of the token pool to consider for the pair\n    /// amountIn The desired input amount\n    /// 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    /// @return sqrtPriceX96After The sqrt price of the pool after the swap\n    /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\n    /// @return gasEstimate The estimate of the gas that the swap consumes\n    function quoteExactInputSingle(QuoteExactInputSingleParams memory params)\n        external\n        returns (\n            uint256 amountOut,\n            uint160 sqrtPriceX96After,\n            uint32 initializedTicksCrossed,\n            uint256 gasEstimate\n        );\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    /// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path\n    /// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path\n    /// @return gasEstimate The estimate of the gas that the swap consumes\n    function quoteExactOutput(bytes memory path, uint256 amountOut)\n        external\n        returns (\n            uint256 amountIn,\n            uint160[] memory sqrtPriceX96AfterList,\n            uint32[] memory initializedTicksCrossedList,\n            uint256 gasEstimate\n        );\n\n    struct QuoteExactOutputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint256 amount;\n        uint24 fee;\n        uint160 sqrtPriceLimitX96;\n    }\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 params The params for the quote, encoded as `QuoteExactOutputSingleParams`\n    /// tokenIn The token being swapped in\n    /// tokenOut The token being swapped out\n    /// fee The fee of the token pool to consider for the pair\n    /// amountOut The desired output amount\n    /// 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    /// @return sqrtPriceX96After The sqrt price of the pool after the swap\n    /// @return initializedTicksCrossed The number of initialized ticks that the swap crossed\n    /// @return gasEstimate The estimate of the gas that the swap consumes\n    function quoteExactOutputSingle(QuoteExactOutputSingleParams memory params)\n        external\n        returns (\n            uint256 amountIn,\n            uint160 sqrtPriceX96After,\n            uint32 initializedTicksCrossed,\n            uint256 gasEstimate\n        );\n}\n"
  },
  {
    "path": "contracts/src/protocols/uniswap/IUniswapV2Pair.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface IUniswapV2Pair {\n    event Approval(\n        address indexed owner,\n        address indexed spender,\n        uint256 value\n    );\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    function name() external pure returns (string memory);\n\n    function symbol() external pure returns (string memory);\n\n    function decimals() external pure returns (uint8);\n\n    function totalSupply() external view returns (uint256);\n\n    function balanceOf(address owner) external view returns (uint256);\n\n    function allowance(address owner, address spender)\n        external\n        view\n        returns (uint256);\n\n    function approve(address spender, uint256 value) external returns (bool);\n\n    function transfer(address to, uint256 value) external returns (bool);\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 value\n    ) external returns (bool);\n\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n    function PERMIT_TYPEHASH() external pure returns (bytes32);\n\n    function nonces(address owner) external view returns (uint256);\n\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    event Mint(address indexed sender, uint256 amount0, uint256 amount1);\n    event Burn(\n        address indexed sender,\n        uint256 amount0,\n        uint256 amount1,\n        address indexed to\n    );\n    event Swap(\n        address indexed sender,\n        uint256 amount0In,\n        uint256 amount1In,\n        uint256 amount0Out,\n        uint256 amount1Out,\n        address indexed to\n    );\n    event Sync(uint112 reserve0, uint112 reserve1);\n\n    function MINIMUM_LIQUIDITY() external pure returns (uint256);\n\n    function factory() external view returns (address);\n\n    function token0() external view returns (address);\n\n    function token1() external view returns (address);\n\n    function getReserves()\n        external\n        view\n        returns (\n            uint112 reserve0,\n            uint112 reserve1,\n            uint32 blockTimestampLast\n        );\n\n    function price0CumulativeLast() external view returns (uint256);\n\n    function price1CumulativeLast() external view returns (uint256);\n\n    function kLast() external view returns (uint256);\n\n    function mint(address to) external returns (uint256 liquidity);\n\n    function burn(address to)\n        external\n        returns (uint256 amount0, uint256 amount1);\n\n    function swap(\n        uint256 amount0Out,\n        uint256 amount1Out,\n        address to,\n        bytes calldata data\n    ) external;\n\n    function skim(address to) external;\n\n    function sync() external;\n\n    function initialize(address, address) external;\n}\n"
  },
  {
    "path": "contracts/src/protocols/uniswap/IUniswapV2Router.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface IUniswapV2Router {\n    function swapExactTokensForTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n\n    function swapTokensForExactTokens(\n        uint amountOut,\n        uint amountInMax,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n}\n"
  },
  {
    "path": "contracts/src/protocols/uniswap/IUniswapV3SwapRouter.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface ISwapRouter {\n    struct ExactInputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        address recipient;\n        uint deadline;\n        uint amountIn;\n        uint 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(\n        ExactInputSingleParams calldata params\n    ) external payable returns (uint amountOut);\n\n    struct ExactInputParams {\n        bytes path;\n        address recipient;\n        uint deadline;\n        uint amountIn;\n        uint 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(\n        ExactInputParams calldata params\n    ) external payable returns (uint amountOut);\n}\n"
  },
  {
    "path": "contracts/src/protocols/uniswap/UniswapV2Library.sol",
    "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"./IUniswapV2Pair.sol\";\n\nimport \"openzeppelin-contracts/contracts/utils/math/SafeMath.sol\";\n\nlibrary UniswapV2Library {\n    using SafeMath for uint256;\n\n    // returns sorted token addresses, used to handle return values from pairs sorted in this order\n    function sortTokens(address tokenA, address tokenB)\n        internal\n        pure\n        returns (address token0, address token1)\n    {\n        require(tokenA != tokenB, \"UniswapV2Library: IDENTICAL_ADDRESSES\");\n        (token0, token1) = tokenA < tokenB\n            ? (tokenA, tokenB)\n            : (tokenB, tokenA);\n        require(token0 != address(0), \"UniswapV2Library: ZERO_ADDRESS\");\n    }\n\n    // calculates the CREATE2 address for a pair without making any external calls\n    function pairFor(\n        address factory,\n        address tokenA,\n        address tokenB\n    ) internal pure returns (address pair) {\n        (address token0, address token1) = sortTokens(tokenA, tokenB);\n\n\n            bytes32 initCodeHash\n         = 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;\n\n        bytes32 salt = keccak256(abi.encodePacked(token0, token1));\n\n        pair = address(\n            uint160(\n                uint256(\n                    keccak256(\n                        abi.encodePacked(\n                            bytes1(0xff),\n                            factory,\n                            salt,\n                            initCodeHash\n                        )\n                    )\n                )\n            )\n        );\n\n        return pair;\n    }\n\n    // fetches and sorts the reserves for a pair\n    function getReserves(\n        address factory,\n        address tokenA,\n        address tokenB\n    ) internal view returns (uint256 reserveA, uint256 reserveB) {\n        (address token0, ) = sortTokens(tokenA, tokenB);\n        (uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(\n            pairFor(factory, tokenA, tokenB)\n        )\n            .getReserves();\n        (reserveA, reserveB) = tokenA == token0\n            ? (reserve0, reserve1)\n            : (reserve1, reserve0);\n    }\n\n    // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n    function getAmountOut(\n        uint256 amountIn,\n        uint256 reserveIn,\n        uint256 reserveOut\n    ) internal pure returns (uint256 amountOut) {\n        require(amountIn > 0, \"UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT\");\n        require(\n            reserveIn > 0 && reserveOut > 0,\n            \"UniswapV2Library: INSUFFICIENT_LIQUIDITY\"\n        );\n        uint256 amountInWithFee = amountIn.mul(997);\n        uint256 numerator = amountInWithFee.mul(reserveOut);\n        uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);\n        amountOut = numerator / denominator;\n    }\n\n    // given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n    function getAmountIn(\n        uint256 amountOut,\n        uint256 reserveIn,\n        uint256 reserveOut\n    ) internal pure returns (uint256 amountIn) {\n        require(amountOut > 0, \"UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT\");\n        require(\n            reserveIn > 0 && reserveOut > 0,\n            \"UniswapV2Library: INSUFFICIENT_LIQUIDITY\"\n        );\n        uint256 numerator = reserveIn.mul(amountOut).mul(1000);\n        uint256 denominator = reserveOut.sub(amountOut).mul(997);\n        amountIn = (numerator / denominator).add(1);\n    }\n\n    // performs chained getAmountOut calculations on any number of pairs\n    function getAmountsOut(\n        address factory,\n        uint256 amountIn,\n        address[] memory path\n    ) internal view returns (uint256[] memory amounts) {\n        require(path.length >= 2, \"UniswapV2Library: INVALID_PATH\");\n        amounts = new uint256[](path.length);\n        amounts[0] = amountIn;\n        for (uint256 i; i < path.length - 1; i++) {\n            (uint256 reserveIn, uint256 reserveOut) = getReserves(\n                factory,\n                path[i],\n                path[i + 1]\n            );\n            amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);\n        }\n    }\n\n    // performs chained getAmountIn calculations on any number of pairs\n    function getAmountsIn(\n        address factory,\n        uint256 amountOut,\n        address[] memory path\n    ) internal view returns (uint256[] memory amounts) {\n        require(path.length >= 2, \"UniswapV2Library: INVALID_PATH\");\n        amounts = new uint256[](path.length);\n        amounts[amounts.length - 1] = amountOut;\n        for (uint256 i = path.length - 1; i > 0; i--) {\n            (uint256 reserveIn, uint256 reserveOut) = getReserves(\n                factory,\n                path[i - 1],\n                path[i]\n            );\n            amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);\n        }\n    }\n}\n"
  },
  {
    "path": "contracts/test/WhackAMoleBotV1.t.sol",
    "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.9;\n\nimport \"forge-std/Test.sol\";\nimport \"../src/WhackAMoleBotV1.sol\";\nimport \"../src/SimulatorV1.sol\";\n\ncontract FoundryDemoTest is Test {\n    WhackAMoleBotV1 bot;\n    SimulatorV1 simulator;\n\n    uint256 simulatedAmountOut1;\n    uint256 simulatedAmountOut2;\n    uint256 simulatedAmountOut3;\n\n    function setUp() public {}\n\n    function testBotDeploy() public {\n        bot = new WhackAMoleBotV1();\n    }\n\n    function testSimulatorDeploy() public {\n        simulator = new SimulatorV1();\n    }\n}\n"
  },
  {
    "path": "data/__init__.py",
    "content": "from data.dex import *\nfrom data.dex_streams import *"
  },
  {
    "path": "data/cex.py",
    "content": "import ccxt\nfrom typing import List\n\n\nclass CEX:\n    \"\"\"\n    Use CCXT to build CEX execution\n\n    The Python project is a prototype CEX-DEX arb. bot,\n    use as much of what others have built already\n    \"\"\"\n\n    def __init__(self, trading_symbols: List[str]):\n        self.trading_symbols = trading_symbols\n\n\nif __name__ == '__main__':\n    \"\"\"\n    Test with Binance, OKX, Bybit\n    These are the top 3 derivatives exchanges\n    \"\"\"\n    from configs import TRADING_SYMBOLS\n\n    cex = CEX(TRADING_SYMBOLS)\n\n    # print(ccxt.exchanges)\n    #\n    # binance = ccxt.binance({'options': {'defaultType': 'future'}})\n    # markets = binance.load_markets()\n    # print(markets)"
  },
  {
    "path": "data/cex_streams.py",
    "content": "import json\nimport time\nimport eth_abi\nimport asyncio\nimport datetime\nimport eth_utils\nimport websockets\nimport numpy as np\nimport aioprocessing\nfrom functools import partial\nfrom typing import Any, Dict, Optional\n\nfrom data.cex import CEX\nfrom data.utils import reconnecting_websocket_loop\n\n\nclass CexStream:\n    \"\"\"\n    WIP\n\n    The first step to building CEX-DEX arbitrage bot is making sure DEX execution works well\n    Data from CEX and DEX are updated at different time frames, as CEX data is real-time,\n    whereas DEX data is updated every new block.\n\n    Analyze how this will affect execution of CEX-DEX arbitrage\n    \"\"\"\n\n    def __init__(self,\n                 cex: CEX,\n                 publisher: Optional[aioprocessing.AioQueue] = None,\n                 debug: bool = False):\n\n        self.cex = cex\n        self.publisher = publisher\n        self.debug = debug\n\n    def publish(self, data: Any):\n        if self.publisher:\n            self.publisher.put(data)\n\n    def start_stream(self):\n        pass\n\n    async def stream_binance_usdm_orderbook(self):\n        async with websockets.connect('wss://fstream.binance.com/ws/') as ws:\n            params = [f'{s.replace(\"/\", \"\").lower()}@depth5@100ms' for s in self.cex.trading_symbols]\n            subscription = {\n                'method': 'SUBSCRIBE',\n                'params': params,\n                'id': 1,\n            }\n            await ws.send(json.dumps(subscription))\n            _ = await ws.recv()\n\n            while True:\n                msg = await asyncio.wait_for(ws.recv(), timeout=15)\n                data = json.loads(msg)\n                print(data)\n\n    async def stream_okx_usdm_orderbook(self):\n        async with websockets.connect('wss://ws.okx.com:8443/ws/v5/public') as ws:\n            args = [{'channel': 'books5', 'instId': f'{s.replace(\"/\", \"-\")}-SWAP'} for s in self.cex.trading_symbols]\n            subscription = {\n                'op': 'subscribe',\n                'args': args,\n            }\n            await ws.send(json.dumps(subscription))\n            _ = await ws.recv()\n\n            while True:\n                msg = await asyncio.wait_for(ws.recv(), timeout=15)\n                data = json.loads(msg)\n                print(data)\n\n    async def stream_bybit_usdm_orderbook(self):\n        \"\"\"\n        Bybit doesn't provide you with the option to stream orderbook snapshot data.\n        We'll have to implement the orderbook snapshot on our own.\n        \"\"\"\n        max_depth = 50\n\n        bids = np.zeros((max_depth, 2))\n        asks = np.zeros((max_depth, 2))\n\n        async with websockets.connect('wss://stream.bybit.com/v5/public/linear') as ws:\n            args = [f'orderbook.{max_depth}.{s.replace(\"/\", \"\").upper()}' for s in self.cex.trading_symbols]\n            subscription = {\n                'op': 'subscribe',\n                'args': args,\n            }\n            await ws.send(json.dumps(subscription))\n            _ = await ws.recv()\n\n            while True:\n                msg = await asyncio.wait_for(ws.recv(), timeout=15)\n                data = json.loads(msg)\n                print(data)\n\n\nif __name__ == '__main__':\n    trading_symbols = ['BTC/USDT']\n\n    cex = CEX(trading_symbols)\n\n    queue = aioprocessing.AioQueue()\n\n    cex_streams = CexStream(cex, queue, False)\n\n    asyncio.run(cex_streams.stream_bybit_usdm_orderbook())\n"
  },
  {
    "path": "data/dex.py",
    "content": "import numpy as np\nfrom web3 import Web3\nfrom typing import Any, Dict, List\nfrom multicall import Call, Multicall\n\nfrom simulation import UniswapV2Simulator, UniswapV3Simulator\n\n# Dimension of DEX.storage_array\nCHAIN = 0\nEXCHANGE = 1\nTOKEN_IN = 2\nTOKEN_OUT = 3\nVERSION = 4\nSTORAGE = 5\n\nV2 = 0\nV3 = 1\n\nDECIMALS0 = 0\nDECIMALS1 = 1\nRESERVE0 = 2\nRESERVE1 = 3\nSQRT_PRICE = 4\nFEE = 5\nTOKEN0_IN = 6\nPOOL_INDEX = 7\n\n\nclass DexBase:\n\n    def __init__(self,\n                 rpc_endpoints: Dict[str, str],\n                 tokens: Dict[str, Dict[str, List[str or int]]],\n                 pools: List[Dict[str, Any]],\n                 trading_symbols: List[str],\n                 max_swap_number: int = 3):\n        \"\"\"\n        :param rpc_endpoints:\n        ex) {'ethereum': '<RPC URL>'}\n\n        :param tokens:\n        ex) {'ethereum': {'ETH': ['<token address>', 18]}}\n\n        :param pools:\n        ex) [{'chain': 'ethereum',\n              'exchange': 'uniswap',\n              'version': 3,\n              'name': 'ETH/USDT',\n              'address': '<pool address>',\n              'fee': 500,  # 0.05%\n              'token0': 'ETH',\n              'token1': 'USDT'}]\n\n        :param trading_symbols:\n        ex) ['BTC/USDT']\n\n        :param max_swap_number: the maximum number of swaps in a trade\n        ex) 1, 2, 3, ...\n        \"\"\"\n        self.rpc_endpoints = rpc_endpoints\n        self.tokens = tokens\n        self.pools = pools\n        self.trading_symbols = trading_symbols\n        self.max_swap_number = max_swap_number\n\n        self.sim_v2 = UniswapV2Simulator()\n        self.sim_v3 = UniswapV3Simulator()\n\n        self.web3 = {k: Web3(Web3.HTTPProvider(v)) for k, v in rpc_endpoints.items()}\n\n        # extract keys from tokens, pools\n        self.chains_list = sorted(list(tokens.keys()))\n        self.exchanges_list = sorted(set([p['exchange'] for p in pools]))\n\n        tokens_list = []\n        for exchange, tokens_dict in tokens.items():\n            tokens_list.extend(list(tokens_dict.keys()))\n        self.tokens_list = sorted(list(set(tokens_list)))\n\n        # map chains, exchanges, tokens to int id value\n        # this is used to map chains/exchanges/tokens to numpy array index values\n        self.chain_to_id = {k: i for i, k in enumerate(self.chains_list)}\n        self.exchange_to_id = {k: i for i, k in enumerate(self.exchanges_list)}\n        self.token_to_id = {k: i for i, k in enumerate(self.tokens_list)}\n\n        \"\"\"\n        storage_array\n        : 6-dimensional array that stores storage values from pool contracts\n        \"\"\"\n        self.storage_array = np.zeros((\n            len(self.chains_list),      # chains\n            len(self.exchanges_list),   # exchanges\n            len(tokens_list),           # token in\n            len(tokens_list),           # token out\n            2,                          # uniswap variant version: 2, 3\n            8                           # decimals0, decimals1, reserve0, reserve1, sqrtPriceX96,\n                                        # fee, token0_is_input, pool_index\n        ))\n\n        \"\"\"\n        storage_index\n        : Keeps the 5-dimensional index of storage_array by chains\n        : Used to generate swap paths\n        : Filled in from _load_pool_data()\n        \n        ex) {'ethereum': [(0, 0, 1, 2, 0), ...]\n        \"\"\"\n        self.storage_index = {c: [] for c in self.chains_list}\n\n        \"\"\"\n        swap_paths\n        : contains information about swap paths, pool indexes, tags, tokens involved, price, fee\n        : Filled in from _generate_swap_paths()\n\n        ex) {'ETH/USDT': {'path': np.ndarray,\n                          'pool_indexes': List[List[int]],\n                          'tag': List[str],\n                          'tokens': np.ndarray,\n                          'price': np.ndarray\n                          'fee': np.ndarray}, ...}\n        \"\"\"\n        self.swap_paths = {s: None for s in self.trading_symbols}\n\n    def load(self):\n        \"\"\"\n        Make sure to call this method in DEX\n        \"\"\"\n        self._load_pool_data()\n        self._generate_swap_paths()\n\n    def _load_pool_data(self):\n        \"\"\"\n        Loads all storage values from multiple pool contracts using Multicall\n        this enables users to bulk query data on the blockchain\n        \"\"\"\n        calls_by_chain = {c: [] for c in self.chains_list}\n\n        for pool_idx, pool in enumerate(self.pools):\n            if pool['version'] == 2:\n                \"\"\"\n                Reference: https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol\n                Return values: reserve0, reserve1, blockTimestampLast\n                \"\"\"\n                signature = 'getReserves()((uint112,uint112,uint32))'\n            else:\n                \"\"\"\n                Reference: https://github.com/Uniswap/v3-core/blob/main/contracts/UniswapV3Pool.sol\n                Return values: sqrtPriceX96, tick, observationIndex, observationCardinality,\n                               observationCardinalityNext, feeProtocol, unlocked\n                \"\"\"\n                signature = 'slot0()((uint160,int24,uint16,uint16,uint16,uint8,bool))'\n\n            call = Call(\n                pool['address'],\n                signature,\n                [(str(pool_idx), lambda x: x)]\n            )\n            calls_by_chain[pool['chain']].append(call)\n\n        # Send multicall queries\n        multicall_results = {}\n        for exchange, calls in calls_by_chain.items():\n            multicall = Multicall(calls, _w3=self.web3[exchange])\n            multicall_results = {\n                **multicall_results,\n                **multicall()\n            }\n\n        # Fill in storage_index, storage_array\n        for pool_idx, storage_data in multicall_results.items():\n            pool: Dict[str, Any] = self.pools[int(pool_idx)]\n\n            chain_idx = self.chain_to_id[pool['chain']]\n            exchange_idx = self.exchange_to_id[pool['exchange']]\n            token0_idx = self.token_to_id[pool['token0']]\n            token1_idx = self.token_to_id[pool['token1']]\n            version_idx = V2 if pool['version'] == 2 else V3\n\n            # We create two indexes to indicate:\n            # - token0 -> token1,\n            # - token1 -> token0\n            idx_1 = (chain_idx, exchange_idx, token0_idx, token1_idx, version_idx)\n            idx_2 = (chain_idx, exchange_idx, token1_idx, token0_idx, version_idx)\n\n            # Keep all the indexes that are associated with the specific chain in DEX.storage_index\n            # this is to _generate_swap_paths using the pre-saved indexes\n            self.storage_index[pool['chain']].append(idx_1)\n            self.storage_index[pool['chain']].append(idx_2)\n\n            decimals0 = self.tokens[pool['chain']][pool['token0']][1]\n            decimals1 = self.tokens[pool['chain']][pool['token1']][1]\n            fee = pool['fee'] / 10000.0 / 100.0\n\n            data = [0] * 6\n\n            if version_idx == V2:\n                reserve0 = storage_data[0]\n                reserve1 = storage_data[1]\n                data = [decimals0, decimals1, reserve0, reserve1, 0, fee]\n\n            elif version_idx == V3:\n                sqrt_price = storage_data[0]\n                data = [decimals0, decimals1, 0, 0, sqrt_price, fee]\n\n            self.storage_array[idx_1] = data + [1, int(pool_idx)]  # token_in is token0\n            self.storage_array[idx_2] = data + [0, int(pool_idx)]  # token_in is not token0\n\n    def _generate_swap_paths(self):\n        \"\"\"\n        Generates all the swap paths up to max_swap_number swaps\n        This internal function has to be called after DEX.storage_index has been filled\n        \"\"\"\n\n        # Dictionary that looks like: {'ETH/USDT': [3, 1], 'BTC/USDT': [3, 0], ...}\n        token_in_out = {\n            symbol: [self.token_to_id[token] for token in reversed(symbol.split('/'))]\n            for symbol in self.trading_symbols\n        }\n\n        chain_swap_paths = {}\n\n        for chain, index in self.storage_index.items():\n            index_arr = np.array(index)\n\n            symbol_swap_paths = {}\n\n            \"\"\"\n            Loop through each symbol from token_in_out (=symbols in trading_symbols)\n            and generate viable swap paths that can occur within a blockchain.\n            This means that there will be multiple viable swap paths for a trading symbol per chain.\n            \"\"\"\n            for symbol, in_out in token_in_out.items():\n                pool_samples = self.__sample_pools(index_arr, in_out)\n                paths = self.__generate_paths(pool_samples)\n\n                paths_arr = np.array(paths)\n                if paths_arr.shape[0] != 0:\n                    symbol_swap_paths[symbol] = paths_arr\n                else:\n                    symbol_swap_paths[symbol] = paths_arr.reshape((0, 3, 5)).astype(np.int64)\n\n            chain_swap_paths[chain] = symbol_swap_paths\n\n        def _get_pool_indexes(_symbol_paths: np.ndarray) -> List[int]:\n            indexes = []\n            for i in np.arange(_symbol_paths.shape[0]):\n                idx = _symbol_paths[i]\n                if np.sum(idx) != 0:\n                    pool_idx = self.storage_array[tuple(idx)][POOL_INDEX]\n                    indexes.append(int(pool_idx))\n            return indexes\n\n        # concatenate the paths generated for each chain\n        for symbol in self.trading_symbols:\n            symbol_paths_list = [chain_swap_paths[chain][symbol] for chain in self.chains_list]\n            symbol_paths_array = np.concatenate(symbol_paths_list)\n\n            pool_indexes = [\n                _get_pool_indexes(symbol_paths_array[i])\n                for i in np.arange(symbol_paths_array.shape[0])\n            ]\n\n            # get unique tokens from pool index that isn't all 0's\n            _tokens_involved = symbol_paths_array[:, :, [TOKEN_IN, TOKEN_OUT]].reshape(-1, 2)\n            tokens_involved = np.unique(_tokens_involved[~np.all(_tokens_involved == 0, axis=1)])\n\n            price_arr = np.zeros(symbol_paths_array.shape[0])\n            fee_arr = np.zeros(symbol_paths_array.shape[0])\n\n            \"\"\"\n            Create a path tag for easy reference/debugging\n            Each tag will look like: ethereum-0, ethereum-1, polygon-0, ...\n            This step is completely unnecessary to the main logic\n            \"\"\"\n            chain_path_counter = {chain: 0 for chain in self.chains_list}\n            tags = []\n            for i in np.arange(symbol_paths_array.shape[0]):\n                chain_idx = symbol_paths_array[i][0][0]\n                chain = self.chains_list[chain_idx]\n                tag = f'{chain}-{chain_path_counter[chain]}'\n                chain_path_counter[chain] += 1\n                tags.append(tag)\n\n            self.swap_paths[symbol] = {\n                'path': symbol_paths_array,     # np.ndarray: (n, max_swap_number, 5)\n                'pool_indexes': pool_indexes,   # List[List[int]]: len() == n\n                'tag': tags,                    # List[str]: len() == n\n                'tokens': tokens_involved,      # np.ndarray: (1, unique token numbers)\n                'price': price_arr,             # np.ndarray: (1, n) --> n should match the number of paths\n                'fee': fee_arr,                 # np.ndarray: (1, n) --> n should match the number of paths\n            }\n\n    def __sample_pools(self, index_arr: np.ndarray, in_out: List[int]) -> Dict[int, List[List[List[int]]]]:\n        # Step #1\n        # Sampling pools that can be used in n-hop swaps with token_in, token_out constraints\n        # Sampling before finding swap paths can reduce the time it takes to build viable swap paths\n        swap_nums = range(1, self.max_swap_number + 1)\n        pool_samples = {n: [] for n in swap_nums}\n\n        for n in swap_nums:\n            token_in, token_out = in_out\n\n            no_path = False\n\n            # setup an empty list of pool samples that could be used in each nth step of the swap path\n            filtered_pools = [[]] * self.max_swap_number\n\n            for i in range(n):\n                if i == 0:\n                    # token_in is int here\n                    condition_1 = index_arr[:, TOKEN_IN] == token_in\n                else:\n                    # token_in in List[int] here\n                    condition_1 = np.isin(index_arr[:, TOKEN_IN], token_in)\n\n                if i == n - 1:\n                    condition_2 = index_arr[:, TOKEN_OUT] == token_out\n                else:\n                    condition_2 = index_arr[:, TOKEN_OUT] != token_out\n\n                condition = condition_1 & condition_2\n                filtered = index_arr[condition]\n                if filtered.shape[0] > 0:\n                    filtered_pools[i] = filtered.tolist()\n                else:\n                    no_path = True\n                    break\n\n                # set the next token_in to be current token_outs\n                token_in = list(filtered[:, TOKEN_OUT])\n\n            if not no_path:\n                pool_samples[n] = filtered_pools\n\n        return pool_samples\n\n    def __generate_paths(self, pool_samples: Dict[int, List[List[List[int]]]]) -> List[List[List[int]]]:\n        \"\"\"\n        :param pool_samples: returned value of DEX._sample_pools\n        \"\"\"\n\n        def __sample_paths_list(_n_total_hops: int,\n                                _nth_hop: int,\n                                _prev_pool: None or List[int],\n                                _sampled: List[List[int]],\n                                _pool_samples: Dict[int, List[List[List[int]]]],\n                                _paths: List[List[List[int]]]):\n            \"\"\"\n            Uses recursive looping to fill in paths_list\n\n            :param _n_total_hops: the number of hops you are trying to sample. ex) 1, 2, 3, ...\n            :param _nth_hop: out of the _n_total_hops which _nth_hop are you on\n            :param _prev_pool: the previous pool index. ex) (0, 0, 1, 2, 0)\n            :param _sampled: the sampled pools we should append to _paths\n            :param _pool_samples: pool_samples we made from the above sampling process\n            :param _paths: the list that collects all viable combination of pools\n            \"\"\"\n\n            for _p in _pool_samples[_n_total_hops][_nth_hop]:\n                _sampled[_nth_hop] = _p\n                if _prev_pool is None or _prev_pool[TOKEN_OUT] == _p[TOKEN_IN]:\n                    if _nth_hop == _n_total_hops - 1:\n                        if _prev_pool:\n                            \"\"\"\n                            Exclude swaps that buy from the previous step, and sells on this one\n                            ex) ETH -> USDT -> ETH\n                            (ETH/USDT, USDT/ETH pools on the same exchange, version are considered equal)\n\n                            This isn't necessarily true in Uniswap V3 variants, because different fee levels can exist.\n                            However, we exclude that scenario for simplicity.\n                            \"\"\"\n                            same_exchange = _prev_pool[EXCHANGE] == _p[EXCHANGE]\n                            same_version = _prev_pool[VERSION] == _p[VERSION]\n                            same_pool = _prev_pool[TOKEN_IN] == _p[TOKEN_OUT] and _prev_pool[TOKEN_OUT] == _p[\n                                TOKEN_IN]\n                            if not (same_exchange and same_version and same_pool):\n                                _paths.append(_sampled.copy())\n                        else:\n                            _paths.append(_sampled.copy())\n                    else:\n                        __sample_paths_list(_n_total_hops,\n                                            _nth_hop + 1,\n                                            _p,\n                                            _sampled,\n                                            _pool_samples,\n                                            _paths)\n\n        # Step #2\n        # Generate swap paths by applying conditional checks to see if token_in, token_out is in sync\n        paths = []\n        empty_pool = [0, 0, 0, 0, 0]\n\n        for i in range(1, self.max_swap_number + 1):\n            if len(pool_samples[i]) > 0:\n                sampled = [empty_pool] * self.max_swap_number\n                prev_pool = None\n                __sample_paths_list(_n_total_hops=i,\n                                    _nth_hop=0,\n                                    _prev_pool=prev_pool,\n                                    _sampled=sampled,\n                                    _pool_samples=pool_samples,\n                                    _paths=paths)\n\n        return paths\n\n\nclass NoSymbolError(Exception):\n\n    def __init__(self, msg: str):\n        self.msg = msg\n\n    def __str__(self):\n        return self.msg\n\n\nclass DEX(DexBase):\n\n    def __init__(self,\n                 rpc_endpoints: Dict[str, str],\n                 tokens: Dict[str, Dict[str, List[str or int]]],\n                 pools: List[Dict[str, Any]],\n                 trading_symbols: List[str],\n                 max_swap_number: int = 3):\n\n        super().__init__(rpc_endpoints,\n                         tokens,\n                         pools,\n                         trading_symbols,\n                         max_swap_number)\n\n        self.load()\n\n        for chain in self.chains_list:\n            for symbol in self.trading_symbols:\n                self.update_price_for_symbol(chain, symbol)\n\n    def get_index(self,\n                  chain: str,\n                  exchange: str,\n                  token0: str,\n                  token1: str,\n                  version: int) -> tuple:\n\n        c = self.chain_to_id[chain]\n        e = self.exchange_to_id[exchange]\n        t0 = self.token_to_id[token0]\n        t1 = self.token_to_id[token1]\n        v = V2 if version == 2 else V3\n        return c, e, t0, t1, v\n\n    def get_price(self,\n                  c: int,\n                  e: int,\n                  t0: int,\n                  t1: int,\n                  v: int) -> tuple:\n\n        idx = (c, e, t0, t1, v)\n        dec0, dec1, res0, res1, sqrt, fee, tok0, _ = self.storage_array[idx]\n\n        if v == V2:\n            price = self.sim_v2.reserves_to_price(res0, res1, dec0, dec1, bool(tok0))\n        else:\n            price = self.sim_v3.sqrtx96_to_price(sqrt, dec0, dec1, bool(tok0))\n\n        return price, fee\n\n    def get_symbols_to_update(self, token0: str, token1: str) -> List[str]:\n        \"\"\"\n        Returns the symbols that need to be updated after\n        token0, token1 storage information have been updated\n\n        This is used in DexStream to figure out which symbols to update the price for\n        after receiving Sync, Swap events from Uniswap V2, V3 variant exchanges\n        \"\"\"\n        token0_id = self.token_to_id[token0]\n        token1_id = self.token_to_id[token1]\n\n        symbols_to_update = []\n\n        for symbol in self.trading_symbols:\n            tokens_involved = self.swap_paths[symbol]['tokens']\n            if token0_id in tokens_involved or token1_id in tokens_involved:\n                symbols_to_update.append(symbol)\n\n        return symbols_to_update\n\n    def update_price_for_symbol(self, chain: str, symbol: str):\n        if symbol not in self.trading_symbols:\n            raise NoSymbolError(f'{symbol} not in {self.trading_symbols}')\n\n        chain_idx = self.chain_to_id[chain]\n        paths_arr = self.swap_paths[symbol]['path']\n\n        for i in np.arange(paths_arr.shape[0]):\n            path = paths_arr[i]\n\n            # There is always a first pool, so check the first pool's chain id\n            if path[0][0] == chain_idx:\n                price = 1\n                fee = 1\n                for p_step in np.arange(path.shape[0]):\n                    idx = path[p_step]\n                    if np.sum(idx) == 0:\n                        break\n                    _p, _f = self.get_price(*idx)\n                    \"\"\"\n                    Take the inverse of price.\n                    This is needed because if you are trying to BUY ETH with USDT,\n                    then token_in will be USDT, and token_out will be ETH.\n                    Thus, the quote amount of ETH you get for providing 1 USDT is currently: 0.0005387 ETH.\n                    However, we want the price to be in the format of ETH/USDT = 1856.32 USDT.\n                    (*This is the equivalent format of CEX price quotes. Binance ETH/USDT = 1856.xx USDT)\n                    To get this value, we take the inverse of price.\n                    1 / 0.0005387 = 1856.32\n                    \"\"\"\n                    price = price * (1 / _p)\n                    fee = fee * (1 - _f)\n\n                self.swap_paths[symbol]['price'][i] = price\n                self.swap_paths[symbol]['fee'][i] = 1 - fee\n\n    def update_reserves(self,\n                        chain: str,\n                        exchange: str,\n                        token0: str,\n                        token1: str,\n                        reserve0: float,\n                        reserve1: float):\n\n        idx_1 = self.get_index(chain, exchange, token0, token1, 2)\n        idx_2 = (idx_1[0], idx_1[1], idx_1[3], idx_1[2], idx_1[4])\n\n        self.storage_array[idx_1][RESERVE0] = reserve0\n        self.storage_array[idx_1][RESERVE1] = reserve1\n\n        self.storage_array[idx_2][RESERVE0] = reserve0\n        self.storage_array[idx_2][RESERVE1] = reserve1\n\n    def update_sqrt_price(self,\n                          chain: str,\n                          exchange: str,\n                          token0: str,\n                          token1: str,\n                          sqrt_price: float):\n\n        idx_1 = self.get_index(chain, exchange, token0, token1, 3)\n        idx_2 = (idx_1[0], idx_1[1], idx_1[3], idx_1[2], idx_1[4])\n\n        self.storage_array[idx_1][SQRT_PRICE] = sqrt_price\n        self.storage_array[idx_2][SQRT_PRICE] = sqrt_price\n\n    def debug_message(self,\n                      chain: str,\n                      exchange: str,\n                      token0: str,\n                      token1: str,\n                      version: int) -> str:\n\n        idx = self.get_index(chain, exchange, token0, token1, version)\n        price, _ = self.get_price(*idx)\n        return f'[{chain}] {exchange} V{version}: {token0}/{token1} @{price} & {token1}/{token0} @{1 / price}'\n\n\nif __name__ == '__main__':\n    from configs import RPC_ENDPOINTS, TOKENS, POOLS\n\n    dex = DEX(RPC_ENDPOINTS,\n              TOKENS,\n              POOLS,\n              ['ETH/USDT'])\n"
  },
  {
    "path": "data/dex_streams.py",
    "content": "import os\nimport json\nimport time\nimport eth_abi\nimport asyncio\nimport aiohttp\nimport datetime\nimport eth_utils\nimport websockets\nimport numpy as np\nimport aioprocessing\nfrom functools import partial\nfrom dotenv import load_dotenv\nfrom typing import Any, Callable, Dict, Optional\n\nfrom data.dex import DEX\nfrom data.utils import reconnecting_websocket_loop, calculate_next_block_base_fee\n\nload_dotenv(override=True)\n\nBLOCKNATIVE_TOKEN = os.getenv('BLOCKNATIVE_TOKEN')\n\n\ndef default_message_format(symbol: str,\n                           message: Dict[str, Any],\n                           block_number: int = 0) -> Dict[str, Any]:\n    \"\"\"\n\n    :param symbol: BTC/USDT, ETH/USDT, ...\n    :param message: value of DEX.swap_paths[symbol]\n    ex) {'path': np.ndarray,\n         'pool_indexes': List[List[int]],\n         'tag': List[str],\n         'tokens': np.ndarray,\n         'price': np.ndarray,\n         'fee': np.ndarray}\n    :param block_number: block number of event\n    :return:\n    \"\"\"\n    return {\n        'source': 'dex',\n        'type': 'event',\n        'block': block_number,\n        'path': message['path'].tolist(),\n        'pool_indexes': message['pool_indexes'],\n        'symbol': symbol,\n        'tag': message['tag'],\n        'price': message['price'].tolist(),\n        'fee': message['fee'].tolist(),\n    }\n\n\nclass DexStream:\n\n    def __init__(self,\n                 dex: DEX,\n                 ws_endpoints: Dict[str, str],\n                 publisher: Optional[aioprocessing.AioQueue] = None,\n                 message_formatter: Callable = default_message_format,\n                 debug: bool = False):\n        \"\"\"\n        :param dex: DEX instance\n\n        :param ws_endpoints:\n        ex) {'ethereum': '<WS URL>'}\n\n        :param publisher: an instance of aioprocessing.AioQueue, used to send processed\n                          market data to strategy\n\n        :param message_formatter: is used to format message sent through the publisher\n                                  this data will be accessed from the main process\n        \"\"\"\n        self.dex = dex\n        self.ws_endpoints = ws_endpoints\n        self.publisher = publisher\n        self.message_formatter = message_formatter\n        self.debug = debug\n\n    def publish(self, data: Any):\n        if self.publisher:\n            self.publisher.put(data)\n\n    def start_streams(self):\n        streams = []\n\n        for chain in self.dex.chains_list:\n            block_stream = reconnecting_websocket_loop(\n                partial(self.stream_new_blocks, chain),\n                tag=f'{chain.upper()}_Blocks'\n            )\n            streams.append(block_stream)\n\n        for chain in self.dex.chains_list:\n            v2_stream = reconnecting_websocket_loop(\n                partial(self.stream_uniswap_v2_events, chain),\n                tag=f'{chain.upper()}_V2'\n            )\n            v3_stream = reconnecting_websocket_loop(\n                partial(self.stream_uniswap_v3_events, chain),\n                tag=f'{chain.upper()}_V3'\n            )\n            streams.extend([asyncio.ensure_future(f) for f in [v2_stream, v3_stream]])\n\n        loop = asyncio.get_event_loop()\n        loop.run_until_complete(asyncio.wait(streams))\n\n    async def stream_uniswap_v2_events(self, chain: str):\n        filtered_pools = [\n            pool for pool in self.dex.pools\n            if pool['chain'] == chain and pool['version'] == 2\n        ]\n        pools = {pool['address'].lower(): pool for pool in filtered_pools}\n\n        sync_event_selector = self.dex.web3[chain].keccak(\n            text='Sync(uint112,uint112)'\n        ).hex()\n\n        async with websockets.connect(self.ws_endpoints[chain]) as ws:\n            subscription = {\n                'json': '2.0',\n                'id': 1,\n                'method': 'eth_subscribe',\n                'params': [\n                    'logs',\n                    {'topics': [sync_event_selector]}\n                ]\n            }\n\n            await ws.send(json.dumps(subscription))\n            _ = await ws.recv()\n\n            while True:\n                msg = await asyncio.wait_for(ws.recv(), timeout=60 * 10)\n                event = json.loads(msg)['params']['result']\n                address = event['address'].lower()\n\n                if address in pools:\n                    s = time.time()\n                    block_number = int(event['blockNumber'], base=16)\n                    pool = pools[address]\n                    data = eth_abi.decode(\n                        ['uint112', 'uint112'],\n                        eth_utils.decode_hex(event['data'])\n                    )\n\n                    chain = pool['chain']\n                    exchange = pool['exchange']\n                    token0 = pool['token0']\n                    token1 = pool['token1']\n\n                    self.dex.update_reserves(chain, exchange, token0, token1, data[0], data[1])\n\n                    symbols = self.dex.get_symbols_to_update(token0, token1)\n                    for symbol in symbols:\n                        self.dex.update_price_for_symbol(chain, symbol)\n                        self.publish(self.message_formatter(symbol, self.dex.swap_paths[symbol], block_number))\n                    e = time.time()\n\n                    if self.debug:\n                        dbg_msg = self.dex.debug_message(chain, exchange, token0, token1, 2)\n                        print(f'{datetime.datetime.now()} {dbg_msg} -> Update took: {e - s} seconds')\n\n    async def stream_uniswap_v3_events(self, chain: str):\n        filtered_pools = [\n            pool for pool in self.dex.pools\n            if pool['chain'] == chain and pool['version'] == 3\n        ]\n        pools = {pool['address'].lower(): pool for pool in filtered_pools}\n\n        swap_event_selector = self.dex.web3[chain].keccak(\n            text='Swap(address,address,int256,int256,uint160,uint128,int24)'\n        ).hex()\n\n        async with websockets.connect(self.ws_endpoints[chain]) as ws:\n            subscription = {\n                'json': '2.0',\n                'id': 1,\n                'method': 'eth_subscribe',\n                'params': [\n                    'logs',\n                    {'topics': [swap_event_selector]}\n                ]\n            }\n\n            await ws.send(json.dumps(subscription))\n            _ = await ws.recv()\n\n            while True:\n                msg = await asyncio.wait_for(ws.recv(), timeout=60 * 10)\n                event = json.loads(msg)['params']['result']\n                address = event['address'].lower()\n\n                if address in pools:\n                    # we don't need the sender, recipient data in topics\n                    s = time.time()\n                    block_number = int(event['blockNumber'], base=16)\n                    pool = pools[address]\n                    data = eth_abi.decode(\n                        ['int256', 'int256', 'uint160', 'uint128', 'int24'],\n                        eth_utils.decode_hex(event['data'])\n                    )\n\n                    chain = pool['chain']\n                    exchange = pool['exchange']\n                    token0 = pool['token0']\n                    token1 = pool['token1']\n\n                    self.dex.update_sqrt_price(chain, exchange, token0, token1, data[2])\n\n                    symbols = self.dex.get_symbols_to_update(token0, token1)\n                    for symbol in symbols:\n                        self.dex.update_price_for_symbol(chain, symbol)\n                        self.publish(self.message_formatter(symbol, self.dex.swap_paths[symbol], block_number))\n                    e = time.time()\n\n                    if self.debug:\n                        dbg_msg = self.dex.debug_message(chain, exchange, token0, token1, 3)\n                        print(f'{datetime.datetime.now()} {dbg_msg} -> Update took: {e - s} seconds')\n\n    async def stream_new_blocks(self, chain: str):\n        \"\"\"\n        Retrieves new blocks and calculates base fees accordingly\n        Base fees are calculated adhering to the EIP-1559 implementation and\n        max_price, max_priority_fee_per_gas, max_fee_per_gas are retrieved using Blocknative's gas estimator endpoint\n\n        - Ethereum: https://api.blocknative.com/gasprices/blockprices?chainId=1\n        - Polygon: https://api.blocknative.com/gasprices/blockprices?chainId=137\n        \"\"\"\n\n        \"\"\"\n        historical_gas tracks 100 historical base_fee, max_priority_fee_per_gas, max_fee_per_gas\n        However, note that the historical data isn't loaded up from the start, but instead is\n        filled in at real-time\n        Thus, at start-up this data is an empty numpy array with all 0's\n        \"\"\"\n        historical_gas = np.zeros((3, 100))\n\n        # index of historical_gas\n        BASE_FEE = 0\n        MAX_PRIORITY_FEE_PER_GAS = 1\n        MAX_FEE_PER_GAS = 2\n\n        async with websockets.connect(self.ws_endpoints[chain]) as ws:\n            subscription = {\n                'json': '2.0',\n                'id': 1,\n                'method': 'eth_subscribe',\n                'params': ['newHeads']\n            }\n\n            await ws.send(json.dumps(subscription))\n            _ = await ws.recv()\n\n            gwei = 10 ** 9\n\n            while True:\n                msg = await asyncio.wait_for(ws.recv(), timeout=60 * 10)\n                block = json.loads(msg)['params']['result']\n                block_number = int(block['number'], base=16)\n                base_fee = calculate_next_block_base_fee(block)\n\n                \"\"\"\n                For Ethereum and Polygon, use gas price estimation tools provided by Blocknative\n                https://www.blocknative.com/gas-estimator\n                \n                Run only if a token is given\n                \"\"\"\n                if chain in ['ethereum', 'polygon'] and BLOCKNATIVE_TOKEN:\n                    chain_id = 1 if 'ethereum' else 137\n                    headers = {'Authorization': BLOCKNATIVE_TOKEN}\n                    async with aiohttp.ClientSession(headers=headers) as session:\n                        async with session.get(f'https://api.blocknative.com/gasprices/blockprices?chainId={chain_id}') as r:\n                            res = await r.json()\n                            estimated_price = res['blockPrices'][0]['estimatedPrices'][0]\n\n                            max_priority_fee_per_gas = estimated_price['maxPriorityFeePerGas']\n                            max_fee_per_gas = estimated_price['maxFeePerGas']\n\n                            new_gas_data = [\n                                base_fee,\n                                int(max_priority_fee_per_gas * gwei),\n                                int(max_fee_per_gas * gwei)\n                            ]\n                else:\n                    new_gas_data = [base_fee, 0, 0]\n\n                \"\"\"\n                update historical_gas data as you would an Deque data structure\n                \n                Currently this data does nothing, however, it can be used to optimize gas costs later\n                \"\"\"\n                historical_gas[:, 0:-1] = historical_gas[:, 1:]\n                historical_gas[:, -1] = new_gas_data\n\n                data = {\n                    'source': 'dex',\n                    'type': 'block',\n                    'chain': chain,\n                    'block': block_number,\n                    'base_fee': int(historical_gas[BASE_FEE, -1]),\n                    'max_priority_fee_per_gas': int(historical_gas[MAX_PRIORITY_FEE_PER_GAS, -1]),\n                    'max_fee_per_gas': int(historical_gas[MAX_FEE_PER_GAS, -1]),\n                }\n                self.publish(data)\n\n\nif __name__ == '__main__':\n    from configs import (\n        RPC_ENDPOINTS,\n        WS_ENDPOINTS,\n        TOKENS,\n        POOLS,\n    )\n\n    chain = 'ethereum'\n\n    rpc_endpoints = {chain: RPC_ENDPOINTS[chain]}\n    ws_endpoints = {chain: WS_ENDPOINTS[chain]}\n    tokens = {chain: TOKENS[chain]}\n    pools = [pool for pool in POOLS if pool['chain'] == chain]\n\n    dex = DEX(rpc_endpoints,\n              tokens,\n              pools,\n              ['ETH/USDT'])\n\n    queue = aioprocessing.AioQueue()\n\n    dex_stream = DexStream(dex, ws_endpoints, queue, default_message_format, False)\n    # dex_stream.start_streams()\n    asyncio.run(dex_stream.stream_new_blocks('ethereum'))\n"
  },
  {
    "path": "data/utils.py",
    "content": "import random\nimport asyncio\nimport websockets\nfrom typing import Any, Callable, Dict\n\n\nasync def reconnecting_websocket_loop(stream_fn: Callable, tag: str):\n    while True:\n        try:\n            await stream_fn()\n\n        except (websockets.ConnectionClosedError, websockets.ConnectionClosedOK) as e:\n            print(f'{tag} websocket connection closed: {e}')\n            print('Reconnecting...')\n            await asyncio.sleep(2)\n\n        except Exception as e:\n            print(f'An error has occurred with {tag} websocket: {e}')\n            break\n\n\ndef calculate_next_block_base_fee(block: Dict[str, Any]):\n    base_fee = int(block['baseFeePerGas'], base=16)\n    gas_used = int(block['gasUsed'], base=16)\n    gas_limit = int(block['gasLimit'], base=16)\n\n    target_gas_used = gas_limit / 2\n    target_gas_used = 1 if target_gas_used == 0 else target_gas_used\n\n    if gas_used > target_gas_used:\n        new_base_fee = base_fee + ((base_fee * (gas_used - target_gas_used)) / target_gas_used) / 8\n    else:\n        new_base_fee = base_fee - ((base_fee * (target_gas_used - gas_used)) / target_gas_used) / 8\n\n    return int(new_base_fee + random.randint(0, 9))\n"
  },
  {
    "path": "examples/dex.py",
    "content": "import numpy as np\n\nfrom data.dex import DEX\nfrom configs import RPC_ENDPOINTS, TOKENS, POOLS\n\n\nif __name__ == '__main__':\n    dex = DEX(RPC_ENDPOINTS,\n              TOKENS,\n              POOLS,\n              ['ETH/USDT', 'BTC/USDT'])\n\n    # Retrieving the price of a specific pool\n    idx = dex.get_index('ethereum', 'uniswap', 'ETH', 'USDT', 3)\n    print(idx)\n\n    price, fee = dex.get_price(*idx)\n    print(price, fee)\n\n    # Retrieving price of multiple swap paths\n    btc_price = dex.swap_paths['BTC/USDT']['price']\n    btc_fee = dex.swap_paths['BTC/USDT']['fee']\n\n    print(btc_price)\n    print(btc_fee)\n\n    # Get the lowest price path: best for BUY orders\n    buy_price = np.min(btc_price)\n\n    # Get the highest price path: best for SELL orders\n    sell_price = np.max(btc_price)\n\n    # Calculate the spread between the two paths\n    buy_sell_spread = (sell_price / buy_price - 1) * 100\n    print(f'Buy-Sell price spread: {buy_sell_spread}%')\n"
  },
  {
    "path": "execution/WhackAMoleBotV1.json",
    "content": "{\n  \"abi\": [\n    {\n      \"inputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"TradeFailed\",\n      \"type\": \"error\"\n    },\n    {\n      \"inputs\": [],\n      \"name\": \"Unauthorized\",\n      \"type\": \"error\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address[]\",\n          \"name\": \"tokens\",\n          \"type\": \"address[]\"\n        },\n        {\n          \"internalType\": \"address[]\",\n          \"name\": \"protocols\",\n          \"type\": \"address[]\"\n        }\n      ],\n      \"name\": \"approveHandlers\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"internalType\": \"address[]\",\n          \"name\": \"tokens\",\n          \"type\": \"address[]\"\n        }\n      ],\n      \"name\": \"recoverTokens\",\n      \"outputs\": [],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"protocol\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"handler\",\n              \"type\": \"address\"\n            },\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\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct WhackAMoleBotV1.SwapParams[]\",\n          \"name\": \"paramsArray\",\n          \"type\": \"tuple[]\"\n        },\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"minAmountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"name\": \"whack\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"payable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"bytecode\": {\n    \"object\": \"0x60a060405234801561001057600080fd5b5033608052608051610f0d61003060003960006102fa0152610f0d6000f3fe6080604052600436106100345760003560e01c80639c832f9314610039578063bc2078fb1461004e578063c0f757c014610061575b600080fd5b61004c610047366004610a9e565b610086565b005b61004c61005c366004610ae0565b61016d565b61007461006f366004610b4c565b61020f565b60405190815260200160405180910390f35b61008e6102ef565b8060005b818110156101675760008484838181106100ae576100ae610bc7565b90506020020160208101906100c39190610bf9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915061015e9033906001600160a01b038416906370a0823190602401602060405180830381865afa158015610129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014d9190610c14565b6001600160a01b0384169190610353565b50600101610092565b50505050565b600019838260005b8281101561020557600088888381811061019157610191610bc7565b90506020020160208101906101a69190610bf9565b905060005b838110156101fb5760008888838181106101c7576101c7610bc7565b90506020020160208101906101dc9190610bf9565b90506101f26001600160a01b0384168289610401565b506001016101ab565b5050600101610175565b5050505050505050565b60006102196102ef565b600083815b818110156102ab57600087878381811061023a5761023a610bc7565b905060c002018036038101906102509190610c9d565b905083600003610266578060a00151935061026e565b60a081018490525b805160ff1660000361028a5761028381610554565b93506102a2565b805160ff166001036102a25761029f81610696565b93505b5060010161021e565b50838210156102e6576040517f2d8ef0cf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50949350505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610351576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6040516001600160a01b0383166024820152604481018290526103fc9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526107c3565b505050565b80158061049457506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561046e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104929190610c14565b155b61050b5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b6040516001600160a01b0383166024820152604481018290526103fc9084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401610398565b604080516002808252606080830184526000939092919060208301908036833701905050905082604001518160008151811061059257610592610bc7565b60200260200101906001600160a01b031690816001600160a01b0316815250508260600151816001815181106105ca576105ca610bc7565b60200260200101906001600160a01b031690816001600160a01b031681525050600083602001516001600160a01b03166338ed17398560a0015160008530426040518663ffffffff1660e01b8152600401610629959493929190610d2b565b6000604051808303816000875af1158015610648573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106709190810190610d9c565b90508060018151811061068557610685610bc7565b602002602001015192505050919050565b6040805161010081018252828201516001600160a01b0390811682526060808501518216602080850191825260808088015162ffffff908116878901908152309588019586524292880192835260a0808b0151908901908152600060c08a0181815260e08b01828152968d01519b517f414bf3890000000000000000000000000000000000000000000000000000000081528b518b16600482015297518a1660248901529251909316604487015295518716606486015291516084850152935160a48401525160c483015251831660e482015290939091169063414bf38990610104016020604051808303816000875af1158015610798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107bc9190610c14565b9392505050565b6000610818826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166108ab9092919063ffffffff16565b90508051600014806108395750808060200190518101906108399190610e42565b6103fc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610502565b60606108ba84846000856108c2565b949350505050565b60608247101561093a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610502565b600080866001600160a01b031685876040516109569190610e88565b60006040518083038185875af1925050503d8060008114610993576040519150601f19603f3d011682016040523d82523d6000602084013e610998565b606091505b50915091506109a9878383876109b4565b979650505050505050565b60608315610a23578251600003610a1c576001600160a01b0385163b610a1c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610502565b50816108ba565b6108ba8383815115610a385781518083602001fd5b8060405162461bcd60e51b81526004016105029190610ea4565b60008083601f840112610a6457600080fd5b50813567ffffffffffffffff811115610a7c57600080fd5b6020830191508360208260051b8501011115610a9757600080fd5b9250929050565b60008060208385031215610ab157600080fd5b823567ffffffffffffffff811115610ac857600080fd5b610ad485828601610a52565b90969095509350505050565b60008060008060408587031215610af657600080fd5b843567ffffffffffffffff80821115610b0e57600080fd5b610b1a88838901610a52565b90965094506020870135915080821115610b3357600080fd5b50610b4087828801610a52565b95989497509550505050565b600080600060408486031215610b6157600080fd5b833567ffffffffffffffff80821115610b7957600080fd5b818601915086601f830112610b8d57600080fd5b813581811115610b9c57600080fd5b87602060c083028501011115610bb157600080fd5b6020928301989097509590910135949350505050565b634e487b7160e01b600052603260045260246000fd5b80356001600160a01b0381168114610bf457600080fd5b919050565b600060208284031215610c0b57600080fd5b6107bc82610bdd565b600060208284031215610c2657600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715610c6657610c66610c2d565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610c9557610c95610c2d565b604052919050565b600060c08284031215610caf57600080fd5b610cb7610c43565b823560ff81168114610cc857600080fd5b8152610cd660208401610bdd565b6020820152610ce760408401610bdd565b6040820152610cf860608401610bdd565b6060820152608083013562ffffff81168114610d1357600080fd5b608082015260a0928301359281019290925250919050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015610d7b5784516001600160a01b031683529383019391830191600101610d56565b50506001600160a01b03969096166060850152505050608001529392505050565b60006020808385031215610daf57600080fd5b825167ffffffffffffffff80821115610dc757600080fd5b818501915085601f830112610ddb57600080fd5b815181811115610ded57610ded610c2d565b8060051b9150610dfe848301610c6c565b8181529183018401918481019088841115610e1857600080fd5b938501935b83851015610e3657845182529385019390850190610e1d565b98975050505050505050565b600060208284031215610e5457600080fd5b815180151581146107bc57600080fd5b60005b83811015610e7f578181015183820152602001610e67565b50506000910152565b60008251610e9a818460208701610e64565b9190910192915050565b6020815260008251806020840152610ec3816040850160208701610e64565b601f01601f1916919091016040019291505056fea2646970667358221220e75668af077dbec1fec4d2e8edeec37cd59855fc788594733b9b89d21e48939064736f6c63430008140033\",\n    \"sourceMap\": \"433:3979:25:-:0;;;763:49;;;;;;;;;-1:-1:-1;795:10:25;787:18;;433:3979;;;;;;;;;;;;\",\n    \"linkReferences\": {}\n  },\n  \"deployedBytecode\": {\n    \"object\": \"0x6080604052600436106100345760003560e01c80639c832f9314610039578063bc2078fb1461004e578063c0f757c014610061575b600080fd5b61004c610047366004610a9e565b610086565b005b61004c61005c366004610ae0565b61016d565b61007461006f366004610b4c565b61020f565b60405190815260200160405180910390f35b61008e6102ef565b8060005b818110156101675760008484838181106100ae576100ae610bc7565b90506020020160208101906100c39190610bf9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915061015e9033906001600160a01b038416906370a0823190602401602060405180830381865afa158015610129573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014d9190610c14565b6001600160a01b0384169190610353565b50600101610092565b50505050565b600019838260005b8281101561020557600088888381811061019157610191610bc7565b90506020020160208101906101a69190610bf9565b905060005b838110156101fb5760008888838181106101c7576101c7610bc7565b90506020020160208101906101dc9190610bf9565b90506101f26001600160a01b0384168289610401565b506001016101ab565b5050600101610175565b5050505050505050565b60006102196102ef565b600083815b818110156102ab57600087878381811061023a5761023a610bc7565b905060c002018036038101906102509190610c9d565b905083600003610266578060a00151935061026e565b60a081018490525b805160ff1660000361028a5761028381610554565b93506102a2565b805160ff166001036102a25761029f81610696565b93505b5060010161021e565b50838210156102e6576040517f2d8ef0cf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50949350505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610351576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6040516001600160a01b0383166024820152604481018290526103fc9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526107c3565b505050565b80158061049457506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561046e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104929190610c14565b155b61050b5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b6040516001600160a01b0383166024820152604481018290526103fc9084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401610398565b604080516002808252606080830184526000939092919060208301908036833701905050905082604001518160008151811061059257610592610bc7565b60200260200101906001600160a01b031690816001600160a01b0316815250508260600151816001815181106105ca576105ca610bc7565b60200260200101906001600160a01b031690816001600160a01b031681525050600083602001516001600160a01b03166338ed17398560a0015160008530426040518663ffffffff1660e01b8152600401610629959493929190610d2b565b6000604051808303816000875af1158015610648573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106709190810190610d9c565b90508060018151811061068557610685610bc7565b602002602001015192505050919050565b6040805161010081018252828201516001600160a01b0390811682526060808501518216602080850191825260808088015162ffffff908116878901908152309588019586524292880192835260a0808b0151908901908152600060c08a0181815260e08b01828152968d01519b517f414bf3890000000000000000000000000000000000000000000000000000000081528b518b16600482015297518a1660248901529251909316604487015295518716606486015291516084850152935160a48401525160c483015251831660e482015290939091169063414bf38990610104016020604051808303816000875af1158015610798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107bc9190610c14565b9392505050565b6000610818826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166108ab9092919063ffffffff16565b90508051600014806108395750808060200190518101906108399190610e42565b6103fc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610502565b60606108ba84846000856108c2565b949350505050565b60608247101561093a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610502565b600080866001600160a01b031685876040516109569190610e88565b60006040518083038185875af1925050503d8060008114610993576040519150601f19603f3d011682016040523d82523d6000602084013e610998565b606091505b50915091506109a9878383876109b4565b979650505050505050565b60608315610a23578251600003610a1c576001600160a01b0385163b610a1c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610502565b50816108ba565b6108ba8383815115610a385781518083602001fd5b8060405162461bcd60e51b81526004016105029190610ea4565b60008083601f840112610a6457600080fd5b50813567ffffffffffffffff811115610a7c57600080fd5b6020830191508360208260051b8501011115610a9757600080fd5b9250929050565b60008060208385031215610ab157600080fd5b823567ffffffffffffffff811115610ac857600080fd5b610ad485828601610a52565b90969095509350505050565b60008060008060408587031215610af657600080fd5b843567ffffffffffffffff80821115610b0e57600080fd5b610b1a88838901610a52565b90965094506020870135915080821115610b3357600080fd5b50610b4087828801610a52565b95989497509550505050565b600080600060408486031215610b6157600080fd5b833567ffffffffffffffff80821115610b7957600080fd5b818601915086601f830112610b8d57600080fd5b813581811115610b9c57600080fd5b87602060c083028501011115610bb157600080fd5b6020928301989097509590910135949350505050565b634e487b7160e01b600052603260045260246000fd5b80356001600160a01b0381168114610bf457600080fd5b919050565b600060208284031215610c0b57600080fd5b6107bc82610bdd565b600060208284031215610c2657600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715610c6657610c66610c2d565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610c9557610c95610c2d565b604052919050565b600060c08284031215610caf57600080fd5b610cb7610c43565b823560ff81168114610cc857600080fd5b8152610cd660208401610bdd565b6020820152610ce760408401610bdd565b6040820152610cf860608401610bdd565b6060820152608083013562ffffff81168114610d1357600080fd5b608082015260a0928301359281019290925250919050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015610d7b5784516001600160a01b031683529383019391830191600101610d56565b50506001600160a01b03969096166060850152505050608001529392505050565b60006020808385031215610daf57600080fd5b825167ffffffffffffffff80821115610dc757600080fd5b818501915085601f830112610ddb57600080fd5b815181811115610ded57610ded610c2d565b8060051b9150610dfe848301610c6c565b8181529183018401918481019088841115610e1857600080fd5b938501935b83851015610e3657845182529385019390850190610e1d565b98975050505050505050565b600060208284031215610e5457600080fd5b815180151581146107bc57600080fd5b60005b83811015610e7f578181015183820152602001610e67565b50506000910152565b60008251610e9a818460208701610e64565b9190910192915050565b6020815260008251806020840152610ec3816040850160208701610e64565b601f01601f1916919091016040019291505056fea2646970667358221220e75668af077dbec1fec4d2e8edeec37cd59855fc788594733b9b89d21e48939064736f6c63430008140033\",\n    \"sourceMap\": \"433:3979:25:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1024:404;;;;;;:::i;:::-;;:::i;:::-;;1476:779;;;;;;:::i;:::-;;:::i;2323:876::-;;;;;;:::i;:::-;;:::i;:::-;;;2480:25:33;;;2468:2;2453:18;2323:876:25;;;;;;;1024:404;849:13;:11;:13::i;:::-;1123:6;1109:11:::1;1147:275;1164:6;1160:1;:10;1147:275;;;1188:13;1204:6;;1211:1;1204:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1299:38;::::0;;;;1331:4:::1;1299:38;::::0;::::1;3243:74:33::0;1188:25:25;;-1:-1:-1;1227:124:25::1;::::0;1271:10:::1;::::0;-1:-1:-1;;;;;1299:23:25;::::1;::::0;::::1;::::0;3216:18:33;;1299:38:25::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;1227:26:25;::::1;::::0;:124;:26:::1;:124::i;:::-;-1:-1:-1::0;1394:3:25::1;;1147:275;;;;1099:329;1024:404:::0;;:::o;1476:779::-;-1:-1:-1;;1788:6:25;1834:9;1726:11;1861:388;1878:12;1874:1;:16;1861:388;;;1908:12;1930:6;;1937:1;1930:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1908:32;;1959:6;1954:225;1971:15;1967:1;:19;1954:225;;;2008:16;2027:9;;2037:1;2027:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2008:31;-1:-1:-1;2057:35:25;-1:-1:-1;;;;;2057:17:25;;2008:31;2085:6;2057:17;:35::i;:::-;-1:-1:-1;2143:3:25;;1954:225;;;-1:-1:-1;;2221:3:25;;1861:388;;;;1595:660;;;1476:779;;;;:::o;2323:876::-;2451:7;849:13;:11;:13::i;:::-;2470:17:::1;2525:11:::0;2470:17;2554:527:::1;2574:17;2570:1;:21;2554:527;;;2609:24;2636:11;;2648:1;2636:14;;;;;;;:::i;:::-;;;;;;2609:41;;;;;;;;;;:::i;:::-;;;2669:9;2682:1;2669:14:::0;2665:142:::1;;2715:6;:13;;;2703:25;;2665:142;;;2767:13;::::0;::::1;:25:::0;;;2665:142:::1;2825:15:::0;;:20:::1;;:15;:20:::0;2821:190:::1;;2877:21;2891:6;2877:13;:21::i;:::-;2865:33;;2821:190;;;2923:15:::0;;:20:::1;;2942:1;2923:20:::0;2919:92:::1;;2975:21;2989:6;2975:13;:21::i;:::-;2963:33;;2919:92;-1:-1:-1::0;3053:3:25::1;;2554:527;;;;3107:12;3095:9;:24;3091:75;;;3142:13;;;;;;;;;;;;;;3091:75;-1:-1:-1::0;3183:9:25;2323:876;-1:-1:-1;;;;2323:876:25:o;886:132::-;945:10;-1:-1:-1;;;;;959:5:25;945:19;;941:71;;987:14;;;;;;;;;;;;;;941:71;886:132::o;941:175:21:-;1050:58;;-1:-1:-1;;;;;5272:55:33;;1050:58:21;;;5254:74:33;5344:18;;;5337:34;;;1023:86:21;;1043:5;;1073:23;;5227:18:33;;1050:58:21;;;;-1:-1:-1;;1050:58:21;;;;;;;;;;;;;;;;;;;;;;;;;;;1023:19;:86::i;:::-;941:175;;;:::o;1818:573::-;2143:10;;;2142:62;;-1:-1:-1;2159:39:21;;;;;2183:4;2159:39;;;5617:34:33;-1:-1:-1;;;;;5687:15:33;;;5667:18;;;5660:43;2159:15:21;;;;;5529:18:33;;2159:39:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;2142:62;2121:163;;;;-1:-1:-1;;;2121:163:21;;5916:2:33;2121:163:21;;;5898:21:33;5955:2;5935:18;;;5928:30;5994:34;5974:18;;;5967:62;6065:24;6045:18;;;6038:52;6107:19;;2121:163:21;;;;;;;;;2321:62;;-1:-1:-1;;;;;5272:55:33;;2321:62:21;;;5254:74:33;5344:18;;;5337:34;;;2294:90:21;;2314:5;;2344:22;;5227:18:33;;2321:62:21;5080:297:33;3225:523:25;3373:16;;;3387:1;3373:16;;;3335:21;3373:16;;;;;3306:17;;3335:21;;3373:16;3387:1;3373:16;;;;;;;;;;-1:-1:-1;3373:16:25;3366:23;;3409:6;:14;;;3399:4;3404:1;3399:7;;;;;;;;:::i;:::-;;;;;;:24;-1:-1:-1;;;;;3399:24:25;;;-1:-1:-1;;;;;3399:24:25;;;;;3443:6;:15;;;3433:4;3438:1;3433:7;;;;;;;;:::i;:::-;;;;;;:25;-1:-1:-1;;;;;3433:25:25;;;-1:-1:-1;;;;;3433:25:25;;;;;3469:21;3510:6;:14;;;-1:-1:-1;;;;;3493:70:25;;3581:6;:13;;;3612:1;3631:4;3661;3684:15;3493:220;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3493:220:25;;;;;;;;;;;;:::i;:::-;3469:244;;3731:7;3739:1;3731:10;;;;;;;;:::i;:::-;;;;;;;3724:17;;;;3225:523;;;:::o;3774:636::-;3941:381;;;;;;;;4016:14;;;;-1:-1:-1;;;;;3941:381:25;;;;;4058:15;;;;;3941:381;;;;;;;;;4096:10;;;;;3941:381;;;;;;;;;;4143:4;3941:381;;;;;;4176:15;3941:381;;;;;;;4219:13;;;;3941:381;;;;;;3855:17;3941:381;;;;;;;;;;;;4357:14;;;;4345:58;;;;;8421:13:33;;8417:22;;4345:58:25;;;8399:41:33;8482:24;;8478:33;;8456:20;;;8449:63;8554:24;;8550:39;;;8528:20;;;8521:69;8632:24;;8628:33;;8606:20;;;8599:63;8700:24;;8678:20;;;8671:54;8763:24;;8741:20;;;8734:54;8826:24;8804:20;;;8797:54;8893:24;8889:33;;8867:20;;;8860:63;3855:17:25;;4345:44;;;;;;8310:19:33;;4345:58:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4333:70;3774:636;-1:-1:-1;;;3774:636:25:o;5173:642:21:-;5592:23;5618:69;5646:4;5618:69;;;;;;;;;;;;;;;;;5626:5;-1:-1:-1;;;;;5618:27:21;;;:69;;;;;:::i;:::-;5592:95;;5705:10;:17;5726:1;5705:22;:56;;;;5742:10;5731:30;;;;;;;;;;;;:::i;:::-;5697:111;;;;-1:-1:-1;;;5697:111:21;;9418:2:33;5697:111:21;;;9400:21:33;9457:2;9437:18;;;9430:30;9496:34;9476:18;;;9469:62;9567:12;9547:18;;;9540:40;9597:19;;5697:111:21;9216:406:33;4108:223:22;4241:12;4272:52;4294:6;4302:4;4308:1;4311:12;4272:21;:52::i;:::-;4265:59;4108:223;-1:-1:-1;;;;4108:223:22:o;5165:446::-;5330:12;5387:5;5362:21;:30;;5354:81;;;;-1:-1:-1;;;5354:81:22;;9829:2:33;5354:81:22;;;9811:21:33;9868:2;9848:18;;;9841:30;9907:34;9887:18;;;9880:62;9978:8;9958:18;;;9951:36;10004:19;;5354:81:22;9627:402:33;5354:81:22;5446:12;5460:23;5487:6;-1:-1:-1;;;;;5487:11:22;5506:5;5513:4;5487:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5445:73;;;;5535:69;5562:6;5570:7;5579:10;5591:12;5535:26;:69::i;:::-;5528:76;5165:446;-1:-1:-1;;;;;;;5165:446:22:o;7671:628::-;7851:12;7879:7;7875:418;;;7906:10;:17;7927:1;7906:22;7902:286;;-1:-1:-1;;;;;1702:19:22;;;8113:60;;;;-1:-1:-1;;;8113:60:22;;10783:2:33;8113:60:22;;;10765:21:33;10822:2;10802:18;;;10795:30;10861:31;10841:18;;;10834:59;10910:18;;8113:60:22;10581:353:33;8113:60:22;-1:-1:-1;8208:10:22;8201:17;;7875:418;8249:33;8257:10;8269:12;8980:17;;:21;8976:379;;9208:10;9202:17;9264:15;9251:10;9247:2;9243:19;9236:44;8976:379;9331:12;9324:20;;-1:-1:-1;;;9324:20:22;;;;;;;;:::i;14:367:33:-;77:8;87:6;141:3;134:4;126:6;122:17;118:27;108:55;;159:1;156;149:12;108:55;-1:-1:-1;182:20:33;;225:18;214:30;;211:50;;;257:1;254;247:12;211:50;294:4;286:6;282:17;270:29;;354:3;347:4;337:6;334:1;330:14;322:6;318:27;314:38;311:47;308:67;;;371:1;368;361:12;308:67;14:367;;;;;:::o;386:437::-;472:6;480;533:2;521:9;512:7;508:23;504:32;501:52;;;549:1;546;539:12;501:52;589:9;576:23;622:18;614:6;611:30;608:50;;;654:1;651;644:12;608:50;693:70;755:7;746:6;735:9;731:22;693:70;:::i;:::-;782:8;;667:96;;-1:-1:-1;386:437:33;-1:-1:-1;;;;386:437:33:o;828:773::-;950:6;958;966;974;1027:2;1015:9;1006:7;1002:23;998:32;995:52;;;1043:1;1040;1033:12;995:52;1083:9;1070:23;1112:18;1153:2;1145:6;1142:14;1139:34;;;1169:1;1166;1159:12;1139:34;1208:70;1270:7;1261:6;1250:9;1246:22;1208:70;:::i;:::-;1297:8;;-1:-1:-1;1182:96:33;-1:-1:-1;1385:2:33;1370:18;;1357:32;;-1:-1:-1;1401:16:33;;;1398:36;;;1430:1;1427;1420:12;1398:36;;1469:72;1533:7;1522:8;1511:9;1507:24;1469:72;:::i;:::-;828:773;;;;-1:-1:-1;1560:8:33;-1:-1:-1;;;;828:773:33:o;1606:723::-;1732:6;1740;1748;1801:2;1789:9;1780:7;1776:23;1772:32;1769:52;;;1817:1;1814;1807:12;1769:52;1857:9;1844:23;1886:18;1927:2;1919:6;1916:14;1913:34;;;1943:1;1940;1933:12;1913:34;1981:6;1970:9;1966:22;1956:32;;2026:7;2019:4;2015:2;2011:13;2007:27;1997:55;;2048:1;2045;2038:12;1997:55;2088:2;2075:16;2114:2;2106:6;2103:14;2100:34;;;2130:1;2127;2120:12;2100:34;2188:7;2181:4;2173;2165:6;2161:17;2157:2;2153:26;2149:37;2146:50;2143:70;;;2209:1;2206;2199:12;2143:70;2240:4;2232:13;;;;2264:6;;-1:-1:-1;2302:20:33;;;;2289:34;;1606:723;-1:-1:-1;;;;1606:723:33:o;2516:184::-;-1:-1:-1;;;2565:1:33;2558:88;2665:4;2662:1;2655:15;2689:4;2686:1;2679:15;2705:196;2773:20;;-1:-1:-1;;;;;2822:54:33;;2812:65;;2802:93;;2891:1;2888;2881:12;2802:93;2705:196;;;:::o;2906:186::-;2965:6;3018:2;3006:9;2997:7;2993:23;2989:32;2986:52;;;3034:1;3031;3024:12;2986:52;3057:29;3076:9;3057:29;:::i;3328:184::-;3398:6;3451:2;3439:9;3430:7;3426:23;3422:32;3419:52;;;3467:1;3464;3457:12;3419:52;-1:-1:-1;3490:16:33;;3328:184;-1:-1:-1;3328:184:33:o;3517:::-;-1:-1:-1;;;3566:1:33;3559:88;3666:4;3663:1;3656:15;3690:4;3687:1;3680:15;3706:252;3778:2;3772:9;3820:3;3808:16;;3854:18;3839:34;;3875:22;;;3836:62;3833:88;;;3901:18;;:::i;:::-;3937:2;3930:22;3706:252;:::o;3963:275::-;4034:2;4028:9;4099:2;4080:13;;-1:-1:-1;;4076:27:33;4064:40;;4134:18;4119:34;;4155:22;;;4116:62;4113:88;;;4181:18;;:::i;:::-;4217:2;4210:22;3963:275;;-1:-1:-1;3963:275:33:o;4243:832::-;4331:6;4384:3;4372:9;4363:7;4359:23;4355:33;4352:53;;;4401:1;4398;4391:12;4352:53;4427:22;;:::i;:::-;4486:9;4473:23;4540:4;4531:7;4527:18;4518:7;4515:31;4505:59;;4560:1;4557;4550:12;4505:59;4573:22;;4627:38;4661:2;4646:18;;4627:38;:::i;:::-;4622:2;4615:5;4611:14;4604:62;4698:38;4732:2;4721:9;4717:18;4698:38;:::i;:::-;4693:2;4686:5;4682:14;4675:62;4769:38;4803:2;4792:9;4788:18;4769:38;:::i;:::-;4764:2;4757:5;4753:14;4746:62;4860:3;4849:9;4845:19;4832:33;4909:8;4900:7;4896:22;4887:7;4884:35;4874:63;;4933:1;4930;4923:12;4874:63;4964:3;4953:15;;4946:32;5039:3;5024:19;;;5011:33;4994:15;;;4987:58;;;;-1:-1:-1;4957:5:33;4243:832;-1:-1:-1;4243:832:33:o;6137:1026::-;6399:4;6447:3;6436:9;6432:19;6478:6;6467:9;6460:25;6504:2;6542:6;6537:2;6526:9;6522:18;6515:34;6585:3;6580:2;6569:9;6565:18;6558:31;6609:6;6644;6638:13;6675:6;6667;6660:22;6713:3;6702:9;6698:19;6691:26;;6752:2;6744:6;6740:15;6726:29;;6773:1;6783:218;6797:6;6794:1;6791:13;6783:218;;;6862:13;;-1:-1:-1;;;;;6858:62:33;6846:75;;6976:15;;;;6941:12;;;;6819:1;6812:9;6783:218;;;-1:-1:-1;;;;;;;7057:55:33;;;;7052:2;7037:18;;7030:83;-1:-1:-1;;;7144:3:33;7129:19;7122:35;7018:3;6137:1026;-1:-1:-1;;;6137:1026:33:o;7168:936::-;7263:6;7294:2;7337;7325:9;7316:7;7312:23;7308:32;7305:52;;;7353:1;7350;7343:12;7305:52;7386:9;7380:16;7415:18;7456:2;7448:6;7445:14;7442:34;;;7472:1;7469;7462:12;7442:34;7510:6;7499:9;7495:22;7485:32;;7555:7;7548:4;7544:2;7540:13;7536:27;7526:55;;7577:1;7574;7567:12;7526:55;7606:2;7600:9;7628:2;7624;7621:10;7618:36;;;7634:18;;:::i;:::-;7680:2;7677:1;7673:10;7663:20;;7703:28;7727:2;7723;7719:11;7703:28;:::i;:::-;7765:15;;;7835:11;;;7831:20;;;7796:12;;;;7863:19;;;7860:39;;;7895:1;7892;7885:12;7860:39;7919:11;;;;7939:135;7955:6;7950:3;7947:15;7939:135;;;8021:10;;8009:23;;7972:12;;;;8052;;;;7939:135;;;8093:5;7168:936;-1:-1:-1;;;;;;;;7168:936:33:o;8934:277::-;9001:6;9054:2;9042:9;9033:7;9029:23;9025:32;9022:52;;;9070:1;9067;9060:12;9022:52;9102:9;9096:16;9155:5;9148:13;9141:21;9134:5;9131:32;9121:60;;9177:1;9174;9167:12;10034:250;10119:1;10129:113;10143:6;10140:1;10137:13;10129:113;;;10219:11;;;10213:18;10200:11;;;10193:39;10165:2;10158:10;10129:113;;;-1:-1:-1;;10276:1:33;10258:16;;10251:27;10034:250::o;10289:287::-;10418:3;10456:6;10450:13;10472:66;10531:6;10526:3;10519:4;10511:6;10507:17;10472:66;:::i;:::-;10554:16;;;;;10289:287;-1:-1:-1;;10289:287:33:o;10939:396::-;11088:2;11077:9;11070:21;11051:4;11120:6;11114:13;11163:6;11158:2;11147:9;11143:18;11136:34;11179:79;11251:6;11246:2;11235:9;11231:18;11226:2;11218:6;11214:15;11179:79;:::i;:::-;11319:2;11298:15;-1:-1:-1;;11294:29:33;11279:45;;;;11326:2;11275:54;;10939:396;-1:-1:-1;;10939:396:33:o\",\n    \"linkReferences\": {},\n    \"immutableReferences\": {\n      \"30835\": [\n        {\n          \"start\": 762,\n          \"length\": 32\n        }\n      ]\n    }\n  },\n  \"methodIdentifiers\": {\n    \"approveHandlers(address[],address[])\": \"bc2078fb\",\n    \"recoverTokens(address[])\": \"9c832f93\",\n    \"whack((uint8,address,address,address,uint24,uint256)[],uint256)\": \"c0f757c0\"\n  },\n  \"rawMetadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.8.20+commit.a1b79de6\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"TradeFailed\\\",\\\"type\\\":\\\"error\\\"},{\\\"inputs\\\":[],\\\"name\\\":\\\"Unauthorized\\\",\\\"type\\\":\\\"error\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address[]\\\",\\\"name\\\":\\\"tokens\\\",\\\"type\\\":\\\"address[]\\\"},{\\\"internalType\\\":\\\"address[]\\\",\\\"name\\\":\\\"protocols\\\",\\\"type\\\":\\\"address[]\\\"}],\\\"name\\\":\\\"approveHandlers\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"internalType\\\":\\\"address[]\\\",\\\"name\\\":\\\"tokens\\\",\\\"type\\\":\\\"address[]\\\"}],\\\"name\\\":\\\"recoverTokens\\\",\\\"outputs\\\":[],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"protocol\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"handler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"internalType\\\":\\\"struct WhackAMoleBotV1.SwapParams[]\\\",\\\"name\\\":\\\"paramsArray\\\",\\\"type\\\":\\\"tuple[]\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"minAmountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"name\\\":\\\"whack\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"payable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"src/WhackAMoleBotV1.sol\\\":\\\"WhackAMoleBotV1\\\"},\\\"evmVersion\\\":\\\"paris\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\"},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":1000},\\\"remappings\\\":[\\\":ds-test/=lib/forge-std/lib/ds-test/src/\\\",\\\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\\\",\\\":forge-std/=lib/forge-std/src/\\\",\\\":openzeppelin-contracts/=lib/openzeppelin-contracts/\\\",\\\":openzeppelin/=lib/openzeppelin-contracts/contracts/\\\"]},\\\"sources\\\":{\\\"lib/openzeppelin-contracts/contracts/token/erc20/IERC20.sol\\\":{\\\"keccak256\\\":\\\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5\\\",\\\"dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53\\\"]},\\\"lib/openzeppelin-contracts/contracts/token/erc20/extensions/IERC20Permit.sol\\\":{\\\"keccak256\\\":\\\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://bc5b5dc12fbc4002f282eaa7a5f06d8310ed62c1c77c5770f6283e058454c39a\\\",\\\"dweb:/ipfs/Qme9rE2wS3yBuyJq9GgbmzbsBQsW2M2sVFqYYLw7bosGrv\\\"]},\\\"lib/openzeppelin-contracts/contracts/token/erc20/utils/SafeERC20.sol\\\":{\\\"keccak256\\\":\\\"0x909d608c2db6eb165ca178c81289a07ed2e118e444d0025b2a85c97d0b44a4fa\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://656cda26512ddd7373c2d5551c8fae759fc30f05b10f0fc2e738e9274199dbd4\\\",\\\"dweb:/ipfs/QmTSArSzQRFbQmHgq7U1PZXnsDFhvDZhKVu9CzMG4yo6Lx\\\"]},\\\"lib/openzeppelin-contracts/contracts/utils/Address.sol\\\":{\\\"keccak256\\\":\\\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://2455248c8ddd9cc6a7af76a13973cddf222072427e7b0e2a7d1aff345145e931\\\",\\\"dweb:/ipfs/QmfYjnjRbWqYpuxurqveE6HtzsY1Xx323J428AKQgtBJZm\\\"]},\\\"lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol\\\":{\\\"keccak256\\\":\\\"0x58b21219689909c4f8339af00813760337f7e2e7f169a97fe49e2896dcfb3b9a\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://ef8e012e946dec20e59f2d4446f4b44bb098f3fa8bac103b1b5112fff777447b\\\",\\\"dweb:/ipfs/QmVTooKWcLkJ9W68yNX4MgdrbAKiAXwuRN9A7f4NkdcdtQ\\\"]},\\\"src/WhackAMoleBotV1.sol\\\":{\\\"keccak256\\\":\\\"0x0eba973ac4a6a9f292beb8c0315d72a9491e28889a4dd4279e1f204d265d80c7\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://3f04c123d12ab9260b71cbf597e32730654c5b8faa026f062035245c1d861533\\\",\\\"dweb:/ipfs/QmRV6R2nc7ZUMQM6Cvudb7nSPJx85zXMyUAeDmzFLkMNcf\\\"]},\\\"src/protocols/uniswap/IUniswapV2Router.sol\\\":{\\\"keccak256\\\":\\\"0x2a86f62d96fd59a10d98e361056e3780cb1b94a758157b8f5d79ab865bb30a5c\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://d055709a7bdc57be7298bafd9a87c60071c06f68192aac1eeb3353615d03ee2b\\\",\\\"dweb:/ipfs/Qmdtojg2PJhdzQVtevYJDPG1ggTLmwJgHqcZ555eDC6xbq\\\"]},\\\"src/protocols/uniswap/IUniswapV3SwapRouter.sol\\\":{\\\"keccak256\\\":\\\"0x7ca2f2c38b3d4e2d9fc8fe55ab8ce482b448bb9618910a6ad4e18d8873b7389c\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://0f5d5e3aeb92e4e163a7dbb39dd66cbd9c9ca9714c48741530a14d57fbab5ed5\\\",\\\"dweb:/ipfs/QmaHyVhkBtoTm4VQHu4b3tXSpRDFmP6BDoqCseUbaKfVBT\\\"]}},\\\"version\\\":1}\",\n  \"metadata\": {\n    \"compiler\": {\n      \"version\": \"0.8.20+commit.a1b79de6\"\n    },\n    \"language\": \"Solidity\",\n    \"output\": {\n      \"abi\": [\n        {\n          \"inputs\": [],\n          \"stateMutability\": \"nonpayable\",\n          \"type\": \"constructor\"\n        },\n        {\n          \"inputs\": [],\n          \"type\": \"error\",\n          \"name\": \"TradeFailed\"\n        },\n        {\n          \"inputs\": [],\n          \"type\": \"error\",\n          \"name\": \"Unauthorized\"\n        },\n        {\n          \"inputs\": [\n            {\n              \"internalType\": \"address[]\",\n              \"name\": \"tokens\",\n              \"type\": \"address[]\"\n            },\n            {\n              \"internalType\": \"address[]\",\n              \"name\": \"protocols\",\n              \"type\": \"address[]\"\n            }\n          ],\n          \"stateMutability\": \"payable\",\n          \"type\": \"function\",\n          \"name\": \"approveHandlers\"\n        },\n        {\n          \"inputs\": [\n            {\n              \"internalType\": \"address[]\",\n              \"name\": \"tokens\",\n              \"type\": \"address[]\"\n            }\n          ],\n          \"stateMutability\": \"payable\",\n          \"type\": \"function\",\n          \"name\": \"recoverTokens\"\n        },\n        {\n          \"inputs\": [\n            {\n              \"internalType\": \"struct WhackAMoleBotV1.SwapParams[]\",\n              \"name\": \"paramsArray\",\n              \"type\": \"tuple[]\",\n              \"components\": [\n                {\n                  \"internalType\": \"uint8\",\n                  \"name\": \"protocol\",\n                  \"type\": \"uint8\"\n                },\n                {\n                  \"internalType\": \"address\",\n                  \"name\": \"handler\",\n                  \"type\": \"address\"\n                },\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\": \"uint256\",\n                  \"name\": \"amount\",\n                  \"type\": \"uint256\"\n                }\n              ]\n            },\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"minAmountOut\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"stateMutability\": \"payable\",\n          \"type\": \"function\",\n          \"name\": \"whack\",\n          \"outputs\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"\",\n              \"type\": \"uint256\"\n            }\n          ]\n        }\n      ],\n      \"devdoc\": {\n        \"kind\": \"dev\",\n        \"methods\": {},\n        \"version\": 1\n      },\n      \"userdoc\": {\n        \"kind\": \"user\",\n        \"methods\": {},\n        \"version\": 1\n      }\n    },\n    \"settings\": {\n      \"remappings\": [\n        \":ds-test/=lib/forge-std/lib/ds-test/src/\",\n        \":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\n        \":forge-std/=lib/forge-std/src/\",\n        \":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\n        \":openzeppelin/=lib/openzeppelin-contracts/contracts/\"\n      ],\n      \"optimizer\": {\n        \"enabled\": true,\n        \"runs\": 1000\n      },\n      \"metadata\": {\n        \"bytecodeHash\": \"ipfs\"\n      },\n      \"compilationTarget\": {\n        \"src/WhackAMoleBotV1.sol\": \"WhackAMoleBotV1\"\n      },\n      \"libraries\": {}\n    },\n    \"sources\": {\n      \"lib/openzeppelin-contracts/contracts/token/erc20/IERC20.sol\": {\n        \"keccak256\": \"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\n        \"urls\": [\n          \"bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5\",\n          \"dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"lib/openzeppelin-contracts/contracts/token/erc20/extensions/IERC20Permit.sol\": {\n        \"keccak256\": \"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\n        \"urls\": [\n          \"bzz-raw://bc5b5dc12fbc4002f282eaa7a5f06d8310ed62c1c77c5770f6283e058454c39a\",\n          \"dweb:/ipfs/Qme9rE2wS3yBuyJq9GgbmzbsBQsW2M2sVFqYYLw7bosGrv\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"lib/openzeppelin-contracts/contracts/token/erc20/utils/SafeERC20.sol\": {\n        \"keccak256\": \"0x909d608c2db6eb165ca178c81289a07ed2e118e444d0025b2a85c97d0b44a4fa\",\n        \"urls\": [\n          \"bzz-raw://656cda26512ddd7373c2d5551c8fae759fc30f05b10f0fc2e738e9274199dbd4\",\n          \"dweb:/ipfs/QmTSArSzQRFbQmHgq7U1PZXnsDFhvDZhKVu9CzMG4yo6Lx\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\n        \"keccak256\": \"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\n        \"urls\": [\n          \"bzz-raw://2455248c8ddd9cc6a7af76a13973cddf222072427e7b0e2a7d1aff345145e931\",\n          \"dweb:/ipfs/QmfYjnjRbWqYpuxurqveE6HtzsY1Xx323J428AKQgtBJZm\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol\": {\n        \"keccak256\": \"0x58b21219689909c4f8339af00813760337f7e2e7f169a97fe49e2896dcfb3b9a\",\n        \"urls\": [\n          \"bzz-raw://ef8e012e946dec20e59f2d4446f4b44bb098f3fa8bac103b1b5112fff777447b\",\n          \"dweb:/ipfs/QmVTooKWcLkJ9W68yNX4MgdrbAKiAXwuRN9A7f4NkdcdtQ\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/WhackAMoleBotV1.sol\": {\n        \"keccak256\": \"0x0eba973ac4a6a9f292beb8c0315d72a9491e28889a4dd4279e1f204d265d80c7\",\n        \"urls\": [\n          \"bzz-raw://3f04c123d12ab9260b71cbf597e32730654c5b8faa026f062035245c1d861533\",\n          \"dweb:/ipfs/QmRV6R2nc7ZUMQM6Cvudb7nSPJx85zXMyUAeDmzFLkMNcf\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/protocols/uniswap/IUniswapV2Router.sol\": {\n        \"keccak256\": \"0x2a86f62d96fd59a10d98e361056e3780cb1b94a758157b8f5d79ab865bb30a5c\",\n        \"urls\": [\n          \"bzz-raw://d055709a7bdc57be7298bafd9a87c60071c06f68192aac1eeb3353615d03ee2b\",\n          \"dweb:/ipfs/Qmdtojg2PJhdzQVtevYJDPG1ggTLmwJgHqcZ555eDC6xbq\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/protocols/uniswap/IUniswapV3SwapRouter.sol\": {\n        \"keccak256\": \"0x7ca2f2c38b3d4e2d9fc8fe55ab8ce482b448bb9618910a6ad4e18d8873b7389c\",\n        \"urls\": [\n          \"bzz-raw://0f5d5e3aeb92e4e163a7dbb39dd66cbd9c9ca9714c48741530a14d57fbab5ed5\",\n          \"dweb:/ipfs/QmaHyVhkBtoTm4VQHu4b3tXSpRDFmP6BDoqCseUbaKfVBT\"\n        ],\n        \"license\": \"MIT\"\n      }\n    },\n    \"version\": 1\n  },\n  \"ast\": {\n    \"absolutePath\": \"src/WhackAMoleBotV1.sol\",\n    \"id\": 31205,\n    \"exportedSymbols\": {\n      \"Address\": [\n        30227\n      ],\n      \"IERC20\": [\n        29521\n      ],\n      \"IERC20Permit\": [\n        32363\n      ],\n      \"ISwapRouter\": [\n        31832\n      ],\n      \"IUniswapV2Router\": [\n        31783\n      ],\n      \"SafeERC20\": [\n        29897\n      ],\n      \"SafeMath\": [\n        30539\n      ],\n      \"WhackAMoleBotV1\": [\n        31204\n      ]\n    },\n    \"nodeType\": \"SourceUnit\",\n    \"src\": \"32:4381:25\",\n    \"nodes\": [\n      {\n        \"id\": 30824,\n        \"nodeType\": \"PragmaDirective\",\n        \"src\": \"32:23:25\",\n        \"nodes\": [],\n        \"literals\": [\n          \"solidity\",\n          \"^\",\n          \"0.8\",\n          \".9\"\n        ]\n      },\n      {\n        \"id\": 30825,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"57:66:25\",\n        \"nodes\": [],\n        \"absolutePath\": \"lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol\",\n        \"file\": \"openzeppelin-contracts/contracts/utils/math/SafeMath.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 31205,\n        \"sourceUnit\": 30540,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30826,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"124:65:25\",\n        \"nodes\": [],\n        \"absolutePath\": \"lib/openzeppelin-contracts/contracts/token/erc20/IERC20.sol\",\n        \"file\": \"openzeppelin-contracts/contracts/token/erc20/IERC20.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 31205,\n        \"sourceUnit\": 29522,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30827,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"190:74:25\",\n        \"nodes\": [],\n        \"absolutePath\": \"lib/openzeppelin-contracts/contracts/token/erc20/utils/SafeERC20.sol\",\n        \"file\": \"openzeppelin-contracts/contracts/token/erc20/utils/SafeERC20.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 31205,\n        \"sourceUnit\": 29898,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30828,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"266:50:25\",\n        \"nodes\": [],\n        \"absolutePath\": \"src/protocols/uniswap/IUniswapV2Router.sol\",\n        \"file\": \"./protocols/uniswap/IUniswapV2Router.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 31205,\n        \"sourceUnit\": 31784,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30829,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"317:54:25\",\n        \"nodes\": [],\n        \"absolutePath\": \"src/protocols/uniswap/IUniswapV3SwapRouter.sol\",\n        \"file\": \"./protocols/uniswap/IUniswapV3SwapRouter.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 31205,\n        \"sourceUnit\": 31833,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 31204,\n        \"nodeType\": \"ContractDefinition\",\n        \"src\": \"433:3979:25\",\n        \"nodes\": [\n          {\n            \"id\": 30833,\n            \"nodeType\": \"UsingForDirective\",\n            \"src\": \"464:27:25\",\n            \"nodes\": [],\n            \"global\": false,\n            \"libraryName\": {\n              \"id\": 30830,\n              \"name\": \"SafeERC20\",\n              \"nameLocations\": [\n                \"470:9:25\"\n              ],\n              \"nodeType\": \"IdentifierPath\",\n              \"referencedDeclaration\": 29897,\n              \"src\": \"470:9:25\"\n            },\n            \"typeName\": {\n              \"id\": 30832,\n              \"nodeType\": \"UserDefinedTypeName\",\n              \"pathNode\": {\n                \"id\": 30831,\n                \"name\": \"IERC20\",\n                \"nameLocations\": [\n                  \"484:6:25\"\n                ],\n                \"nodeType\": \"IdentifierPath\",\n                \"referencedDeclaration\": 29521,\n                \"src\": \"484:6:25\"\n              },\n              \"referencedDeclaration\": 29521,\n              \"src\": \"484:6:25\",\n              \"typeDescriptions\": {\n                \"typeIdentifier\": \"t_contract$_IERC20_$29521\",\n                \"typeString\": \"contract IERC20\"\n              }\n            }\n          },\n          {\n            \"id\": 30835,\n            \"nodeType\": \"VariableDeclaration\",\n            \"src\": \"497:32:25\",\n            \"nodes\": [],\n            \"constant\": false,\n            \"mutability\": \"immutable\",\n            \"name\": \"owner\",\n            \"nameLocation\": \"524:5:25\",\n            \"scope\": 31204,\n            \"stateVariable\": true,\n            \"storageLocation\": \"default\",\n            \"typeDescriptions\": {\n              \"typeIdentifier\": \"t_address\",\n              \"typeString\": \"address\"\n            },\n            \"typeName\": {\n              \"id\": 30834,\n              \"name\": \"address\",\n              \"nodeType\": \"ElementaryTypeName\",\n              \"src\": \"497:7:25\",\n              \"stateMutability\": \"nonpayable\",\n              \"typeDescriptions\": {\n                \"typeIdentifier\": \"t_address\",\n                \"typeString\": \"address\"\n              }\n            },\n            \"visibility\": \"internal\"\n          },\n          {\n            \"id\": 30848,\n            \"nodeType\": \"StructDefinition\",\n            \"src\": \"536:169:25\",\n            \"nodes\": [],\n            \"canonicalName\": \"WhackAMoleBotV1.SwapParams\",\n            \"members\": [\n              {\n                \"constant\": false,\n                \"id\": 30837,\n                \"mutability\": \"mutable\",\n                \"name\": \"protocol\",\n                \"nameLocation\": \"570:8:25\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30848,\n                \"src\": \"564:14:25\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_uint8\",\n                  \"typeString\": \"uint8\"\n                },\n                \"typeName\": {\n                  \"id\": 30836,\n                  \"name\": \"uint8\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"564:5:25\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint8\",\n                    \"typeString\": \"uint8\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30839,\n                \"mutability\": \"mutable\",\n                \"name\": \"handler\",\n                \"nameLocation\": \"596:7:25\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30848,\n                \"src\": \"588:15:25\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_address\",\n                  \"typeString\": \"address\"\n                },\n                \"typeName\": {\n                  \"id\": 30838,\n                  \"name\": \"address\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"588:7:25\",\n                  \"stateMutability\": \"nonpayable\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_address\",\n                    \"typeString\": \"address\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30841,\n                \"mutability\": \"mutable\",\n                \"name\": \"tokenIn\",\n                \"nameLocation\": \"621:7:25\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30848,\n                \"src\": \"613:15:25\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_address\",\n                  \"typeString\": \"address\"\n                },\n                \"typeName\": {\n                  \"id\": 30840,\n                  \"name\": \"address\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"613:7:25\",\n                  \"stateMutability\": \"nonpayable\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_address\",\n                    \"typeString\": \"address\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30843,\n                \"mutability\": \"mutable\",\n                \"name\": \"tokenOut\",\n                \"nameLocation\": \"646:8:25\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30848,\n                \"src\": \"638:16:25\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_address\",\n                  \"typeString\": \"address\"\n                },\n                \"typeName\": {\n                  \"id\": 30842,\n                  \"name\": \"address\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"638:7:25\",\n                  \"stateMutability\": \"nonpayable\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_address\",\n                    \"typeString\": \"address\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30845,\n                \"mutability\": \"mutable\",\n                \"name\": \"fee\",\n                \"nameLocation\": \"671:3:25\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30848,\n                \"src\": \"664:10:25\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_uint24\",\n                  \"typeString\": \"uint24\"\n                },\n                \"typeName\": {\n                  \"id\": 30844,\n                  \"name\": \"uint24\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"664:6:25\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint24\",\n                    \"typeString\": \"uint24\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30847,\n                \"mutability\": \"mutable\",\n                \"name\": \"amount\",\n                \"nameLocation\": \"692:6:25\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30848,\n                \"src\": \"684:14:25\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_uint256\",\n                  \"typeString\": \"uint256\"\n                },\n                \"typeName\": {\n                  \"id\": 30846,\n                  \"name\": \"uint256\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"684:7:25\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              }\n            ],\n            \"name\": \"SwapParams\",\n            \"nameLocation\": \"543:10:25\",\n            \"scope\": 31204,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 30850,\n            \"nodeType\": \"ErrorDefinition\",\n            \"src\": \"711:21:25\",\n            \"nodes\": [],\n            \"errorSelector\": \"82b42900\",\n            \"name\": \"Unauthorized\",\n            \"nameLocation\": \"717:12:25\",\n            \"parameters\": {\n              \"id\": 30849,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"729:2:25\"\n            }\n          },\n          {\n            \"id\": 30852,\n            \"nodeType\": \"ErrorDefinition\",\n            \"src\": \"737:20:25\",\n            \"nodes\": [],\n            \"errorSelector\": \"2d8ef0cf\",\n            \"name\": \"TradeFailed\",\n            \"nameLocation\": \"743:11:25\",\n            \"parameters\": {\n              \"id\": 30851,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"754:2:25\"\n            }\n          },\n          {\n            \"id\": 30861,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"763:49:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30860,\n              \"nodeType\": \"Block\",\n              \"src\": \"777:35:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"expression\": {\n                    \"id\": 30858,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"id\": 30855,\n                      \"name\": \"owner\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30835,\n                      \"src\": \"787:5:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"expression\": {\n                        \"id\": 30856,\n                        \"name\": \"msg\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": -15,\n                        \"src\": \"795:3:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_magic_message\",\n                          \"typeString\": \"msg\"\n                        }\n                      },\n                      \"id\": 30857,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"799:6:25\",\n                      \"memberName\": \"sender\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"src\": \"795:10:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"src\": \"787:18:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_address\",\n                      \"typeString\": \"address\"\n                    }\n                  },\n                  \"id\": 30859,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"787:18:25\"\n                }\n              ]\n            },\n            \"implemented\": true,\n            \"kind\": \"constructor\",\n            \"modifiers\": [],\n            \"name\": \"\",\n            \"nameLocation\": \"-1:-1:-1\",\n            \"parameters\": {\n              \"id\": 30853,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"774:2:25\"\n            },\n            \"returnParameters\": {\n              \"id\": 30854,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"777:0:25\"\n            },\n            \"scope\": 31204,\n            \"stateMutability\": \"nonpayable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 30868,\n            \"nodeType\": \"ModifierDefinition\",\n            \"src\": \"818:62:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30867,\n              \"nodeType\": \"Block\",\n              \"src\": \"839:41:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"expression\": {\n                    \"arguments\": [],\n                    \"expression\": {\n                      \"argumentTypes\": [],\n                      \"id\": 30863,\n                      \"name\": \"_checkOwner\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30881,\n                      \"src\": \"849:11:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_function_internal_view$__$returns$__$\",\n                        \"typeString\": \"function () view\"\n                      }\n                    },\n                    \"id\": 30864,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"kind\": \"functionCall\",\n                    \"lValueRequested\": false,\n                    \"nameLocations\": [],\n                    \"names\": [],\n                    \"nodeType\": \"FunctionCall\",\n                    \"src\": \"849:13:25\",\n                    \"tryCall\": false,\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_tuple$__$\",\n                      \"typeString\": \"tuple()\"\n                    }\n                  },\n                  \"id\": 30865,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"849:13:25\"\n                },\n                {\n                  \"id\": 30866,\n                  \"nodeType\": \"PlaceholderStatement\",\n                  \"src\": \"872:1:25\"\n                }\n              ]\n            },\n            \"name\": \"onlyOwner\",\n            \"nameLocation\": \"827:9:25\",\n            \"parameters\": {\n              \"id\": 30862,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"836:2:25\"\n            },\n            \"virtual\": false,\n            \"visibility\": \"internal\"\n          },\n          {\n            \"id\": 30881,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"886:132:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30880,\n              \"nodeType\": \"Block\",\n              \"src\": \"931:87:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"condition\": {\n                    \"commonType\": {\n                      \"typeIdentifier\": \"t_address\",\n                      \"typeString\": \"address\"\n                    },\n                    \"id\": 30874,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftExpression\": {\n                      \"expression\": {\n                        \"id\": 30871,\n                        \"name\": \"msg\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": -15,\n                        \"src\": \"945:3:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_magic_message\",\n                          \"typeString\": \"msg\"\n                        }\n                      },\n                      \"id\": 30872,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"949:6:25\",\n                      \"memberName\": \"sender\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"src\": \"945:10:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"nodeType\": \"BinaryOperation\",\n                    \"operator\": \"!=\",\n                    \"rightExpression\": {\n                      \"id\": 30873,\n                      \"name\": \"owner\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30835,\n                      \"src\": \"959:5:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"src\": \"945:19:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_bool\",\n                      \"typeString\": \"bool\"\n                    }\n                  },\n                  \"id\": 30879,\n                  \"nodeType\": \"IfStatement\",\n                  \"src\": \"941:71:25\",\n                  \"trueBody\": {\n                    \"id\": 30878,\n                    \"nodeType\": \"Block\",\n                    \"src\": \"966:46:25\",\n                    \"statements\": [\n                      {\n                        \"errorCall\": {\n                          \"arguments\": [],\n                          \"expression\": {\n                            \"argumentTypes\": [],\n                            \"id\": 30875,\n                            \"name\": \"Unauthorized\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30850,\n                            \"src\": \"987:12:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_function_error_pure$__$returns$__$\",\n                              \"typeString\": \"function () pure\"\n                            }\n                          },\n                          \"id\": 30876,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"kind\": \"functionCall\",\n                          \"lValueRequested\": false,\n                          \"nameLocations\": [],\n                          \"names\": [],\n                          \"nodeType\": \"FunctionCall\",\n                          \"src\": \"987:14:25\",\n                          \"tryCall\": false,\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_tuple$__$\",\n                            \"typeString\": \"tuple()\"\n                          }\n                        },\n                        \"id\": 30877,\n                        \"nodeType\": \"RevertStatement\",\n                        \"src\": \"980:21:25\"\n                      }\n                    ]\n                  }\n                }\n              ]\n            },\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"_checkOwner\",\n            \"nameLocation\": \"895:11:25\",\n            \"parameters\": {\n              \"id\": 30869,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"906:2:25\"\n            },\n            \"returnParameters\": {\n              \"id\": 30870,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"931:0:25\"\n            },\n            \"scope\": 31204,\n            \"stateMutability\": \"view\",\n            \"virtual\": true,\n            \"visibility\": \"internal\"\n          },\n          {\n            \"id\": 30930,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"1024:404:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30929,\n              \"nodeType\": \"Block\",\n              \"src\": \"1099:329:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    30890\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30890,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"length\",\n                      \"nameLocation\": \"1114:6:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30929,\n                      \"src\": \"1109:11:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30889,\n                        \"name\": \"uint\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"1109:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30893,\n                  \"initialValue\": {\n                    \"expression\": {\n                      \"id\": 30891,\n                      \"name\": \"tokens\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30884,\n                      \"src\": \"1123:6:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                        \"typeString\": \"address[] calldata\"\n                      }\n                    },\n                    \"id\": 30892,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"memberLocation\": \"1130:6:25\",\n                    \"memberName\": \"length\",\n                    \"nodeType\": \"MemberAccess\",\n                    \"src\": \"1123:13:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"1109:27:25\"\n                },\n                {\n                  \"body\": {\n                    \"id\": 30927,\n                    \"nodeType\": \"Block\",\n                    \"src\": \"1174:248:25\",\n                    \"statements\": [\n                      {\n                        \"assignments\": [\n                          30901\n                        ],\n                        \"declarations\": [\n                          {\n                            \"constant\": false,\n                            \"id\": 30901,\n                            \"mutability\": \"mutable\",\n                            \"name\": \"token\",\n                            \"nameLocation\": \"1196:5:25\",\n                            \"nodeType\": \"VariableDeclaration\",\n                            \"scope\": 30927,\n                            \"src\": \"1188:13:25\",\n                            \"stateVariable\": false,\n                            \"storageLocation\": \"default\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            },\n                            \"typeName\": {\n                              \"id\": 30900,\n                              \"name\": \"address\",\n                              \"nodeType\": \"ElementaryTypeName\",\n                              \"src\": \"1188:7:25\",\n                              \"stateMutability\": \"nonpayable\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            },\n                            \"visibility\": \"internal\"\n                          }\n                        ],\n                        \"id\": 30905,\n                        \"initialValue\": {\n                          \"baseExpression\": {\n                            \"id\": 30902,\n                            \"name\": \"tokens\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30884,\n                            \"src\": \"1204:6:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                              \"typeString\": \"address[] calldata\"\n                            }\n                          },\n                          \"id\": 30904,\n                          \"indexExpression\": {\n                            \"id\": 30903,\n                            \"name\": \"i\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30895,\n                            \"src\": \"1211:1:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint256\",\n                              \"typeString\": \"uint256\"\n                            }\n                          },\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"nodeType\": \"IndexAccess\",\n                          \"src\": \"1204:9:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_address\",\n                            \"typeString\": \"address\"\n                          }\n                        },\n                        \"nodeType\": \"VariableDeclarationStatement\",\n                        \"src\": \"1188:25:25\"\n                      },\n                      {\n                        \"expression\": {\n                          \"arguments\": [\n                            {\n                              \"expression\": {\n                                \"id\": 30910,\n                                \"name\": \"msg\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": -15,\n                                \"src\": \"1271:3:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_magic_message\",\n                                  \"typeString\": \"msg\"\n                                }\n                              },\n                              \"id\": 30911,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"memberLocation\": \"1275:6:25\",\n                              \"memberName\": \"sender\",\n                              \"nodeType\": \"MemberAccess\",\n                              \"src\": \"1271:10:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            },\n                            {\n                              \"arguments\": [\n                                {\n                                  \"arguments\": [\n                                    {\n                                      \"id\": 30918,\n                                      \"name\": \"this\",\n                                      \"nodeType\": \"Identifier\",\n                                      \"overloadedDeclarations\": [],\n                                      \"referencedDeclaration\": -28,\n                                      \"src\": \"1331:4:25\",\n                                      \"typeDescriptions\": {\n                                        \"typeIdentifier\": \"t_contract$_WhackAMoleBotV1_$31204\",\n                                        \"typeString\": \"contract WhackAMoleBotV1\"\n                                      }\n                                    }\n                                  ],\n                                  \"expression\": {\n                                    \"argumentTypes\": [\n                                      {\n                                        \"typeIdentifier\": \"t_contract$_WhackAMoleBotV1_$31204\",\n                                        \"typeString\": \"contract WhackAMoleBotV1\"\n                                      }\n                                    ],\n                                    \"id\": 30917,\n                                    \"isConstant\": false,\n                                    \"isLValue\": false,\n                                    \"isPure\": true,\n                                    \"lValueRequested\": false,\n                                    \"nodeType\": \"ElementaryTypeNameExpression\",\n                                    \"src\": \"1323:7:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_type$_t_address_$\",\n                                      \"typeString\": \"type(address)\"\n                                    },\n                                    \"typeName\": {\n                                      \"id\": 30916,\n                                      \"name\": \"address\",\n                                      \"nodeType\": \"ElementaryTypeName\",\n                                      \"src\": \"1323:7:25\",\n                                      \"typeDescriptions\": {}\n                                    }\n                                  },\n                                  \"id\": 30919,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"kind\": \"typeConversion\",\n                                  \"lValueRequested\": false,\n                                  \"nameLocations\": [],\n                                  \"names\": [],\n                                  \"nodeType\": \"FunctionCall\",\n                                  \"src\": \"1323:13:25\",\n                                  \"tryCall\": false,\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_address\",\n                                    \"typeString\": \"address\"\n                                  }\n                                }\n                              ],\n                              \"expression\": {\n                                \"argumentTypes\": [\n                                  {\n                                    \"typeIdentifier\": \"t_address\",\n                                    \"typeString\": \"address\"\n                                  }\n                                ],\n                                \"expression\": {\n                                  \"arguments\": [\n                                    {\n                                      \"id\": 30913,\n                                      \"name\": \"token\",\n                                      \"nodeType\": \"Identifier\",\n                                      \"overloadedDeclarations\": [],\n                                      \"referencedDeclaration\": 30901,\n                                      \"src\": \"1306:5:25\",\n                                      \"typeDescriptions\": {\n                                        \"typeIdentifier\": \"t_address\",\n                                        \"typeString\": \"address\"\n                                      }\n                                    }\n                                  ],\n                                  \"expression\": {\n                                    \"argumentTypes\": [\n                                      {\n                                        \"typeIdentifier\": \"t_address\",\n                                        \"typeString\": \"address\"\n                                      }\n                                    ],\n                                    \"id\": 30912,\n                                    \"name\": \"IERC20\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 29521,\n                                    \"src\": \"1299:6:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_type$_t_contract$_IERC20_$29521_$\",\n                                      \"typeString\": \"type(contract IERC20)\"\n                                    }\n                                  },\n                                  \"id\": 30914,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"kind\": \"typeConversion\",\n                                  \"lValueRequested\": false,\n                                  \"nameLocations\": [],\n                                  \"names\": [],\n                                  \"nodeType\": \"FunctionCall\",\n                                  \"src\": \"1299:13:25\",\n                                  \"tryCall\": false,\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_contract$_IERC20_$29521\",\n                                    \"typeString\": \"contract IERC20\"\n                                  }\n                                },\n                                \"id\": 30915,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"memberLocation\": \"1313:9:25\",\n                                \"memberName\": \"balanceOf\",\n                                \"nodeType\": \"MemberAccess\",\n                                \"referencedDeclaration\": 29478,\n                                \"src\": \"1299:23:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_function_external_view$_t_address_$returns$_t_uint256_$\",\n                                  \"typeString\": \"function (address) view external returns (uint256)\"\n                                }\n                              },\n                              \"id\": 30920,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"kind\": \"functionCall\",\n                              \"lValueRequested\": false,\n                              \"nameLocations\": [],\n                              \"names\": [],\n                              \"nodeType\": \"FunctionCall\",\n                              \"src\": \"1299:38:25\",\n                              \"tryCall\": false,\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint256\",\n                                \"typeString\": \"uint256\"\n                              }\n                            }\n                          ],\n                          \"expression\": {\n                            \"argumentTypes\": [\n                              {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              },\n                              {\n                                \"typeIdentifier\": \"t_uint256\",\n                                \"typeString\": \"uint256\"\n                              }\n                            ],\n                            \"expression\": {\n                              \"arguments\": [\n                                {\n                                  \"id\": 30907,\n                                  \"name\": \"token\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30901,\n                                  \"src\": \"1234:5:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_address\",\n                                    \"typeString\": \"address\"\n                                  }\n                                }\n                              ],\n                              \"expression\": {\n                                \"argumentTypes\": [\n                                  {\n                                    \"typeIdentifier\": \"t_address\",\n                                    \"typeString\": \"address\"\n                                  }\n                                ],\n                                \"id\": 30906,\n                                \"name\": \"IERC20\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 29521,\n                                \"src\": \"1227:6:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_type$_t_contract$_IERC20_$29521_$\",\n                                  \"typeString\": \"type(contract IERC20)\"\n                                }\n                              },\n                              \"id\": 30908,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"kind\": \"typeConversion\",\n                              \"lValueRequested\": false,\n                              \"nameLocations\": [],\n                              \"names\": [],\n                              \"nodeType\": \"FunctionCall\",\n                              \"src\": \"1227:13:25\",\n                              \"tryCall\": false,\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_contract$_IERC20_$29521\",\n                                \"typeString\": \"contract IERC20\"\n                              }\n                            },\n                            \"id\": 30909,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"memberLocation\": \"1241:12:25\",\n                            \"memberName\": \"safeTransfer\",\n                            \"nodeType\": \"MemberAccess\",\n                            \"referencedDeclaration\": 29554,\n                            \"src\": \"1227:26:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_function_internal_nonpayable$_t_contract$_IERC20_$29521_$_t_address_$_t_uint256_$returns$__$attached_to$_t_contract$_IERC20_$29521_$\",\n                              \"typeString\": \"function (contract IERC20,address,uint256)\"\n                            }\n                          },\n                          \"id\": 30921,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"kind\": \"functionCall\",\n                          \"lValueRequested\": false,\n                          \"nameLocations\": [],\n                          \"names\": [],\n                          \"nodeType\": \"FunctionCall\",\n                          \"src\": \"1227:124:25\",\n                          \"tryCall\": false,\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_tuple$__$\",\n                            \"typeString\": \"tuple()\"\n                          }\n                        },\n                        \"id\": 30922,\n                        \"nodeType\": \"ExpressionStatement\",\n                        \"src\": \"1227:124:25\"\n                      },\n                      {\n                        \"id\": 30926,\n                        \"nodeType\": \"UncheckedBlock\",\n                        \"src\": \"1366:46:25\",\n                        \"statements\": [\n                          {\n                            \"expression\": {\n                              \"id\": 30924,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"UnaryOperation\",\n                              \"operator\": \"++\",\n                              \"prefix\": true,\n                              \"src\": \"1394:3:25\",\n                              \"subExpression\": {\n                                \"id\": 30923,\n                                \"name\": \"i\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30895,\n                                \"src\": \"1396:1:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint256\",\n                                \"typeString\": \"uint256\"\n                              }\n                            },\n                            \"id\": 30925,\n                            \"nodeType\": \"ExpressionStatement\",\n                            \"src\": \"1394:3:25\"\n                          }\n                        ]\n                      }\n                    ]\n                  },\n                  \"condition\": {\n                    \"commonType\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    },\n                    \"id\": 30899,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftExpression\": {\n                      \"id\": 30897,\n                      \"name\": \"i\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30895,\n                      \"src\": \"1160:1:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"BinaryOperation\",\n                    \"operator\": \"<\",\n                    \"rightExpression\": {\n                      \"id\": 30898,\n                      \"name\": \"length\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30890,\n                      \"src\": \"1164:6:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"1160:10:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_bool\",\n                      \"typeString\": \"bool\"\n                    }\n                  },\n                  \"id\": 30928,\n                  \"initializationExpression\": {\n                    \"assignments\": [\n                      30895\n                    ],\n                    \"declarations\": [\n                      {\n                        \"constant\": false,\n                        \"id\": 30895,\n                        \"mutability\": \"mutable\",\n                        \"name\": \"i\",\n                        \"nameLocation\": \"1157:1:25\",\n                        \"nodeType\": \"VariableDeclaration\",\n                        \"scope\": 30928,\n                        \"src\": \"1152:6:25\",\n                        \"stateVariable\": false,\n                        \"storageLocation\": \"default\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        },\n                        \"typeName\": {\n                          \"id\": 30894,\n                          \"name\": \"uint\",\n                          \"nodeType\": \"ElementaryTypeName\",\n                          \"src\": \"1152:4:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        \"visibility\": \"internal\"\n                      }\n                    ],\n                    \"id\": 30896,\n                    \"nodeType\": \"VariableDeclarationStatement\",\n                    \"src\": \"1152:6:25\"\n                  },\n                  \"nodeType\": \"ForStatement\",\n                  \"src\": \"1147:275:25\"\n                }\n              ]\n            },\n            \"functionSelector\": \"9c832f93\",\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [\n              {\n                \"id\": 30887,\n                \"kind\": \"modifierInvocation\",\n                \"modifierName\": {\n                  \"id\": 30886,\n                  \"name\": \"onlyOwner\",\n                  \"nameLocations\": [\n                    \"1089:9:25\"\n                  ],\n                  \"nodeType\": \"IdentifierPath\",\n                  \"referencedDeclaration\": 30868,\n                  \"src\": \"1089:9:25\"\n                },\n                \"nodeType\": \"ModifierInvocation\",\n                \"src\": \"1089:9:25\"\n              }\n            ],\n            \"name\": \"recoverTokens\",\n            \"nameLocation\": \"1033:13:25\",\n            \"parameters\": {\n              \"id\": 30885,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30884,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"tokens\",\n                  \"nameLocation\": \"1066:6:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30930,\n                  \"src\": \"1047:25:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"calldata\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                    \"typeString\": \"address[]\"\n                  },\n                  \"typeName\": {\n                    \"baseType\": {\n                      \"id\": 30882,\n                      \"name\": \"address\",\n                      \"nodeType\": \"ElementaryTypeName\",\n                      \"src\": \"1047:7:25\",\n                      \"stateMutability\": \"nonpayable\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"id\": 30883,\n                    \"nodeType\": \"ArrayTypeName\",\n                    \"src\": \"1047:9:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_array$_t_address_$dyn_storage_ptr\",\n                      \"typeString\": \"address[]\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"1046:27:25\"\n            },\n            \"returnParameters\": {\n              \"id\": 30888,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"1099:0:25\"\n            },\n            \"scope\": 31204,\n            \"stateMutability\": \"payable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 31004,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"1476:779:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 31003,\n              \"nodeType\": \"Block\",\n              \"src\": \"1595:660:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    30940\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30940,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"maxInt\",\n                      \"nameLocation\": \"1731:6:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31003,\n                      \"src\": \"1726:11:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30939,\n                        \"name\": \"uint\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"1726:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30946,\n                  \"initialValue\": {\n                    \"expression\": {\n                      \"arguments\": [\n                        {\n                          \"id\": 30943,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": true,\n                          \"lValueRequested\": false,\n                          \"nodeType\": \"ElementaryTypeNameExpression\",\n                          \"src\": \"1745:7:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_type$_t_uint256_$\",\n                            \"typeString\": \"type(uint256)\"\n                          },\n                          \"typeName\": {\n                            \"id\": 30942,\n                            \"name\": \"uint256\",\n                            \"nodeType\": \"ElementaryTypeName\",\n                            \"src\": \"1745:7:25\",\n                            \"typeDescriptions\": {}\n                          }\n                        }\n                      ],\n                      \"expression\": {\n                        \"argumentTypes\": [\n                          {\n                            \"typeIdentifier\": \"t_type$_t_uint256_$\",\n                            \"typeString\": \"type(uint256)\"\n                          }\n                        ],\n                        \"id\": 30941,\n                        \"name\": \"type\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": -27,\n                        \"src\": \"1740:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_function_metatype_pure$__$returns$__$\",\n                          \"typeString\": \"function () pure\"\n                        }\n                      },\n                      \"id\": 30944,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": true,\n                      \"kind\": \"functionCall\",\n                      \"lValueRequested\": false,\n                      \"nameLocations\": [],\n                      \"names\": [],\n                      \"nodeType\": \"FunctionCall\",\n                      \"src\": \"1740:13:25\",\n                      \"tryCall\": false,\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_magic_meta_type_t_uint256\",\n                        \"typeString\": \"type(uint256)\"\n                      }\n                    },\n                    \"id\": 30945,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": true,\n                    \"lValueRequested\": false,\n                    \"memberLocation\": \"1754:3:25\",\n                    \"memberName\": \"max\",\n                    \"nodeType\": \"MemberAccess\",\n                    \"src\": \"1740:17:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"1726:31:25\"\n                },\n                {\n                  \"assignments\": [\n                    30948\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30948,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"tokensLength\",\n                      \"nameLocation\": \"1773:12:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31003,\n                      \"src\": \"1768:17:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30947,\n                        \"name\": \"uint\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"1768:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30951,\n                  \"initialValue\": {\n                    \"expression\": {\n                      \"id\": 30949,\n                      \"name\": \"tokens\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30933,\n                      \"src\": \"1788:6:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                        \"typeString\": \"address[] calldata\"\n                      }\n                    },\n                    \"id\": 30950,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"memberLocation\": \"1795:6:25\",\n                    \"memberName\": \"length\",\n                    \"nodeType\": \"MemberAccess\",\n                    \"src\": \"1788:13:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"1768:33:25\"\n                },\n                {\n                  \"assignments\": [\n                    30953\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30953,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"protocolsLength\",\n                      \"nameLocation\": \"1816:15:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31003,\n                      \"src\": \"1811:20:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30952,\n                        \"name\": \"uint\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"1811:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30956,\n                  \"initialValue\": {\n                    \"expression\": {\n                      \"id\": 30954,\n                      \"name\": \"protocols\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30936,\n                      \"src\": \"1834:9:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                        \"typeString\": \"address[] calldata\"\n                      }\n                    },\n                    \"id\": 30955,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"memberLocation\": \"1844:6:25\",\n                    \"memberName\": \"length\",\n                    \"nodeType\": \"MemberAccess\",\n                    \"src\": \"1834:16:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"1811:39:25\"\n                },\n                {\n                  \"body\": {\n                    \"id\": 31001,\n                    \"nodeType\": \"Block\",\n                    \"src\": \"1894:355:25\",\n                    \"statements\": [\n                      {\n                        \"assignments\": [\n                          30965\n                        ],\n                        \"declarations\": [\n                          {\n                            \"constant\": false,\n                            \"id\": 30965,\n                            \"mutability\": \"mutable\",\n                            \"name\": \"token\",\n                            \"nameLocation\": \"1915:5:25\",\n                            \"nodeType\": \"VariableDeclaration\",\n                            \"scope\": 31001,\n                            \"src\": \"1908:12:25\",\n                            \"stateVariable\": false,\n                            \"storageLocation\": \"default\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_contract$_IERC20_$29521\",\n                              \"typeString\": \"contract IERC20\"\n                            },\n                            \"typeName\": {\n                              \"id\": 30964,\n                              \"nodeType\": \"UserDefinedTypeName\",\n                              \"pathNode\": {\n                                \"id\": 30963,\n                                \"name\": \"IERC20\",\n                                \"nameLocations\": [\n                                  \"1908:6:25\"\n                                ],\n                                \"nodeType\": \"IdentifierPath\",\n                                \"referencedDeclaration\": 29521,\n                                \"src\": \"1908:6:25\"\n                              },\n                              \"referencedDeclaration\": 29521,\n                              \"src\": \"1908:6:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_contract$_IERC20_$29521\",\n                                \"typeString\": \"contract IERC20\"\n                              }\n                            },\n                            \"visibility\": \"internal\"\n                          }\n                        ],\n                        \"id\": 30971,\n                        \"initialValue\": {\n                          \"arguments\": [\n                            {\n                              \"baseExpression\": {\n                                \"id\": 30967,\n                                \"name\": \"tokens\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30933,\n                                \"src\": \"1930:6:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                                  \"typeString\": \"address[] calldata\"\n                                }\n                              },\n                              \"id\": 30969,\n                              \"indexExpression\": {\n                                \"id\": 30968,\n                                \"name\": \"i\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30958,\n                                \"src\": \"1937:1:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"IndexAccess\",\n                              \"src\": \"1930:9:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            }\n                          ],\n                          \"expression\": {\n                            \"argumentTypes\": [\n                              {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            ],\n                            \"id\": 30966,\n                            \"name\": \"IERC20\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 29521,\n                            \"src\": \"1923:6:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_type$_t_contract$_IERC20_$29521_$\",\n                              \"typeString\": \"type(contract IERC20)\"\n                            }\n                          },\n                          \"id\": 30970,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"kind\": \"typeConversion\",\n                          \"lValueRequested\": false,\n                          \"nameLocations\": [],\n                          \"names\": [],\n                          \"nodeType\": \"FunctionCall\",\n                          \"src\": \"1923:17:25\",\n                          \"tryCall\": false,\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_contract$_IERC20_$29521\",\n                            \"typeString\": \"contract IERC20\"\n                          }\n                        },\n                        \"nodeType\": \"VariableDeclarationStatement\",\n                        \"src\": \"1908:32:25\"\n                      },\n                      {\n                        \"body\": {\n                          \"id\": 30995,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"1990:189:25\",\n                          \"statements\": [\n                            {\n                              \"assignments\": [\n                                30979\n                              ],\n                              \"declarations\": [\n                                {\n                                  \"constant\": false,\n                                  \"id\": 30979,\n                                  \"mutability\": \"mutable\",\n                                  \"name\": \"protocol\",\n                                  \"nameLocation\": \"2016:8:25\",\n                                  \"nodeType\": \"VariableDeclaration\",\n                                  \"scope\": 30995,\n                                  \"src\": \"2008:16:25\",\n                                  \"stateVariable\": false,\n                                  \"storageLocation\": \"default\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_address\",\n                                    \"typeString\": \"address\"\n                                  },\n                                  \"typeName\": {\n                                    \"id\": 30978,\n                                    \"name\": \"address\",\n                                    \"nodeType\": \"ElementaryTypeName\",\n                                    \"src\": \"2008:7:25\",\n                                    \"stateMutability\": \"nonpayable\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_address\",\n                                      \"typeString\": \"address\"\n                                    }\n                                  },\n                                  \"visibility\": \"internal\"\n                                }\n                              ],\n                              \"id\": 30983,\n                              \"initialValue\": {\n                                \"baseExpression\": {\n                                  \"id\": 30980,\n                                  \"name\": \"protocols\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30936,\n                                  \"src\": \"2027:9:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                                    \"typeString\": \"address[] calldata\"\n                                  }\n                                },\n                                \"id\": 30982,\n                                \"indexExpression\": {\n                                  \"id\": 30981,\n                                  \"name\": \"j\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30973,\n                                  \"src\": \"2037:1:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"nodeType\": \"IndexAccess\",\n                                \"src\": \"2027:12:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_address\",\n                                  \"typeString\": \"address\"\n                                }\n                              },\n                              \"nodeType\": \"VariableDeclarationStatement\",\n                              \"src\": \"2008:31:25\"\n                            },\n                            {\n                              \"expression\": {\n                                \"arguments\": [\n                                  {\n                                    \"id\": 30987,\n                                    \"name\": \"protocol\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30979,\n                                    \"src\": \"2075:8:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_address\",\n                                      \"typeString\": \"address\"\n                                    }\n                                  },\n                                  {\n                                    \"id\": 30988,\n                                    \"name\": \"maxInt\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30940,\n                                    \"src\": \"2085:6:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_uint256\",\n                                      \"typeString\": \"uint256\"\n                                    }\n                                  }\n                                ],\n                                \"expression\": {\n                                  \"argumentTypes\": [\n                                    {\n                                      \"typeIdentifier\": \"t_address\",\n                                      \"typeString\": \"address\"\n                                    },\n                                    {\n                                      \"typeIdentifier\": \"t_uint256\",\n                                      \"typeString\": \"uint256\"\n                                    }\n                                  ],\n                                  \"expression\": {\n                                    \"id\": 30984,\n                                    \"name\": \"token\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30965,\n                                    \"src\": \"2057:5:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_contract$_IERC20_$29521\",\n                                      \"typeString\": \"contract IERC20\"\n                                    }\n                                  },\n                                  \"id\": 30986,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": false,\n                                  \"memberLocation\": \"2063:11:25\",\n                                  \"memberName\": \"safeApprove\",\n                                  \"nodeType\": \"MemberAccess\",\n                                  \"referencedDeclaration\": 29625,\n                                  \"src\": \"2057:17:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_function_internal_nonpayable$_t_contract$_IERC20_$29521_$_t_address_$_t_uint256_$returns$__$attached_to$_t_contract$_IERC20_$29521_$\",\n                                    \"typeString\": \"function (contract IERC20,address,uint256)\"\n                                  }\n                                },\n                                \"id\": 30989,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"kind\": \"functionCall\",\n                                \"lValueRequested\": false,\n                                \"nameLocations\": [],\n                                \"names\": [],\n                                \"nodeType\": \"FunctionCall\",\n                                \"src\": \"2057:35:25\",\n                                \"tryCall\": false,\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_tuple$__$\",\n                                  \"typeString\": \"tuple()\"\n                                }\n                              },\n                              \"id\": 30990,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"2057:35:25\"\n                            },\n                            {\n                              \"id\": 30994,\n                              \"nodeType\": \"UncheckedBlock\",\n                              \"src\": \"2111:54:25\",\n                              \"statements\": [\n                                {\n                                  \"expression\": {\n                                    \"id\": 30992,\n                                    \"isConstant\": false,\n                                    \"isLValue\": false,\n                                    \"isPure\": false,\n                                    \"lValueRequested\": false,\n                                    \"nodeType\": \"UnaryOperation\",\n                                    \"operator\": \"++\",\n                                    \"prefix\": true,\n                                    \"src\": \"2143:3:25\",\n                                    \"subExpression\": {\n                                      \"id\": 30991,\n                                      \"name\": \"j\",\n                                      \"nodeType\": \"Identifier\",\n                                      \"overloadedDeclarations\": [],\n                                      \"referencedDeclaration\": 30973,\n                                      \"src\": \"2145:1:25\",\n                                      \"typeDescriptions\": {\n                                        \"typeIdentifier\": \"t_uint256\",\n                                        \"typeString\": \"uint256\"\n                                      }\n                                    },\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_uint256\",\n                                      \"typeString\": \"uint256\"\n                                    }\n                                  },\n                                  \"id\": 30993,\n                                  \"nodeType\": \"ExpressionStatement\",\n                                  \"src\": \"2143:3:25\"\n                                }\n                              ]\n                            }\n                          ]\n                        },\n                        \"condition\": {\n                          \"commonType\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          },\n                          \"id\": 30977,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"leftExpression\": {\n                            \"id\": 30975,\n                            \"name\": \"j\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30973,\n                            \"src\": \"1967:1:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint256\",\n                              \"typeString\": \"uint256\"\n                            }\n                          },\n                          \"nodeType\": \"BinaryOperation\",\n                          \"operator\": \"<\",\n                          \"rightExpression\": {\n                            \"id\": 30976,\n                            \"name\": \"protocolsLength\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30953,\n                            \"src\": \"1971:15:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint256\",\n                              \"typeString\": \"uint256\"\n                            }\n                          },\n                          \"src\": \"1967:19:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_bool\",\n                            \"typeString\": \"bool\"\n                          }\n                        },\n                        \"id\": 30996,\n                        \"initializationExpression\": {\n                          \"assignments\": [\n                            30973\n                          ],\n                          \"declarations\": [\n                            {\n                              \"constant\": false,\n                              \"id\": 30973,\n                              \"mutability\": \"mutable\",\n                              \"name\": \"j\",\n                              \"nameLocation\": \"1964:1:25\",\n                              \"nodeType\": \"VariableDeclaration\",\n                              \"scope\": 30996,\n                              \"src\": \"1959:6:25\",\n                              \"stateVariable\": false,\n                              \"storageLocation\": \"default\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint256\",\n                                \"typeString\": \"uint256\"\n                              },\n                              \"typeName\": {\n                                \"id\": 30972,\n                                \"name\": \"uint\",\n                                \"nodeType\": \"ElementaryTypeName\",\n                                \"src\": \"1959:4:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"visibility\": \"internal\"\n                            }\n                          ],\n                          \"id\": 30974,\n                          \"nodeType\": \"VariableDeclarationStatement\",\n                          \"src\": \"1959:6:25\"\n                        },\n                        \"nodeType\": \"ForStatement\",\n                        \"src\": \"1954:225:25\"\n                      },\n                      {\n                        \"id\": 31000,\n                        \"nodeType\": \"UncheckedBlock\",\n                        \"src\": \"2193:46:25\",\n                        \"statements\": [\n                          {\n                            \"expression\": {\n                              \"id\": 30998,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"UnaryOperation\",\n                              \"operator\": \"++\",\n                              \"prefix\": true,\n                              \"src\": \"2221:3:25\",\n                              \"subExpression\": {\n                                \"id\": 30997,\n                                \"name\": \"i\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30958,\n                                \"src\": \"2223:1:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint256\",\n                                \"typeString\": \"uint256\"\n                              }\n                            },\n                            \"id\": 30999,\n                            \"nodeType\": \"ExpressionStatement\",\n                            \"src\": \"2221:3:25\"\n                          }\n                        ]\n                      }\n                    ]\n                  },\n                  \"condition\": {\n                    \"commonType\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    },\n                    \"id\": 30962,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftExpression\": {\n                      \"id\": 30960,\n                      \"name\": \"i\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30958,\n                      \"src\": \"1874:1:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"BinaryOperation\",\n                    \"operator\": \"<\",\n                    \"rightExpression\": {\n                      \"id\": 30961,\n                      \"name\": \"tokensLength\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30948,\n                      \"src\": \"1878:12:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"1874:16:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_bool\",\n                      \"typeString\": \"bool\"\n                    }\n                  },\n                  \"id\": 31002,\n                  \"initializationExpression\": {\n                    \"assignments\": [\n                      30958\n                    ],\n                    \"declarations\": [\n                      {\n                        \"constant\": false,\n                        \"id\": 30958,\n                        \"mutability\": \"mutable\",\n                        \"name\": \"i\",\n                        \"nameLocation\": \"1871:1:25\",\n                        \"nodeType\": \"VariableDeclaration\",\n                        \"scope\": 31002,\n                        \"src\": \"1866:6:25\",\n                        \"stateVariable\": false,\n                        \"storageLocation\": \"default\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        },\n                        \"typeName\": {\n                          \"id\": 30957,\n                          \"name\": \"uint\",\n                          \"nodeType\": \"ElementaryTypeName\",\n                          \"src\": \"1866:4:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        \"visibility\": \"internal\"\n                      }\n                    ],\n                    \"id\": 30959,\n                    \"nodeType\": \"VariableDeclarationStatement\",\n                    \"src\": \"1866:6:25\"\n                  },\n                  \"nodeType\": \"ForStatement\",\n                  \"src\": \"1861:388:25\"\n                }\n              ]\n            },\n            \"functionSelector\": \"bc2078fb\",\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"approveHandlers\",\n            \"nameLocation\": \"1485:15:25\",\n            \"parameters\": {\n              \"id\": 30937,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30933,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"tokens\",\n                  \"nameLocation\": \"1529:6:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31004,\n                  \"src\": \"1510:25:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"calldata\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                    \"typeString\": \"address[]\"\n                  },\n                  \"typeName\": {\n                    \"baseType\": {\n                      \"id\": 30931,\n                      \"name\": \"address\",\n                      \"nodeType\": \"ElementaryTypeName\",\n                      \"src\": \"1510:7:25\",\n                      \"stateMutability\": \"nonpayable\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"id\": 30932,\n                    \"nodeType\": \"ArrayTypeName\",\n                    \"src\": \"1510:9:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_array$_t_address_$dyn_storage_ptr\",\n                      \"typeString\": \"address[]\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                },\n                {\n                  \"constant\": false,\n                  \"id\": 30936,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"protocols\",\n                  \"nameLocation\": \"1564:9:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31004,\n                  \"src\": \"1545:28:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"calldata\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_array$_t_address_$dyn_calldata_ptr\",\n                    \"typeString\": \"address[]\"\n                  },\n                  \"typeName\": {\n                    \"baseType\": {\n                      \"id\": 30934,\n                      \"name\": \"address\",\n                      \"nodeType\": \"ElementaryTypeName\",\n                      \"src\": \"1545:7:25\",\n                      \"stateMutability\": \"nonpayable\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"id\": 30935,\n                    \"nodeType\": \"ArrayTypeName\",\n                    \"src\": \"1545:9:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_array$_t_address_$dyn_storage_ptr\",\n                      \"typeString\": \"address[]\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"1500:79:25\"\n            },\n            \"returnParameters\": {\n              \"id\": 30938,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"1595:0:25\"\n            },\n            \"scope\": 31204,\n            \"stateMutability\": \"payable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 31096,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"2323:876:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 31095,\n              \"nodeType\": \"Block\",\n              \"src\": \"2460:739:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    31018\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 31018,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"amountOut\",\n                      \"nameLocation\": \"2478:9:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31095,\n                      \"src\": \"2470:17:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 31017,\n                        \"name\": \"uint256\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"2470:7:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 31019,\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2470:17:25\"\n                },\n                {\n                  \"assignments\": [\n                    31021\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 31021,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"paramsArrayLength\",\n                      \"nameLocation\": \"2505:17:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31095,\n                      \"src\": \"2497:25:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 31020,\n                        \"name\": \"uint256\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"2497:7:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 31024,\n                  \"initialValue\": {\n                    \"expression\": {\n                      \"id\": 31022,\n                      \"name\": \"paramsArray\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31008,\n                      \"src\": \"2525:11:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30848_calldata_ptr_$dyn_calldata_ptr\",\n                        \"typeString\": \"struct WhackAMoleBotV1.SwapParams calldata[] calldata\"\n                      }\n                    },\n                    \"id\": 31023,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"memberLocation\": \"2537:6:25\",\n                    \"memberName\": \"length\",\n                    \"nodeType\": \"MemberAccess\",\n                    \"src\": \"2525:18:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2497:46:25\"\n                },\n                {\n                  \"body\": {\n                    \"id\": 31083,\n                    \"nodeType\": \"Block\",\n                    \"src\": \"2595:486:25\",\n                    \"statements\": [\n                      {\n                        \"assignments\": [\n                          31033\n                        ],\n                        \"declarations\": [\n                          {\n                            \"constant\": false,\n                            \"id\": 31033,\n                            \"mutability\": \"mutable\",\n                            \"name\": \"params\",\n                            \"nameLocation\": \"2627:6:25\",\n                            \"nodeType\": \"VariableDeclaration\",\n                            \"scope\": 31083,\n                            \"src\": \"2609:24:25\",\n                            \"stateVariable\": false,\n                            \"storageLocation\": \"memory\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                              \"typeString\": \"struct WhackAMoleBotV1.SwapParams\"\n                            },\n                            \"typeName\": {\n                              \"id\": 31032,\n                              \"nodeType\": \"UserDefinedTypeName\",\n                              \"pathNode\": {\n                                \"id\": 31031,\n                                \"name\": \"SwapParams\",\n                                \"nameLocations\": [\n                                  \"2609:10:25\"\n                                ],\n                                \"nodeType\": \"IdentifierPath\",\n                                \"referencedDeclaration\": 30848,\n                                \"src\": \"2609:10:25\"\n                              },\n                              \"referencedDeclaration\": 30848,\n                              \"src\": \"2609:10:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_struct$_SwapParams_$30848_storage_ptr\",\n                                \"typeString\": \"struct WhackAMoleBotV1.SwapParams\"\n                              }\n                            },\n                            \"visibility\": \"internal\"\n                          }\n                        ],\n                        \"id\": 31037,\n                        \"initialValue\": {\n                          \"baseExpression\": {\n                            \"id\": 31034,\n                            \"name\": \"paramsArray\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 31008,\n                            \"src\": \"2636:11:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30848_calldata_ptr_$dyn_calldata_ptr\",\n                              \"typeString\": \"struct WhackAMoleBotV1.SwapParams calldata[] calldata\"\n                            }\n                          },\n                          \"id\": 31036,\n                          \"indexExpression\": {\n                            \"id\": 31035,\n                            \"name\": \"i\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 31026,\n                            \"src\": \"2648:1:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint256\",\n                              \"typeString\": \"uint256\"\n                            }\n                          },\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"nodeType\": \"IndexAccess\",\n                          \"src\": \"2636:14:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30848_calldata_ptr\",\n                            \"typeString\": \"struct WhackAMoleBotV1.SwapParams calldata\"\n                          }\n                        },\n                        \"nodeType\": \"VariableDeclarationStatement\",\n                        \"src\": \"2609:41:25\"\n                      },\n                      {\n                        \"condition\": {\n                          \"commonType\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          },\n                          \"id\": 31040,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"leftExpression\": {\n                            \"id\": 31038,\n                            \"name\": \"amountOut\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 31018,\n                            \"src\": \"2669:9:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint256\",\n                              \"typeString\": \"uint256\"\n                            }\n                          },\n                          \"nodeType\": \"BinaryOperation\",\n                          \"operator\": \"==\",\n                          \"rightExpression\": {\n                            \"hexValue\": \"30\",\n                            \"id\": 31039,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": true,\n                            \"kind\": \"number\",\n                            \"lValueRequested\": false,\n                            \"nodeType\": \"Literal\",\n                            \"src\": \"2682:1:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_rational_0_by_1\",\n                              \"typeString\": \"int_const 0\"\n                            },\n                            \"value\": \"0\"\n                          },\n                          \"src\": \"2669:14:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_bool\",\n                            \"typeString\": \"bool\"\n                          }\n                        },\n                        \"falseBody\": {\n                          \"id\": 31053,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"2749:58:25\",\n                          \"statements\": [\n                            {\n                              \"expression\": {\n                                \"id\": 31051,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"leftHandSide\": {\n                                  \"expression\": {\n                                    \"id\": 31047,\n                                    \"name\": \"params\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 31033,\n                                    \"src\": \"2767:6:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                      \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                    }\n                                  },\n                                  \"id\": 31049,\n                                  \"isConstant\": false,\n                                  \"isLValue\": true,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": true,\n                                  \"memberLocation\": \"2774:6:25\",\n                                  \"memberName\": \"amount\",\n                                  \"nodeType\": \"MemberAccess\",\n                                  \"referencedDeclaration\": 30847,\n                                  \"src\": \"2767:13:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"nodeType\": \"Assignment\",\n                                \"operator\": \"=\",\n                                \"rightHandSide\": {\n                                  \"id\": 31050,\n                                  \"name\": \"amountOut\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 31018,\n                                  \"src\": \"2783:9:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"src\": \"2767:25:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"id\": 31052,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"2767:25:25\"\n                            }\n                          ]\n                        },\n                        \"id\": 31054,\n                        \"nodeType\": \"IfStatement\",\n                        \"src\": \"2665:142:25\",\n                        \"trueBody\": {\n                          \"id\": 31046,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"2685:58:25\",\n                          \"statements\": [\n                            {\n                              \"expression\": {\n                                \"id\": 31044,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"leftHandSide\": {\n                                  \"id\": 31041,\n                                  \"name\": \"amountOut\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 31018,\n                                  \"src\": \"2703:9:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"nodeType\": \"Assignment\",\n                                \"operator\": \"=\",\n                                \"rightHandSide\": {\n                                  \"expression\": {\n                                    \"id\": 31042,\n                                    \"name\": \"params\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 31033,\n                                    \"src\": \"2715:6:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                      \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                    }\n                                  },\n                                  \"id\": 31043,\n                                  \"isConstant\": false,\n                                  \"isLValue\": true,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": false,\n                                  \"memberLocation\": \"2722:6:25\",\n                                  \"memberName\": \"amount\",\n                                  \"nodeType\": \"MemberAccess\",\n                                  \"referencedDeclaration\": 30847,\n                                  \"src\": \"2715:13:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"src\": \"2703:25:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"id\": 31045,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"2703:25:25\"\n                            }\n                          ]\n                        }\n                      },\n                      {\n                        \"condition\": {\n                          \"commonType\": {\n                            \"typeIdentifier\": \"t_uint8\",\n                            \"typeString\": \"uint8\"\n                          },\n                          \"id\": 31058,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"leftExpression\": {\n                            \"expression\": {\n                              \"id\": 31055,\n                              \"name\": \"params\",\n                              \"nodeType\": \"Identifier\",\n                              \"overloadedDeclarations\": [],\n                              \"referencedDeclaration\": 31033,\n                              \"src\": \"2825:6:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                              }\n                            },\n                            \"id\": 31056,\n                            \"isConstant\": false,\n                            \"isLValue\": true,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"memberLocation\": \"2832:8:25\",\n                            \"memberName\": \"protocol\",\n                            \"nodeType\": \"MemberAccess\",\n                            \"referencedDeclaration\": 30837,\n                            \"src\": \"2825:15:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint8\",\n                              \"typeString\": \"uint8\"\n                            }\n                          },\n                          \"nodeType\": \"BinaryOperation\",\n                          \"operator\": \"==\",\n                          \"rightExpression\": {\n                            \"hexValue\": \"30\",\n                            \"id\": 31057,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": true,\n                            \"kind\": \"number\",\n                            \"lValueRequested\": false,\n                            \"nodeType\": \"Literal\",\n                            \"src\": \"2844:1:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_rational_0_by_1\",\n                              \"typeString\": \"int_const 0\"\n                            },\n                            \"value\": \"0\"\n                          },\n                          \"src\": \"2825:20:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_bool\",\n                            \"typeString\": \"bool\"\n                          }\n                        },\n                        \"falseBody\": {\n                          \"condition\": {\n                            \"commonType\": {\n                              \"typeIdentifier\": \"t_uint8\",\n                              \"typeString\": \"uint8\"\n                            },\n                            \"id\": 31069,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"leftExpression\": {\n                              \"expression\": {\n                                \"id\": 31066,\n                                \"name\": \"params\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 31033,\n                                \"src\": \"2923:6:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                  \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                }\n                              },\n                              \"id\": 31067,\n                              \"isConstant\": false,\n                              \"isLValue\": true,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"memberLocation\": \"2930:8:25\",\n                              \"memberName\": \"protocol\",\n                              \"nodeType\": \"MemberAccess\",\n                              \"referencedDeclaration\": 30837,\n                              \"src\": \"2923:15:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint8\",\n                                \"typeString\": \"uint8\"\n                              }\n                            },\n                            \"nodeType\": \"BinaryOperation\",\n                            \"operator\": \"==\",\n                            \"rightExpression\": {\n                              \"hexValue\": \"31\",\n                              \"id\": 31068,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": true,\n                              \"kind\": \"number\",\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"Literal\",\n                              \"src\": \"2942:1:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_rational_1_by_1\",\n                                \"typeString\": \"int_const 1\"\n                              },\n                              \"value\": \"1\"\n                            },\n                            \"src\": \"2923:20:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_bool\",\n                              \"typeString\": \"bool\"\n                            }\n                          },\n                          \"id\": 31077,\n                          \"nodeType\": \"IfStatement\",\n                          \"src\": \"2919:92:25\",\n                          \"trueBody\": {\n                            \"id\": 31076,\n                            \"nodeType\": \"Block\",\n                            \"src\": \"2945:66:25\",\n                            \"statements\": [\n                              {\n                                \"expression\": {\n                                  \"id\": 31074,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": false,\n                                  \"leftHandSide\": {\n                                    \"id\": 31070,\n                                    \"name\": \"amountOut\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 31018,\n                                    \"src\": \"2963:9:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_uint256\",\n                                      \"typeString\": \"uint256\"\n                                    }\n                                  },\n                                  \"nodeType\": \"Assignment\",\n                                  \"operator\": \"=\",\n                                  \"rightHandSide\": {\n                                    \"arguments\": [\n                                      {\n                                        \"id\": 31072,\n                                        \"name\": \"params\",\n                                        \"nodeType\": \"Identifier\",\n                                        \"overloadedDeclarations\": [],\n                                        \"referencedDeclaration\": 31033,\n                                        \"src\": \"2989:6:25\",\n                                        \"typeDescriptions\": {\n                                          \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                          \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                        }\n                                      }\n                                    ],\n                                    \"expression\": {\n                                      \"argumentTypes\": [\n                                        {\n                                          \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                          \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                        }\n                                      ],\n                                      \"id\": 31071,\n                                      \"name\": \"uniswapV3Swap\",\n                                      \"nodeType\": \"Identifier\",\n                                      \"overloadedDeclarations\": [],\n                                      \"referencedDeclaration\": 31203,\n                                      \"src\": \"2975:13:25\",\n                                      \"typeDescriptions\": {\n                                        \"typeIdentifier\": \"t_function_internal_nonpayable$_t_struct$_SwapParams_$30848_memory_ptr_$returns$_t_uint256_$\",\n                                        \"typeString\": \"function (struct WhackAMoleBotV1.SwapParams memory) returns (uint256)\"\n                                      }\n                                    },\n                                    \"id\": 31073,\n                                    \"isConstant\": false,\n                                    \"isLValue\": false,\n                                    \"isPure\": false,\n                                    \"kind\": \"functionCall\",\n                                    \"lValueRequested\": false,\n                                    \"nameLocations\": [],\n                                    \"names\": [],\n                                    \"nodeType\": \"FunctionCall\",\n                                    \"src\": \"2975:21:25\",\n                                    \"tryCall\": false,\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_uint256\",\n                                      \"typeString\": \"uint256\"\n                                    }\n                                  },\n                                  \"src\": \"2963:33:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"id\": 31075,\n                                \"nodeType\": \"ExpressionStatement\",\n                                \"src\": \"2963:33:25\"\n                              }\n                            ]\n                          }\n                        },\n                        \"id\": 31078,\n                        \"nodeType\": \"IfStatement\",\n                        \"src\": \"2821:190:25\",\n                        \"trueBody\": {\n                          \"id\": 31065,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"2847:66:25\",\n                          \"statements\": [\n                            {\n                              \"expression\": {\n                                \"id\": 31063,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"leftHandSide\": {\n                                  \"id\": 31059,\n                                  \"name\": \"amountOut\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 31018,\n                                  \"src\": \"2865:9:25\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"nodeType\": \"Assignment\",\n                                \"operator\": \"=\",\n                                \"rightHandSide\": {\n                                  \"arguments\": [\n                                    {\n                                      \"id\": 31061,\n                                      \"name\": \"params\",\n                                      \"nodeType\": \"Identifier\",\n                                      \"overloadedDeclarations\": [],\n                                      \"referencedDeclaration\": 31033,\n                                      \"src\": \"2891:6:25\",\n                                      \"typeDescriptions\": {\n                                        \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                        \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                      }\n                                    }\n                                  ],\n                                  \"expression\": {\n                                    \"argumentTypes\": [\n                                      {\n                                        \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                        \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                      }\n                                    ],\n                                    \"id\": 31060,\n                                    \"name\": \"uniswapV2Swap\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 31159,\n                                    \"src\": \"2877:13:25\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_function_internal_nonpayable$_t_struct$_SwapParams_$30848_memory_ptr_$returns$_t_uint256_$\",\n                                      \"typeString\": \"function (struct WhackAMoleBotV1.SwapParams memory) returns (uint256)\"\n                                    }\n                                  },\n                                  \"id\": 31062,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"kind\": \"functionCall\",\n                                  \"lValueRequested\": false,\n                                  \"nameLocations\": [],\n                                  \"names\": [],\n                                  \"nodeType\": \"FunctionCall\",\n                                  \"src\": \"2877:21:25\",\n                                  \"tryCall\": false,\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"src\": \"2865:33:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"id\": 31064,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"2865:33:25\"\n                            }\n                          ]\n                        }\n                      },\n                      {\n                        \"id\": 31082,\n                        \"nodeType\": \"UncheckedBlock\",\n                        \"src\": \"3025:46:25\",\n                        \"statements\": [\n                          {\n                            \"expression\": {\n                              \"id\": 31080,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"UnaryOperation\",\n                              \"operator\": \"++\",\n                              \"prefix\": true,\n                              \"src\": \"3053:3:25\",\n                              \"subExpression\": {\n                                \"id\": 31079,\n                                \"name\": \"i\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 31026,\n                                \"src\": \"3055:1:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint256\",\n                                \"typeString\": \"uint256\"\n                              }\n                            },\n                            \"id\": 31081,\n                            \"nodeType\": \"ExpressionStatement\",\n                            \"src\": \"3053:3:25\"\n                          }\n                        ]\n                      }\n                    ]\n                  },\n                  \"condition\": {\n                    \"commonType\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    },\n                    \"id\": 31030,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftExpression\": {\n                      \"id\": 31028,\n                      \"name\": \"i\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31026,\n                      \"src\": \"2570:1:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"BinaryOperation\",\n                    \"operator\": \"<\",\n                    \"rightExpression\": {\n                      \"id\": 31029,\n                      \"name\": \"paramsArrayLength\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31021,\n                      \"src\": \"2574:17:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"2570:21:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_bool\",\n                      \"typeString\": \"bool\"\n                    }\n                  },\n                  \"id\": 31084,\n                  \"initializationExpression\": {\n                    \"assignments\": [\n                      31026\n                    ],\n                    \"declarations\": [\n                      {\n                        \"constant\": false,\n                        \"id\": 31026,\n                        \"mutability\": \"mutable\",\n                        \"name\": \"i\",\n                        \"nameLocation\": \"2567:1:25\",\n                        \"nodeType\": \"VariableDeclaration\",\n                        \"scope\": 31084,\n                        \"src\": \"2559:9:25\",\n                        \"stateVariable\": false,\n                        \"storageLocation\": \"default\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        },\n                        \"typeName\": {\n                          \"id\": 31025,\n                          \"name\": \"uint256\",\n                          \"nodeType\": \"ElementaryTypeName\",\n                          \"src\": \"2559:7:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        \"visibility\": \"internal\"\n                      }\n                    ],\n                    \"id\": 31027,\n                    \"nodeType\": \"VariableDeclarationStatement\",\n                    \"src\": \"2559:9:25\"\n                  },\n                  \"nodeType\": \"ForStatement\",\n                  \"src\": \"2554:527:25\"\n                },\n                {\n                  \"condition\": {\n                    \"commonType\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    },\n                    \"id\": 31087,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftExpression\": {\n                      \"id\": 31085,\n                      \"name\": \"amountOut\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31018,\n                      \"src\": \"3095:9:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"BinaryOperation\",\n                    \"operator\": \"<\",\n                    \"rightExpression\": {\n                      \"id\": 31086,\n                      \"name\": \"minAmountOut\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31010,\n                      \"src\": \"3107:12:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"3095:24:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_bool\",\n                      \"typeString\": \"bool\"\n                    }\n                  },\n                  \"id\": 31092,\n                  \"nodeType\": \"IfStatement\",\n                  \"src\": \"3091:75:25\",\n                  \"trueBody\": {\n                    \"id\": 31091,\n                    \"nodeType\": \"Block\",\n                    \"src\": \"3121:45:25\",\n                    \"statements\": [\n                      {\n                        \"errorCall\": {\n                          \"arguments\": [],\n                          \"expression\": {\n                            \"argumentTypes\": [],\n                            \"id\": 31088,\n                            \"name\": \"TradeFailed\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30852,\n                            \"src\": \"3142:11:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_function_error_pure$__$returns$__$\",\n                              \"typeString\": \"function () pure\"\n                            }\n                          },\n                          \"id\": 31089,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"kind\": \"functionCall\",\n                          \"lValueRequested\": false,\n                          \"nameLocations\": [],\n                          \"names\": [],\n                          \"nodeType\": \"FunctionCall\",\n                          \"src\": \"3142:13:25\",\n                          \"tryCall\": false,\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_tuple$__$\",\n                            \"typeString\": \"tuple()\"\n                          }\n                        },\n                        \"id\": 31090,\n                        \"nodeType\": \"RevertStatement\",\n                        \"src\": \"3135:20:25\"\n                      }\n                    ]\n                  }\n                },\n                {\n                  \"expression\": {\n                    \"id\": 31093,\n                    \"name\": \"amountOut\",\n                    \"nodeType\": \"Identifier\",\n                    \"overloadedDeclarations\": [],\n                    \"referencedDeclaration\": 31018,\n                    \"src\": \"3183:9:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"functionReturnParameters\": 31016,\n                  \"id\": 31094,\n                  \"nodeType\": \"Return\",\n                  \"src\": \"3176:16:25\"\n                }\n              ]\n            },\n            \"functionSelector\": \"c0f757c0\",\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [\n              {\n                \"id\": 31013,\n                \"kind\": \"modifierInvocation\",\n                \"modifierName\": {\n                  \"id\": 31012,\n                  \"name\": \"onlyOwner\",\n                  \"nameLocations\": [\n                    \"2432:9:25\"\n                  ],\n                  \"nodeType\": \"IdentifierPath\",\n                  \"referencedDeclaration\": 30868,\n                  \"src\": \"2432:9:25\"\n                },\n                \"nodeType\": \"ModifierInvocation\",\n                \"src\": \"2432:9:25\"\n              }\n            ],\n            \"name\": \"whack\",\n            \"nameLocation\": \"2332:5:25\",\n            \"parameters\": {\n              \"id\": 31011,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 31008,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"paramsArray\",\n                  \"nameLocation\": \"2369:11:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31096,\n                  \"src\": \"2347:33:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"calldata\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30848_calldata_ptr_$dyn_calldata_ptr\",\n                    \"typeString\": \"struct WhackAMoleBotV1.SwapParams[]\"\n                  },\n                  \"typeName\": {\n                    \"baseType\": {\n                      \"id\": 31006,\n                      \"nodeType\": \"UserDefinedTypeName\",\n                      \"pathNode\": {\n                        \"id\": 31005,\n                        \"name\": \"SwapParams\",\n                        \"nameLocations\": [\n                          \"2347:10:25\"\n                        ],\n                        \"nodeType\": \"IdentifierPath\",\n                        \"referencedDeclaration\": 30848,\n                        \"src\": \"2347:10:25\"\n                      },\n                      \"referencedDeclaration\": 30848,\n                      \"src\": \"2347:10:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_struct$_SwapParams_$30848_storage_ptr\",\n                        \"typeString\": \"struct WhackAMoleBotV1.SwapParams\"\n                      }\n                    },\n                    \"id\": 31007,\n                    \"nodeType\": \"ArrayTypeName\",\n                    \"src\": \"2347:12:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30848_storage_$dyn_storage_ptr\",\n                      \"typeString\": \"struct WhackAMoleBotV1.SwapParams[]\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                },\n                {\n                  \"constant\": false,\n                  \"id\": 31010,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"minAmountOut\",\n                  \"nameLocation\": \"2398:12:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31096,\n                  \"src\": \"2390:20:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 31009,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"2390:7:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"2337:79:25\"\n            },\n            \"returnParameters\": {\n              \"id\": 31016,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 31015,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"\",\n                  \"nameLocation\": \"-1:-1:-1\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31096,\n                  \"src\": \"2451:7:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 31014,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"2451:7:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"2450:9:25\"\n            },\n            \"scope\": 31204,\n            \"stateMutability\": \"payable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 31159,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"3225:523:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 31158,\n              \"nodeType\": \"Block\",\n              \"src\": \"3325:423:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    31108\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 31108,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"path\",\n                      \"nameLocation\": \"3352:4:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31158,\n                      \"src\": \"3335:21:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"memory\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                        \"typeString\": \"address[]\"\n                      },\n                      \"typeName\": {\n                        \"baseType\": {\n                          \"id\": 31106,\n                          \"name\": \"address\",\n                          \"nodeType\": \"ElementaryTypeName\",\n                          \"src\": \"3335:7:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_address\",\n                            \"typeString\": \"address\"\n                          }\n                        },\n                        \"id\": 31107,\n                        \"nodeType\": \"ArrayTypeName\",\n                        \"src\": \"3335:9:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_array$_t_address_$dyn_storage_ptr\",\n                          \"typeString\": \"address[]\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 31109,\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"3335:21:25\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 31116,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"id\": 31110,\n                      \"name\": \"path\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31108,\n                      \"src\": \"3366:4:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                        \"typeString\": \"address[] memory\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"arguments\": [\n                        {\n                          \"hexValue\": \"32\",\n                          \"id\": 31114,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": true,\n                          \"kind\": \"number\",\n                          \"lValueRequested\": false,\n                          \"nodeType\": \"Literal\",\n                          \"src\": \"3387:1:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_rational_2_by_1\",\n                            \"typeString\": \"int_const 2\"\n                          },\n                          \"value\": \"2\"\n                        }\n                      ],\n                      \"expression\": {\n                        \"argumentTypes\": [\n                          {\n                            \"typeIdentifier\": \"t_rational_2_by_1\",\n                            \"typeString\": \"int_const 2\"\n                          }\n                        ],\n                        \"id\": 31113,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": true,\n                        \"lValueRequested\": false,\n                        \"nodeType\": \"NewExpression\",\n                        \"src\": \"3373:13:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_function_objectcreation_pure$_t_uint256_$returns$_t_array$_t_address_$dyn_memory_ptr_$\",\n                          \"typeString\": \"function (uint256) pure returns (address[] memory)\"\n                        },\n                        \"typeName\": {\n                          \"baseType\": {\n                            \"id\": 31111,\n                            \"name\": \"address\",\n                            \"nodeType\": \"ElementaryTypeName\",\n                            \"src\": \"3377:7:25\",\n                            \"stateMutability\": \"nonpayable\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            }\n                          },\n                          \"id\": 31112,\n                          \"nodeType\": \"ArrayTypeName\",\n                          \"src\": \"3377:9:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_array$_t_address_$dyn_storage_ptr\",\n                            \"typeString\": \"address[]\"\n                          }\n                        }\n                      },\n                      \"id\": 31115,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": true,\n                      \"kind\": \"functionCall\",\n                      \"lValueRequested\": false,\n                      \"nameLocations\": [],\n                      \"names\": [],\n                      \"nodeType\": \"FunctionCall\",\n                      \"src\": \"3373:16:25\",\n                      \"tryCall\": false,\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                        \"typeString\": \"address[] memory\"\n                      }\n                    },\n                    \"src\": \"3366:23:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                      \"typeString\": \"address[] memory\"\n                    }\n                  },\n                  \"id\": 31117,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"3366:23:25\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 31123,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"baseExpression\": {\n                        \"id\": 31118,\n                        \"name\": \"path\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 31108,\n                        \"src\": \"3399:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                          \"typeString\": \"address[] memory\"\n                        }\n                      },\n                      \"id\": 31120,\n                      \"indexExpression\": {\n                        \"hexValue\": \"30\",\n                        \"id\": 31119,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": true,\n                        \"kind\": \"number\",\n                        \"lValueRequested\": false,\n                        \"nodeType\": \"Literal\",\n                        \"src\": \"3404:1:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_rational_0_by_1\",\n                          \"typeString\": \"int_const 0\"\n                        },\n                        \"value\": \"0\"\n                      },\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"nodeType\": \"IndexAccess\",\n                      \"src\": \"3399:7:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"expression\": {\n                        \"id\": 31121,\n                        \"name\": \"params\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 31099,\n                        \"src\": \"3409:6:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                          \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                        }\n                      },\n                      \"id\": 31122,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"3416:7:25\",\n                      \"memberName\": \"tokenIn\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 30841,\n                      \"src\": \"3409:14:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"src\": \"3399:24:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_address\",\n                      \"typeString\": \"address\"\n                    }\n                  },\n                  \"id\": 31124,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"3399:24:25\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 31130,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"baseExpression\": {\n                        \"id\": 31125,\n                        \"name\": \"path\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 31108,\n                        \"src\": \"3433:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                          \"typeString\": \"address[] memory\"\n                        }\n                      },\n                      \"id\": 31127,\n                      \"indexExpression\": {\n                        \"hexValue\": \"31\",\n                        \"id\": 31126,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": true,\n                        \"kind\": \"number\",\n                        \"lValueRequested\": false,\n                        \"nodeType\": \"Literal\",\n                        \"src\": \"3438:1:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_rational_1_by_1\",\n                          \"typeString\": \"int_const 1\"\n                        },\n                        \"value\": \"1\"\n                      },\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"nodeType\": \"IndexAccess\",\n                      \"src\": \"3433:7:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"expression\": {\n                        \"id\": 31128,\n                        \"name\": \"params\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 31099,\n                        \"src\": \"3443:6:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                          \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                        }\n                      },\n                      \"id\": 31129,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"3450:8:25\",\n                      \"memberName\": \"tokenOut\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 30843,\n                      \"src\": \"3443:15:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"src\": \"3433:25:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_address\",\n                      \"typeString\": \"address\"\n                    }\n                  },\n                  \"id\": 31131,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"3433:25:25\"\n                },\n                {\n                  \"assignments\": [\n                    31136\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 31136,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"amounts\",\n                      \"nameLocation\": \"3483:7:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31158,\n                      \"src\": \"3469:21:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"memory\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_uint256_$dyn_memory_ptr\",\n                        \"typeString\": \"uint256[]\"\n                      },\n                      \"typeName\": {\n                        \"baseType\": {\n                          \"id\": 31134,\n                          \"name\": \"uint\",\n                          \"nodeType\": \"ElementaryTypeName\",\n                          \"src\": \"3469:4:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        \"id\": 31135,\n                        \"nodeType\": \"ArrayTypeName\",\n                        \"src\": \"3469:6:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_array$_t_uint256_$dyn_storage_ptr\",\n                          \"typeString\": \"uint256[]\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 31153,\n                  \"initialValue\": {\n                    \"arguments\": [\n                      {\n                        \"expression\": {\n                          \"id\": 31142,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 31099,\n                          \"src\": \"3581:6:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                            \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 31143,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"3588:6:25\",\n                        \"memberName\": \"amount\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30847,\n                        \"src\": \"3581:13:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      {\n                        \"hexValue\": \"30\",\n                        \"id\": 31144,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": true,\n                        \"kind\": \"number\",\n                        \"lValueRequested\": false,\n                        \"nodeType\": \"Literal\",\n                        \"src\": \"3612:1:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_rational_0_by_1\",\n                          \"typeString\": \"int_const 0\"\n                        },\n                        \"value\": \"0\"\n                      },\n                      {\n                        \"id\": 31145,\n                        \"name\": \"path\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 31108,\n                        \"src\": \"3631:4:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                          \"typeString\": \"address[] memory\"\n                        }\n                      },\n                      {\n                        \"arguments\": [\n                          {\n                            \"id\": 31148,\n                            \"name\": \"this\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": -28,\n                            \"src\": \"3661:4:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_contract$_WhackAMoleBotV1_$31204\",\n                              \"typeString\": \"contract WhackAMoleBotV1\"\n                            }\n                          }\n                        ],\n                        \"expression\": {\n                          \"argumentTypes\": [\n                            {\n                              \"typeIdentifier\": \"t_contract$_WhackAMoleBotV1_$31204\",\n                              \"typeString\": \"contract WhackAMoleBotV1\"\n                            }\n                          ],\n                          \"id\": 31147,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": true,\n                          \"lValueRequested\": false,\n                          \"nodeType\": \"ElementaryTypeNameExpression\",\n                          \"src\": \"3653:7:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_type$_t_address_$\",\n                            \"typeString\": \"type(address)\"\n                          },\n                          \"typeName\": {\n                            \"id\": 31146,\n                            \"name\": \"address\",\n                            \"nodeType\": \"ElementaryTypeName\",\n                            \"src\": \"3653:7:25\",\n                            \"typeDescriptions\": {}\n                          }\n                        },\n                        \"id\": 31149,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"kind\": \"typeConversion\",\n                        \"lValueRequested\": false,\n                        \"nameLocations\": [],\n                        \"names\": [],\n                        \"nodeType\": \"FunctionCall\",\n                        \"src\": \"3653:13:25\",\n                        \"tryCall\": false,\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      },\n                      {\n                        \"expression\": {\n                          \"id\": 31150,\n                          \"name\": \"block\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": -4,\n                          \"src\": \"3684:5:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_magic_block\",\n                            \"typeString\": \"block\"\n                          }\n                        },\n                        \"id\": 31151,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"3690:9:25\",\n                        \"memberName\": \"timestamp\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"src\": \"3684:15:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      }\n                    ],\n                    \"expression\": {\n                      \"argumentTypes\": [\n                        {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_rational_0_by_1\",\n                          \"typeString\": \"int_const 0\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_array$_t_address_$dyn_memory_ptr\",\n                          \"typeString\": \"address[] memory\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      ],\n                      \"expression\": {\n                        \"arguments\": [\n                          {\n                            \"expression\": {\n                              \"id\": 31138,\n                              \"name\": \"params\",\n                              \"nodeType\": \"Identifier\",\n                              \"overloadedDeclarations\": [],\n                              \"referencedDeclaration\": 31099,\n                              \"src\": \"3510:6:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                              }\n                            },\n                            \"id\": 31139,\n                            \"isConstant\": false,\n                            \"isLValue\": true,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"memberLocation\": \"3517:7:25\",\n                            \"memberName\": \"handler\",\n                            \"nodeType\": \"MemberAccess\",\n                            \"referencedDeclaration\": 30839,\n                            \"src\": \"3510:14:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            }\n                          }\n                        ],\n                        \"expression\": {\n                          \"argumentTypes\": [\n                            {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            }\n                          ],\n                          \"id\": 31137,\n                          \"name\": \"IUniswapV2Router\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 31783,\n                          \"src\": \"3493:16:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_type$_t_contract$_IUniswapV2Router_$31783_$\",\n                            \"typeString\": \"type(contract IUniswapV2Router)\"\n                          }\n                        },\n                        \"id\": 31140,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"kind\": \"typeConversion\",\n                        \"lValueRequested\": false,\n                        \"nameLocations\": [],\n                        \"names\": [],\n                        \"nodeType\": \"FunctionCall\",\n                        \"src\": \"3493:32:25\",\n                        \"tryCall\": false,\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_contract$_IUniswapV2Router_$31783\",\n                          \"typeString\": \"contract IUniswapV2Router\"\n                        }\n                      },\n                      \"id\": 31141,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"3539:24:25\",\n                      \"memberName\": \"swapExactTokensForTokens\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31765,\n                      \"src\": \"3493:70:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_function_external_nonpayable$_t_uint256_$_t_uint256_$_t_array$_t_address_$dyn_memory_ptr_$_t_address_$_t_uint256_$returns$_t_array$_t_uint256_$dyn_memory_ptr_$\",\n                        \"typeString\": \"function (uint256,uint256,address[] memory,address,uint256) external returns (uint256[] memory)\"\n                      }\n                    },\n                    \"id\": 31152,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"kind\": \"functionCall\",\n                    \"lValueRequested\": false,\n                    \"nameLocations\": [],\n                    \"names\": [],\n                    \"nodeType\": \"FunctionCall\",\n                    \"src\": \"3493:220:25\",\n                    \"tryCall\": false,\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_array$_t_uint256_$dyn_memory_ptr\",\n                      \"typeString\": \"uint256[] memory\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"3469:244:25\"\n                },\n                {\n                  \"expression\": {\n                    \"baseExpression\": {\n                      \"id\": 31154,\n                      \"name\": \"amounts\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31136,\n                      \"src\": \"3731:7:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_uint256_$dyn_memory_ptr\",\n                        \"typeString\": \"uint256[] memory\"\n                      }\n                    },\n                    \"id\": 31156,\n                    \"indexExpression\": {\n                      \"hexValue\": \"31\",\n                      \"id\": 31155,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": true,\n                      \"kind\": \"number\",\n                      \"lValueRequested\": false,\n                      \"nodeType\": \"Literal\",\n                      \"src\": \"3739:1:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_rational_1_by_1\",\n                        \"typeString\": \"int_const 1\"\n                      },\n                      \"value\": \"1\"\n                    },\n                    \"isConstant\": false,\n                    \"isLValue\": true,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"nodeType\": \"IndexAccess\",\n                    \"src\": \"3731:10:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"functionReturnParameters\": 31103,\n                  \"id\": 31157,\n                  \"nodeType\": \"Return\",\n                  \"src\": \"3724:17:25\"\n                }\n              ]\n            },\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"uniswapV2Swap\",\n            \"nameLocation\": \"3234:13:25\",\n            \"parameters\": {\n              \"id\": 31100,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 31099,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"params\",\n                  \"nameLocation\": \"3275:6:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31159,\n                  \"src\": \"3257:24:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"memory\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                    \"typeString\": \"struct WhackAMoleBotV1.SwapParams\"\n                  },\n                  \"typeName\": {\n                    \"id\": 31098,\n                    \"nodeType\": \"UserDefinedTypeName\",\n                    \"pathNode\": {\n                      \"id\": 31097,\n                      \"name\": \"SwapParams\",\n                      \"nameLocations\": [\n                        \"3257:10:25\"\n                      ],\n                      \"nodeType\": \"IdentifierPath\",\n                      \"referencedDeclaration\": 30848,\n                      \"src\": \"3257:10:25\"\n                    },\n                    \"referencedDeclaration\": 30848,\n                    \"src\": \"3257:10:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_struct$_SwapParams_$30848_storage_ptr\",\n                      \"typeString\": \"struct WhackAMoleBotV1.SwapParams\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"3247:40:25\"\n            },\n            \"returnParameters\": {\n              \"id\": 31103,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 31102,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"amountOut\",\n                  \"nameLocation\": \"3314:9:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31159,\n                  \"src\": \"3306:17:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 31101,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"3306:7:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"3305:19:25\"\n            },\n            \"scope\": 31204,\n            \"stateMutability\": \"nonpayable\",\n            \"virtual\": false,\n            \"visibility\": \"internal\"\n          },\n          {\n            \"id\": 31203,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"3774:636:25\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 31202,\n              \"nodeType\": \"Block\",\n              \"src\": \"3874:536:25\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    31171\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 31171,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"singleParams\",\n                      \"nameLocation\": \"3926:12:25\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 31202,\n                      \"src\": \"3884:54:25\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"memory\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_struct$_ExactInputSingleParams_$31802_memory_ptr\",\n                        \"typeString\": \"struct ISwapRouter.ExactInputSingleParams\"\n                      },\n                      \"typeName\": {\n                        \"id\": 31170,\n                        \"nodeType\": \"UserDefinedTypeName\",\n                        \"pathNode\": {\n                          \"id\": 31169,\n                          \"name\": \"ISwapRouter.ExactInputSingleParams\",\n                          \"nameLocations\": [\n                            \"3884:11:25\",\n                            \"3896:22:25\"\n                          ],\n                          \"nodeType\": \"IdentifierPath\",\n                          \"referencedDeclaration\": 31802,\n                          \"src\": \"3884:34:25\"\n                        },\n                        \"referencedDeclaration\": 31802,\n                        \"src\": \"3884:34:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_ExactInputSingleParams_$31802_storage_ptr\",\n                          \"typeString\": \"struct ISwapRouter.ExactInputSingleParams\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 31191,\n                  \"initialValue\": {\n                    \"arguments\": [\n                      {\n                        \"expression\": {\n                          \"id\": 31174,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 31162,\n                          \"src\": \"4016:6:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                            \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 31175,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"4023:7:25\",\n                        \"memberName\": \"tokenIn\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30841,\n                        \"src\": \"4016:14:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      },\n                      {\n                        \"expression\": {\n                          \"id\": 31176,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 31162,\n                          \"src\": \"4058:6:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                            \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 31177,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"4065:8:25\",\n                        \"memberName\": \"tokenOut\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30843,\n                        \"src\": \"4058:15:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      },\n                      {\n                        \"expression\": {\n                          \"id\": 31178,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 31162,\n                          \"src\": \"4096:6:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                            \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 31179,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"4103:3:25\",\n                        \"memberName\": \"fee\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30845,\n                        \"src\": \"4096:10:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint24\",\n                          \"typeString\": \"uint24\"\n                        }\n                      },\n                      {\n                        \"arguments\": [\n                          {\n                            \"id\": 31182,\n                            \"name\": \"this\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": -28,\n                            \"src\": \"4143:4:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_contract$_WhackAMoleBotV1_$31204\",\n                              \"typeString\": \"contract WhackAMoleBotV1\"\n                            }\n                          }\n                        ],\n                        \"expression\": {\n                          \"argumentTypes\": [\n                            {\n                              \"typeIdentifier\": \"t_contract$_WhackAMoleBotV1_$31204\",\n                              \"typeString\": \"contract WhackAMoleBotV1\"\n                            }\n                          ],\n                          \"id\": 31181,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": true,\n                          \"lValueRequested\": false,\n                          \"nodeType\": \"ElementaryTypeNameExpression\",\n                          \"src\": \"4135:7:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_type$_t_address_$\",\n                            \"typeString\": \"type(address)\"\n                          },\n                          \"typeName\": {\n                            \"id\": 31180,\n                            \"name\": \"address\",\n                            \"nodeType\": \"ElementaryTypeName\",\n                            \"src\": \"4135:7:25\",\n                            \"typeDescriptions\": {}\n                          }\n                        },\n                        \"id\": 31183,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"kind\": \"typeConversion\",\n                        \"lValueRequested\": false,\n                        \"nameLocations\": [],\n                        \"names\": [],\n                        \"nodeType\": \"FunctionCall\",\n                        \"src\": \"4135:13:25\",\n                        \"tryCall\": false,\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      },\n                      {\n                        \"expression\": {\n                          \"id\": 31184,\n                          \"name\": \"block\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": -4,\n                          \"src\": \"4176:5:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_magic_block\",\n                            \"typeString\": \"block\"\n                          }\n                        },\n                        \"id\": 31185,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"4182:9:25\",\n                        \"memberName\": \"timestamp\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"src\": \"4176:15:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      {\n                        \"expression\": {\n                          \"id\": 31186,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 31162,\n                          \"src\": \"4219:6:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                            \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 31187,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"4226:6:25\",\n                        \"memberName\": \"amount\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30847,\n                        \"src\": \"4219:13:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      {\n                        \"hexValue\": \"30\",\n                        \"id\": 31188,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": true,\n                        \"kind\": \"number\",\n                        \"lValueRequested\": false,\n                        \"nodeType\": \"Literal\",\n                        \"src\": \"4268:1:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_rational_0_by_1\",\n                          \"typeString\": \"int_const 0\"\n                        },\n                        \"value\": \"0\"\n                      },\n                      {\n                        \"hexValue\": \"30\",\n                        \"id\": 31189,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": true,\n                        \"kind\": \"number\",\n                        \"lValueRequested\": false,\n                        \"nodeType\": \"Literal\",\n                        \"src\": \"4306:1:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_rational_0_by_1\",\n                          \"typeString\": \"int_const 0\"\n                        },\n                        \"value\": \"0\"\n                      }\n                    ],\n                    \"expression\": {\n                      \"argumentTypes\": [\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_uint24\",\n                          \"typeString\": \"uint24\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_rational_0_by_1\",\n                          \"typeString\": \"int_const 0\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_rational_0_by_1\",\n                          \"typeString\": \"int_const 0\"\n                        }\n                      ],\n                      \"expression\": {\n                        \"id\": 31172,\n                        \"name\": \"ISwapRouter\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 31832,\n                        \"src\": \"3941:11:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_type$_t_contract$_ISwapRouter_$31832_$\",\n                          \"typeString\": \"type(contract ISwapRouter)\"\n                        }\n                      },\n                      \"id\": 31173,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"3966:22:25\",\n                      \"memberName\": \"ExactInputSingleParams\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31802,\n                      \"src\": \"3941:47:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_type$_t_struct$_ExactInputSingleParams_$31802_storage_ptr_$\",\n                        \"typeString\": \"type(struct ISwapRouter.ExactInputSingleParams storage pointer)\"\n                      }\n                    },\n                    \"id\": 31190,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"kind\": \"structConstructorCall\",\n                    \"lValueRequested\": false,\n                    \"nameLocations\": [\n                      \"4007:7:25\",\n                      \"4048:8:25\",\n                      \"4091:3:25\",\n                      \"4124:9:25\",\n                      \"4166:8:25\",\n                      \"4209:8:25\",\n                      \"4250:16:25\",\n                      \"4287:17:25\"\n                    ],\n                    \"names\": [\n                      \"tokenIn\",\n                      \"tokenOut\",\n                      \"fee\",\n                      \"recipient\",\n                      \"deadline\",\n                      \"amountIn\",\n                      \"amountOutMinimum\",\n                      \"sqrtPriceLimitX96\"\n                    ],\n                    \"nodeType\": \"FunctionCall\",\n                    \"src\": \"3941:381:25\",\n                    \"tryCall\": false,\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_struct$_ExactInputSingleParams_$31802_memory_ptr\",\n                      \"typeString\": \"struct ISwapRouter.ExactInputSingleParams memory\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"3884:438:25\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 31200,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"id\": 31192,\n                      \"name\": \"amountOut\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31165,\n                      \"src\": \"4333:9:25\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"arguments\": [\n                        {\n                          \"id\": 31198,\n                          \"name\": \"singleParams\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 31171,\n                          \"src\": \"4390:12:25\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_ExactInputSingleParams_$31802_memory_ptr\",\n                            \"typeString\": \"struct ISwapRouter.ExactInputSingleParams memory\"\n                          }\n                        }\n                      ],\n                      \"expression\": {\n                        \"argumentTypes\": [\n                          {\n                            \"typeIdentifier\": \"t_struct$_ExactInputSingleParams_$31802_memory_ptr\",\n                            \"typeString\": \"struct ISwapRouter.ExactInputSingleParams memory\"\n                          }\n                        ],\n                        \"expression\": {\n                          \"arguments\": [\n                            {\n                              \"expression\": {\n                                \"id\": 31194,\n                                \"name\": \"params\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 31162,\n                                \"src\": \"4357:6:25\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                                  \"typeString\": \"struct WhackAMoleBotV1.SwapParams memory\"\n                                }\n                              },\n                              \"id\": 31195,\n                              \"isConstant\": false,\n                              \"isLValue\": true,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"memberLocation\": \"4364:7:25\",\n                              \"memberName\": \"handler\",\n                              \"nodeType\": \"MemberAccess\",\n                              \"referencedDeclaration\": 30839,\n                              \"src\": \"4357:14:25\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            }\n                          ],\n                          \"expression\": {\n                            \"argumentTypes\": [\n                              {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            ],\n                            \"id\": 31193,\n                            \"name\": \"ISwapRouter\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 31832,\n                            \"src\": \"4345:11:25\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_type$_t_contract$_ISwapRouter_$31832_$\",\n                              \"typeString\": \"type(contract ISwapRouter)\"\n                            }\n                          },\n                          \"id\": 31196,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"kind\": \"typeConversion\",\n                          \"lValueRequested\": false,\n                          \"nameLocations\": [],\n                          \"names\": [],\n                          \"nodeType\": \"FunctionCall\",\n                          \"src\": \"4345:27:25\",\n                          \"tryCall\": false,\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_contract$_ISwapRouter_$31832\",\n                            \"typeString\": \"contract ISwapRouter\"\n                          }\n                        },\n                        \"id\": 31197,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"4373:16:25\",\n                        \"memberName\": \"exactInputSingle\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 31811,\n                        \"src\": \"4345:44:25\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_function_external_payable$_t_struct$_ExactInputSingleParams_$31802_memory_ptr_$returns$_t_uint256_$\",\n                          \"typeString\": \"function (struct ISwapRouter.ExactInputSingleParams memory) payable external returns (uint256)\"\n                        }\n                      },\n                      \"id\": 31199,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"kind\": \"functionCall\",\n                      \"lValueRequested\": false,\n                      \"nameLocations\": [],\n                      \"names\": [],\n                      \"nodeType\": \"FunctionCall\",\n                      \"src\": \"4345:58:25\",\n                      \"tryCall\": false,\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"4333:70:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"id\": 31201,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"4333:70:25\"\n                }\n              ]\n            },\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"uniswapV3Swap\",\n            \"nameLocation\": \"3783:13:25\",\n            \"parameters\": {\n              \"id\": 31163,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 31162,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"params\",\n                  \"nameLocation\": \"3824:6:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31203,\n                  \"src\": \"3806:24:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"memory\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_struct$_SwapParams_$30848_memory_ptr\",\n                    \"typeString\": \"struct WhackAMoleBotV1.SwapParams\"\n                  },\n                  \"typeName\": {\n                    \"id\": 31161,\n                    \"nodeType\": \"UserDefinedTypeName\",\n                    \"pathNode\": {\n                      \"id\": 31160,\n                      \"name\": \"SwapParams\",\n                      \"nameLocations\": [\n                        \"3806:10:25\"\n                      ],\n                      \"nodeType\": \"IdentifierPath\",\n                      \"referencedDeclaration\": 30848,\n                      \"src\": \"3806:10:25\"\n                    },\n                    \"referencedDeclaration\": 30848,\n                    \"src\": \"3806:10:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_struct$_SwapParams_$30848_storage_ptr\",\n                      \"typeString\": \"struct WhackAMoleBotV1.SwapParams\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"3796:40:25\"\n            },\n            \"returnParameters\": {\n              \"id\": 31166,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 31165,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"amountOut\",\n                  \"nameLocation\": \"3863:9:25\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 31203,\n                  \"src\": \"3855:17:25\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 31164,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"3855:7:25\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"3854:19:25\"\n            },\n            \"scope\": 31204,\n            \"stateMutability\": \"nonpayable\",\n            \"virtual\": false,\n            \"visibility\": \"internal\"\n          }\n        ],\n        \"abstract\": false,\n        \"baseContracts\": [],\n        \"canonicalName\": \"WhackAMoleBotV1\",\n        \"contractDependencies\": [],\n        \"contractKind\": \"contract\",\n        \"fullyImplemented\": true,\n        \"linearizedBaseContracts\": [\n          31204\n        ],\n        \"name\": \"WhackAMoleBotV1\",\n        \"nameLocation\": \"442:15:25\",\n        \"scope\": 31205,\n        \"usedErrors\": [\n          30850,\n          30852\n        ],\n        \"usedEvents\": []\n      }\n    ],\n    \"license\": \"MIT\"\n  },\n  \"id\": 25\n}"
  },
  {
    "path": "execution/__init__.py",
    "content": "from execution.dex_order import DexOrder"
  },
  {
    "path": "execution/dex_order.py",
    "content": "import os\nimport json\nimport asyncio\nfrom web3 import Web3\nfrom uuid import uuid4\nfrom pathlib import Path\nfrom dotenv import load_dotenv\nfrom typing import Any, Dict, List\nfrom eth_account.account import Account\nfrom flashbots import flashbot, Flashbots\nfrom web3.exceptions import TransactionNotFound\nfrom flashbots.flashbots import FlashbotsBundleResponse\n\nload_dotenv(override=True)\n\nPROTOCOL_TO_ID = {\n    'uniswap_v2': 0,\n    'sushiswap_v2': 0,\n    'uniswap_v3': 1,\n    'sushiswap_v3': 1,\n}\n\nFLASHBOTS_SIGNING_KEY = os.getenv('FLASHBOTS_SIGNING_KEY')\nFLASHBOTS_PRIVATE_KEY = os.getenv('FLASHBOTS_PRIVATE_KEY')\n\nDIR = os.path.dirname(os.path.abspath(__file__))\n\nBOT_ABI_FILE_PATH = Path(DIR) / 'WhackAMoleBotV1.json'\nBOT_ABI = json.load(open(BOT_ABI_FILE_PATH, 'r'))['abi']\n\nERC20_ABI_FILE_PATH = Path(DIR).parent / 'abi' / 'ERC20.json'\nERC20_ABI = json.load(open(ERC20_ABI_FILE_PATH, 'r'))\n\n\nclass DexOrder:\n    \"\"\"\n    TODO: Send bundles to multiple private relays to increase probability of being added\n    \"\"\"\n    PRIVATE_RELAY = {\n        'ethereum': 'https://relay.flashbots.net'\n    }\n\n    def __init__(self,\n                 private_key: str = FLASHBOTS_PRIVATE_KEY,\n                 signing_key: str = FLASHBOTS_SIGNING_KEY,\n                 rpc_endpoints: Dict[str, str] = None,\n                 tokens: Dict[str, Dict[str, List[str or int]]] = None,\n                 pools: List[Dict[str, Any]] = None,\n                 contracts: Dict[str, str] = None,\n                 handlers: Dict[str, Dict[str, str]] = None):\n\n        self.sender = Account.from_key(private_key)\n        self.signer = Account.from_key(signing_key)  # used for Flashbots reputation\n\n        self.rpc_endpoints = rpc_endpoints\n        self.tokens = tokens\n        self.pools = pools\n        self.contracts = contracts\n        self.handlers = handlers\n\n        # extract keys from tokens, pools\n        self.chains_list = sorted(list(tokens.keys()))\n        self.exchanges_list = sorted(set([p['exchange'] for p in pools]))\n\n        tokens_list = []\n        for exchange, tokens_dict in tokens.items():\n            tokens_list.extend(list(tokens_dict.keys()))\n        self.tokens_list = sorted(list(set(tokens_list)))\n\n        # map chains, exchanges, tokens to int id value\n        # this is used to map chains/exchanges/tokens to numpy array index values\n        self.chain_to_id = {k: i for i, k in enumerate(self.chains_list)}\n        self.exchange_to_id = {k: i for i, k in enumerate(self.exchanges_list)}\n        self.token_to_id = {k: i for i, k in enumerate(self.tokens_list)}\n\n        self.web3: Dict[str, Web3] = {k: Web3(Web3.HTTPProvider(v)) for k, v in rpc_endpoints.items()}\n        self.chain_id = {k: v.eth.chain_id for k, v in self.web3.items()}\n\n        for chain, w3 in self.web3.items():\n            flashbot(w3, self.signer, self.PRIVATE_RELAY[chain])\n\n        self.bot = {\n            chain: w3.eth.contract(address=contracts[chain], abi=BOT_ABI)\n            for chain, w3 in self.web3.items()\n        }\n\n    async def send_bundle(self,\n                          w3: Web3,\n                          bundle: List[Dict[str, Any]],\n                          retry: int,\n                          block_number: int = None) -> list:\n\n        flashbots: Flashbots = w3.flashbots\n\n        left_retries = retry\n\n        if not block_number:\n            block_number = w3.eth.block_number\n\n        receipts = []\n\n        while left_retries > 0:\n            print(f'Sending bundles at: #{block_number}')\n            try:\n                flashbots.simulate(bundle, block_number)\n            except Exception as e:\n                print('Simulation error', e)\n                break\n\n            replacement_uuid = str(uuid4())\n            response: FlashbotsBundleResponse = flashbots.send_bundle(\n                bundle,\n                target_block_number=block_number + 1,\n                opts={'replacementUuid': replacement_uuid},\n            )\n\n            while w3.eth.block_number < response.target_block_number:\n                await asyncio.sleep(1)\n\n            try:\n                receipts = list(\n                    map(lambda tx: w3.eth.get_transaction_receipt(tx['hash']), response.bundle)\n                )\n                print(f'\\nBundle was mined in block {receipts[0].blockNumber}\\a')\n                break\n            except TransactionNotFound:\n                print(f'Bundle not found in block {block_number + 1}')\n                flashbots.cancel_bundles(replacement_uuid)\n                left_retries -= 1\n                block_number += 1\n\n        return receipts\n\n    async def transfer_in(self,\n                          chain: str,\n                          token: str,\n                          amount: float,\n                          max_priority_fee_per_gas: float,\n                          max_fee_per_gas: float,\n                          retry: int,\n                          block_number: int = None) -> list:\n\n        w3 = self.web3[chain]\n        token_contract = w3.eth.contract(address=token, abi=ERC20_ABI)\n        nonce = w3.eth.get_transaction_count(self.sender.address)\n        transaction = token_contract.functions.transfer(\n            self.bot[chain].address, int(amount)\n        ).build_transaction({\n            'from': self.sender.address,\n            'gas': 200000,\n            'nonce': nonce,\n            'chainId': self.chain_id[chain],\n            'maxFeePerGas': int(max_fee_per_gas),\n            'maxPriorityFeePerGas': int(max_priority_fee_per_gas),\n        })\n        signed = self.sender.sign_transaction(transaction)\n        bundle = [{'signed_transaction': signed.rawTransaction}]\n        return await self.send_bundle(w3, bundle, retry, block_number)\n\n    async def transfer_out(self,\n                           chain: str,\n                           tokens: List[str],\n                           max_priority_fee_per_gas: float,\n                           max_fee_per_gas: float,\n                           retry: int,\n                           block_number: int = None) -> list:\n\n        w3 = self.web3[chain]\n        nonce = w3.eth.get_transaction_count(self.sender.address)\n        transaction = self.bot[chain].functions.recoverTokens(\n            tokens\n        ).build_transaction({\n            'from': self.sender.address,\n            'gas': 300000,\n            'nonce': nonce,\n            'chainId': self.chain_id[chain],\n            'maxFeePerGas': int(max_fee_per_gas),\n            'maxPriorityFeePerGas': int(max_priority_fee_per_gas),\n        })\n        signed = self.sender.sign_transaction(transaction)\n        bundle = [{'signed_transaction': signed.rawTransaction}]\n        return await self.send_bundle(w3, bundle, retry, block_number)\n\n    async def approve_handlers(self,\n                               chain: str,\n                               tokens: List[str],\n                               handlers: List[str],\n                               max_priority_fee_per_gas: float,\n                               max_fee_per_gas: float,\n                               retry: int,\n                               block_number: int = None):\n        \"\"\"\n        You only need to call this once with all the tokens used in your trades\n        This function call will automatically set maxint as the approved amount to all the handlers\n        \"\"\"\n        w3 = self.web3[chain]\n        nonce = w3.eth.get_transaction_count(self.sender.address)\n        transaction = self.bot[chain].functions.approveHandlers(\n            tokens, handlers\n        ).build_transaction({\n            'from': self.sender.address,\n            'gas': 400000,\n            'nonce': nonce,\n            'chainId': self.chain_id[chain],\n            'maxFeePerGas': int(max_fee_per_gas),\n            'maxPriorityFeePerGas': int(max_priority_fee_per_gas),\n        })\n        signed = self.sender.sign_transaction(transaction)\n        bundle = [{'signed_transaction': signed.rawTransaction}]\n        return await self.send_bundle(w3, bundle, retry, block_number)\n\n    def make_params(self,\n                    amount_in: float,\n                    buy_path: List[List[int]],\n                    sell_path: List[List[int]],\n                    buy_pools: List[int],\n                    sell_pools: List[int]) -> List[Dict[str, Any]]:\n\n        params = []\n        params.extend(self._make_buy_params(amount_in, buy_path, buy_pools))\n        params.extend(self._make_sell_params(sell_path, sell_pools))\n        return params\n\n    def _make_buy_params(self,\n                         amount_in: float,\n                         path: List[List[int]],\n                         pools: List[int]):\n\n        params_list = []\n\n        for i in range(len(path)):\n            _path = path[i]\n            if not sum(_path):\n                continue\n\n            _pool_idx = pools[i]\n\n            pool = self.pools[_pool_idx]\n            chain = pool['chain']\n            exchange = pool['exchange']\n            version = pool['version']\n            exchange_key = f'{exchange}_v{version}'\n\n            token_in = self.tokens_list[_path[2]]\n            token_out = self.tokens_list[_path[3]]\n\n            amount_in_scaled = amount_in if i == 0 else 0\n\n            params = {\n                'protocol': PROTOCOL_TO_ID[exchange_key],\n                'handler': self.handlers[chain][exchange_key],\n                'tokenIn': self.tokens[chain][token_in][0],\n                'tokenOut': self.tokens[chain][token_out][0],\n                'fee': pool['fee'],\n                'amount': int(amount_in_scaled),\n            }\n            params_list.append(params)\n\n        return params_list\n\n    def _make_sell_params(self, path: List[List[int]], pools: List[int]):\n        params_list = []\n\n        for i in range(len(path)):\n            _path = path[i]\n            if not sum(_path):\n                continue\n\n            _pool_idx = pools[i]\n\n            pool = self.pools[_pool_idx]\n            chain = pool['chain']\n            exchange = pool['exchange']\n            version = pool['version']\n            exchange_key = f'{exchange}_v{version}'\n\n            # not the index difference with buy_params\n            token_in = self.tokens_list[_path[3]]\n            token_out = self.tokens_list[_path[2]]\n\n            params = {\n                'protocol': PROTOCOL_TO_ID[exchange_key],\n                'handler': self.handlers[chain][exchange_key],\n                'tokenIn': self.tokens[chain][token_in][0],\n                'tokenOut': self.tokens[chain][token_out][0],\n                'fee': pool['fee'],\n                'amount': 0,  # no need to set amount\n            }\n            params_list.append(params)\n\n        return list(reversed(params_list))\n\n    async def send_order(self,\n                         chain: str,\n                         params: List[Dict[str, Any]],\n                         min_amount_out: float,\n                         max_priority_fee_per_gas: float,\n                         max_fee_per_gas: float,\n                         retry: int,\n                         block_number: int = None):\n\n        w3 = self.web3[chain]\n        nonce = w3.eth.get_transaction_count(self.sender.address)\n        transaction = self.bot[chain].functions.whack(\n            params, int(min_amount_out)\n        ).build_transaction({\n            'from': self.sender.address,\n            'gas': 400000,\n            'nonce': nonce,\n            'chainId': self.chain_id[chain],\n            'maxFeePerGas': int(max_fee_per_gas),\n            'maxPriorityFeePerGas': int(max_priority_fee_per_gas),\n        })\n        signed = self.sender.sign_transaction(transaction)\n        bundle = [{'signed_transaction': signed.rawTransaction}]\n        return await self.send_bundle(w3, bundle, retry, block_number)\n\n\nif __name__ == '__main__':\n    from configs import RPC_ENDPOINTS\n    from addresses import ETHEREUM_EXECUTION_HANDLERS\n\n    ETHEREUM_BOT_ADDRESS = os.getenv('ETHEREUM_BOT_ADDRESS')\n\n    order = DexOrder(private_key=FLASHBOTS_PRIVATE_KEY,\n                     signing_key=FLASHBOTS_SIGNING_KEY,\n                     rpc_endpoints={'ethereum': RPC_ENDPOINTS['ethereum']},\n                     contracts={'ethereum': ETHEREUM_BOT_ADDRESS},\n                     handlers={'ethereum': ETHEREUM_EXECUTION_HANDLERS})\n\n    block_number = order.web3['ethereum'].eth.block_number\n    max_priority_fee_per_gas = 1 * 10 ** 9\n    max_fee_per_gas = 30 * 10 ** 9\n\n    # # example of sending USDT into bot contract\n    # receipts = asyncio.run(order.transfer_in('ethereum',\n    #                                          '0xdAC17F958D2ee523a2206206994597C13D831ec7',\n    #                                          100 * 10 ** 6,\n    #                                          max_priority_fee_per_gas,\n    #                                          max_fee_per_gas,\n    #                                          block_number))\n\n    # # example of recovering USDT from bot contract\n    # receipts = asyncio.run(order.transfer_out('ethereum',\n    #                                           ['0xdAC17F958D2ee523a2206206994597C13D831ec7'],\n    #                                           max_priority_fee_per_gas,\n    #                                           max_fee_per_gas,\n    #                                           3,\n    #                                           block_number))\n\n    usdt = order.web3['ethereum'].eth.contract(address='0xdAC17F958D2ee523a2206206994597C13D831ec7',\n                                               abi=ERC20_ABI)\n    owner_usdt_balance = usdt.functions.balanceOf(order.sender.address).call()\n    bot_usdt_balance = usdt.functions.balanceOf(order.contracts['ethereum']).call()\n    print(owner_usdt_balance, bot_usdt_balance)\n"
  },
  {
    "path": "external/__init__.py",
    "content": "from external.influxdb import *\nfrom external.telegram_bot import *"
  },
  {
    "path": "external/influxdb.py",
    "content": "import os\nfrom typing import Dict\nfrom dotenv import load_dotenv\nfrom influxdb_client import Point\nfrom influxdb_client.client.influxdb_client_async import InfluxDBClientAsync\n\nload_dotenv(override=True)\n\nINFLUXDB_TOKEN = os.getenv('INFLUXDB_TOKEN')\nINFLUXDB_URL = os.getenv('INFLUXDB_URL')\nINFLUXDB_ORG = os.getenv('INFLUXDB_ORG')\nINFLUXDB_BUCKET = os.getenv('INFLUXDB_BUCKET')\n\n\nclass InfluxDB:\n    \"\"\"\n    Used to collect real-time data from bot.\n    If all init args are None, InfluxDB won't do anything.\n    \"\"\"\n\n    def __init__(self,\n                 token: str = INFLUXDB_TOKEN,\n                 url: str = INFLUXDB_URL,\n                 org: str = INFLUXDB_ORG,\n                 bucket: str = INFLUXDB_BUCKET):\n\n        self.token = token\n        self.url = url\n        self.org = org\n        self.bucket = bucket\n\n        if token:\n            self.client = InfluxDBClientAsync(\n                url=url,\n                token=token,\n                org=org\n            )\n            self.write_api = self.client.write_api()\n        else:\n            self.client = None\n            self.write_api = None\n\n    async def send(self, measurement: str, data: Dict[str, float]):\n        if self.write_api:\n            points = [\n                Point(measurement).field(k, v)\n                for k, v in data.items()\n            ]\n            await self.write_api.write(\n                bucket=self.bucket,\n                org=self.org,\n                record=points\n            )\n\n    async def close(self):\n        if self.client:\n            await self.client.close()\n\n\nasync def test_send():\n    influxdb = InfluxDB()\n    await influxdb.send('test', {'data1': 1, 'data2': 2})\n    await influxdb.close()\n\n\nif __name__ == '__main__':\n    import asyncio\n\n    asyncio.run(test_send())\n"
  },
  {
    "path": "external/telegram_bot.py",
    "content": "import os\nimport requests\nfrom telegram import Bot\nfrom dotenv import load_dotenv\n\nload_dotenv(override=True)\n\nTELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN')\nTELEGRAM_CHAT_ID = os.getenv('TELEGRAM_CHAT_ID')\n\n\nclass Telegram:\n\n    def __init__(self,\n                 token: str = TELEGRAM_TOKEN,\n                 chat_id: str or int = TELEGRAM_CHAT_ID):\n\n        if token and chat_id:\n            self.token = token\n            self.chat_id = int(chat_id)\n\n        if token:\n            self.bot = Bot(token=self.token)\n        else:\n            self.bot = None\n\n    def get_updates(self):\n        \"\"\"\n        You can call get_updates to get the chat_id\n        \"\"\"\n        url = f'https://api.telegram.org/bot{self.token}/getUpdates'\n        updates = requests.get(url)\n        return updates.json()\n\n    async def send(self, message: str):\n        if self.bot:\n            await self.bot.sendMessage(chat_id=self.chat_id, text=message)\n\n\nasync def test_send():\n    tele = Telegram()\n    await tele.send('hello there')\n\n\nif __name__ == '__main__':\n    import asyncio\n\n    asyncio.run(test_send())\n"
  },
  {
    "path": "main.py",
    "content": "import asyncio\nimport nest_asyncio\n\nfrom strategies.dex_arb_base import main\n\n\nif __name__ == '__main__':\n    nest_asyncio.apply()\n    asyncio.run(main())\n"
  },
  {
    "path": "requirements.txt",
    "content": "aiohttp==3.8.5\naioprocessing==2.0.1\naiosignal==1.3.1\nanyio==3.7.1\nasync-timeout==4.0.2\nattrs==23.1.0\nbase58==2.1.1\nbitarray==2.8.1\ncertifi==2023.7.22\ncharset-normalizer==3.2.0\ncytoolz==0.12.2\neth-abi==2.2.0\neth-account==0.5.9\neth-hash==0.5.2\neth-keyfile==0.5.1\neth-keys==0.3.4\neth-retry==0.1.18\neth-rlp==0.2.1\neth-typing==2.3.0\neth-utils==1.9.5\nexceptiongroup==1.1.2\nflashbots==1.1.1\nfrozenlist==1.4.0\nh11==0.14.0\nhexbytes==0.3.1\nhttpcore==0.17.3\nhttpx==0.24.1\nidna==3.4\ninfluxdb-client==1.37.0\nipfshttpclient==0.8.0a2\njsonschema==4.19.0\njsonschema-specifications==2023.7.1\nlru-dict==1.2.0\nmultiaddr==0.0.9\nmulticall==0.7.4\nmultidict==6.0.4\nnest-asyncio==1.5.7\nnetaddr==0.8.0\nnumpy==1.25.2\nparsimonious==0.8.1\nprotobuf==3.19.5\npycryptodome==3.18.0\npython-dateutil==2.8.2\npython-dotenv==1.0.0\npython-telegram-bot==20.4\npyunormalize==15.0.0\nreactivex==4.0.4\nreferencing==0.30.2\nregex==2023.6.3\nrequests==2.31.0\nrlp==2.0.1\nrpds-py==0.9.2\nsix==1.16.0\nsniffio==1.3.0\ntoolz==0.12.0\ntyping_extensions==4.7.1\nurllib3==2.0.4\nvarint==1.0.2\nweb3==5.31.4\nwebsockets==11.0.3\nyarl==1.9.2\n"
  },
  {
    "path": "simulation/SimulatorV1.json",
    "content": "{\n  \"abi\": [\n    {\n      \"inputs\": [],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"constructor\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"protocol\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"handler\",\n              \"type\": \"address\"\n            },\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\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct SimulatorV1.SwapParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"simulateCurveSwapIn\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"protocol\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"handler\",\n              \"type\": \"address\"\n            },\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\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct SimulatorV1.SwapParams[]\",\n          \"name\": \"paramsArray\",\n          \"type\": \"tuple[]\"\n        }\n      ],\n      \"name\": \"simulateSwapIn\",\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          \"components\": [\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"protocol\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"handler\",\n              \"type\": \"address\"\n            },\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\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct SimulatorV1.SwapParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"simulateUniswapV2SwapIn\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"components\": [\n            {\n              \"internalType\": \"uint8\",\n              \"name\": \"protocol\",\n              \"type\": \"uint8\"\n            },\n            {\n              \"internalType\": \"address\",\n              \"name\": \"handler\",\n              \"type\": \"address\"\n            },\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\": \"uint256\",\n              \"name\": \"amount\",\n              \"type\": \"uint256\"\n            }\n          ],\n          \"internalType\": \"struct SimulatorV1.SwapParams\",\n          \"name\": \"params\",\n          \"type\": \"tuple\"\n        }\n      ],\n      \"name\": \"simulateUniswapV3SwapIn\",\n      \"outputs\": [\n        {\n          \"internalType\": \"uint256\",\n          \"name\": \"amountOut\",\n          \"type\": \"uint256\"\n        }\n      ],\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    }\n  ],\n  \"bytecode\": {\n    \"object\": \"0x608060405234801561001057600080fd5b50610b6f806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806355abbafc14610051578063766370281461007657806388dbf051146100895780638e888ccc1461009c575b600080fd5b61006461005f366004610866565b6100af565b60405190815260200160405180910390f35b610064610084366004610927565b61014e565b610064610097366004610927565b610185565b6100646100aa366004610927565b610332565b60008082815b818110156101425760008686838181106100d1576100d16109d0565b905060c002018036038101906100e79190610927565b9050836000036100fd578060a001519350610105565b60a081018490525b805160ff166000036101215761011a8161014e565b9350610139565b805160ff166001036101395761013681610332565b93505b506001016100b5565b50909150505b92915050565b600080600061016a84602001518560400151866060015161043d565b9150915061017d8460a001518383610515565b949350505050565b60208101516000908180805b81600f0b83600f0b0361028c576040517f23746eb8000000000000000000000000000000000000000000000000000000008152600f82900b60048201526000906001600160a01b038616906323746eb8906024016020604051808303816000875af1158015610204573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022891906109e6565b905086604001516001600160a01b0316816001600160a01b03160361024f57819350610270565b86606001516001600160a01b0316816001600160a01b031603610270578192505b82600f0b84600f0b14610283575061028c565b50600101610191565b60a08601516040517f5e0d443f000000000000000000000000000000000000000000000000000000008152600f85810b600483015284900b602482015260448101919091526001600160a01b03851690635e0d443f906064016020604051808303816000875af1158015610304573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103289190610a03565b9695505050505050565b6020818101516040805160a080820183526000808352948201858152828401868152606080850188815260808087018a8152888c01516001600160a01b039081168952938c015184168652958b015184528a015162ffffff908116825296517fc6a5026a0000000000000000000000000000000000000000000000000000000081528651831660048201529351821660248501529151604484015290519094166064820152905183166084820152909183169063c6a5026a9060a4016080604051808303816000875af115801561040d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104319190610a30565b50919695505050505050565b600080600061044c8585610660565b50905060008061045d88888861076f565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561049a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104be9190610a94565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150826001600160a01b0316876001600160a01b031614610503578082610506565b81815b90999098509650505050505050565b60008084116105915760405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201527f4e5055545f414d4f554e5400000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000831180156105a15750600082115b6106135760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c60448201527f49515549444954590000000000000000000000000000000000000000000000006064820152608401610588565b6000610621856103e5610847565b9050600061062f8285610847565b9050600061064983610643886103e8610847565b9061085a565b90506106558183610aed565b979650505050505050565b600080826001600160a01b0316846001600160a01b0316036106ea5760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f4144445260448201527f45535345530000000000000000000000000000000000000000000000000000006064820152608401610588565b826001600160a01b0316846001600160a01b03161061070a57828461070d565b83835b90925090506001600160a01b0382166107685760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606401610588565b9250929050565b600080600061077e8585610660565b604080516bffffffffffffffffffffffff19606094851b811660208084019190915293851b81166034830152825180830360280181526048830184528051908501207fff0000000000000000000000000000000000000000000000000000000000000060688401529a90941b9093166069840152607d8301989098527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b60006108538284610b0f565b9392505050565b60006108538284610b26565b6000806020838503121561087957600080fd5b823567ffffffffffffffff8082111561089157600080fd5b818501915085601f8301126108a557600080fd5b8135818111156108b457600080fd5b86602060c0830285010111156108c957600080fd5b60209290920196919550909350505050565b803560ff811681146108ec57600080fd5b919050565b6001600160a01b038116811461090657600080fd5b50565b80356108ec816108f1565b803562ffffff811681146108ec57600080fd5b600060c0828403121561093957600080fd5b60405160c0810181811067ffffffffffffffff8211171561096a57634e487b7160e01b600052604160045260246000fd5b604052610976836108db565b815261098460208401610909565b602082015261099560408401610909565b60408201526109a660608401610909565b60608201526109b760808401610914565b608082015260a083013560a08201528091505092915050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156109f857600080fd5b8151610853816108f1565b600060208284031215610a1557600080fd5b5051919050565b805163ffffffff811681146108ec57600080fd5b60008060008060808587031215610a4657600080fd5b845193506020850151610a58816108f1565b9250610a6660408601610a1c565b6060959095015193969295505050565b80516dffffffffffffffffffffffffffff811681146108ec57600080fd5b600080600060608486031215610aa957600080fd5b610ab284610a76565b9250610ac060208501610a76565b9150610ace60408501610a1c565b90509250925092565b634e487b7160e01b600052601160045260246000fd5b600082610b0a57634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761014857610148610ad7565b8082018082111561014857610148610ad756fea2646970667358221220e356eadef5c9ba78dc02924fa374e49a14a1c39f7523faef2ea2243ff497574564736f6c63430008140033\",\n    \"sourceMap\": \"322:2859:24:-:0;;;748:16;;;;;;;;;;322:2859;;;;;;\",\n    \"linkReferences\": {}\n  },\n  \"deployedBytecode\": {\n    \"object\": \"0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806355abbafc14610051578063766370281461007657806388dbf051146100895780638e888ccc1461009c575b600080fd5b61006461005f366004610866565b6100af565b60405190815260200160405180910390f35b610064610084366004610927565b61014e565b610064610097366004610927565b610185565b6100646100aa366004610927565b610332565b60008082815b818110156101425760008686838181106100d1576100d16109d0565b905060c002018036038101906100e79190610927565b9050836000036100fd578060a001519350610105565b60a081018490525b805160ff166000036101215761011a8161014e565b9350610139565b805160ff166001036101395761013681610332565b93505b506001016100b5565b50909150505b92915050565b600080600061016a84602001518560400151866060015161043d565b9150915061017d8460a001518383610515565b949350505050565b60208101516000908180805b81600f0b83600f0b0361028c576040517f23746eb8000000000000000000000000000000000000000000000000000000008152600f82900b60048201526000906001600160a01b038616906323746eb8906024016020604051808303816000875af1158015610204573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022891906109e6565b905086604001516001600160a01b0316816001600160a01b03160361024f57819350610270565b86606001516001600160a01b0316816001600160a01b031603610270578192505b82600f0b84600f0b14610283575061028c565b50600101610191565b60a08601516040517f5e0d443f000000000000000000000000000000000000000000000000000000008152600f85810b600483015284900b602482015260448101919091526001600160a01b03851690635e0d443f906064016020604051808303816000875af1158015610304573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103289190610a03565b9695505050505050565b6020818101516040805160a080820183526000808352948201858152828401868152606080850188815260808087018a8152888c01516001600160a01b039081168952938c015184168652958b015184528a015162ffffff908116825296517fc6a5026a0000000000000000000000000000000000000000000000000000000081528651831660048201529351821660248501529151604484015290519094166064820152905183166084820152909183169063c6a5026a9060a4016080604051808303816000875af115801561040d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104319190610a30565b50919695505050505050565b600080600061044c8585610660565b50905060008061045d88888861076f565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561049a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104be9190610a94565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150826001600160a01b0316876001600160a01b031614610503578082610506565b81815b90999098509650505050505050565b60008084116105915760405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201527f4e5055545f414d4f554e5400000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000831180156105a15750600082115b6106135760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c60448201527f49515549444954590000000000000000000000000000000000000000000000006064820152608401610588565b6000610621856103e5610847565b9050600061062f8285610847565b9050600061064983610643886103e8610847565b9061085a565b90506106558183610aed565b979650505050505050565b600080826001600160a01b0316846001600160a01b0316036106ea5760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f4144445260448201527f45535345530000000000000000000000000000000000000000000000000000006064820152608401610588565b826001600160a01b0316846001600160a01b03161061070a57828461070d565b83835b90925090506001600160a01b0382166107685760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606401610588565b9250929050565b600080600061077e8585610660565b604080516bffffffffffffffffffffffff19606094851b811660208084019190915293851b81166034830152825180830360280181526048830184528051908501207fff0000000000000000000000000000000000000000000000000000000000000060688401529a90941b9093166069840152607d8301989098527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f609d808401919091528851808403909101815260bd909201909752805196019590952095945050505050565b60006108538284610b0f565b9392505050565b60006108538284610b26565b6000806020838503121561087957600080fd5b823567ffffffffffffffff8082111561089157600080fd5b818501915085601f8301126108a557600080fd5b8135818111156108b457600080fd5b86602060c0830285010111156108c957600080fd5b60209290920196919550909350505050565b803560ff811681146108ec57600080fd5b919050565b6001600160a01b038116811461090657600080fd5b50565b80356108ec816108f1565b803562ffffff811681146108ec57600080fd5b600060c0828403121561093957600080fd5b60405160c0810181811067ffffffffffffffff8211171561096a57634e487b7160e01b600052604160045260246000fd5b604052610976836108db565b815261098460208401610909565b602082015261099560408401610909565b60408201526109a660608401610909565b60608201526109b760808401610914565b608082015260a083013560a08201528091505092915050565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156109f857600080fd5b8151610853816108f1565b600060208284031215610a1557600080fd5b5051919050565b805163ffffffff811681146108ec57600080fd5b60008060008060808587031215610a4657600080fd5b845193506020850151610a58816108f1565b9250610a6660408601610a1c565b6060959095015193969295505050565b80516dffffffffffffffffffffffffffff811681146108ec57600080fd5b600080600060608486031215610aa957600080fd5b610ab284610a76565b9250610ac060208501610a76565b9150610ace60408501610a1c565b90509250925092565b634e487b7160e01b600052601160045260246000fd5b600082610b0a57634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761014857610148610ad7565b8082018082111561014857610148610ad756fea2646970667358221220e356eadef5c9ba78dc02924fa374e49a14a1c39f7523faef2ea2243ff497574564736f6c63430008140033\",\n    \"sourceMap\": \"322:2859:24:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;770:772;;;;;;:::i;:::-;;:::i;:::-;;;814:25:33;;;802:2;787:18;770:772:24;;;;;;;1548:424;;;;;;:::i;:::-;;:::i;2518:661::-;;;;;;:::i;:::-;;:::i;1978:534::-;;;;;;:::i;:::-;;:::i;770:772::-;859:7;;933:11;859:7;962:547;982:17;978:1;:21;962:547;;;1017:24;1044:11;;1056:1;1044:14;;;;;;;:::i;:::-;;;;;;1017:41;;;;;;;;;;:::i;:::-;;;1077:9;1090:1;1077:14;1073:142;;1123:6;:13;;;1111:25;;1073:142;;;1175:13;;;:25;;;1073:142;1233:15;;:20;;:15;:20;1229:210;;1285:31;1309:6;1285:23;:31::i;:::-;1273:43;;1229:210;;;1341:15;;:20;;1360:1;1341:20;1337:102;;1393:31;1417:6;1393:23;:31::i;:::-;1381:43;;1337:102;-1:-1:-1;1481:3:24;;962:547;;;-1:-1:-1;1526:9:24;;-1:-1:-1;;770:772:24;;;;;:::o;1548:424::-;1642:17;1672:14;1688:15;1707:123;1749:6;:14;;;1777:6;:14;;;1805:6;:15;;;1707:28;:123::i;:::-;1671:159;;;;1852:113;1895:6;:13;;;1922:9;1945:10;1852:29;:113::i;:::-;1840:125;1548:424;-1:-1:-1;;;;1548:424:24:o;2518:661::-;2661:14;;;;2603:17;;;;;2749:369;2761:1;2756:6;;:1;:6;;;2749:369;;2793:19;;;;;2801:2:33;2790:22;;;2793:19:24;;;2772:41:33;2778:12:24;;-1:-1:-1;;;;;2793:10:24;;;;;2745:18:33;;2793:19:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2778:34;;2839:6;:14;;;-1:-1:-1;;;;;2831:22:24;:4;-1:-1:-1;;;;;2831:22:24;;2827:151;;2877:7;2873:11;;2827:151;;;2917:6;:15;;;-1:-1:-1;;;;;2909:23:24;:4;-1:-1:-1;;;;;2909:23:24;;2905:73;;2956:7;2952:11;;2905:73;3001:1;2996:6;;:1;:6;;;2992:50;;3022:5;;;2992:50;-1:-1:-1;3084:9:24;;2749:369;;;3158:13;;;;3140:32;;;;;3307:2:33;3296:22;;;3140:32:24;;;3278:41:33;3355:22;;;3335:18;;;3328:50;3394:18;;;3387:34;;;;-1:-1:-1;;;;;3140:11:24;;;;;3251:18:33;;3140:32:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3128:44;2518:661;-1:-1:-1;;;;;;2518:661:24:o;1978:534::-;2125:14;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2240:14:24;;;;-1:-1:-1;;;;;2217:37:24;;;;;2288:15;;;;2264:39;;;;2337:13;;;;2313:37;;2379:10;;;2360:29;;;;;;2463:42;;;;;3943:13:33;;3939:22;;2463:42:24;;;3921:41:33;4004:24;;4000:33;;3978:20;;;3971:63;4072:24;;4050:20;;;4043:54;4139:24;;4135:39;;;4113:20;;;4106:69;4217:24;;4213:33;;4191:20;;;4184:63;-1:-1:-1;;2463:28:24;;;;;3832:19:33;;2463:42:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;2443:62:24;;1978:534;-1:-1:-1;;;;;;1978:534:24:o;1667:490:31:-;1790:16;1808;1837:14;1857:26;1868:6;1876;1857:10;:26::i;:::-;1836:47;;;1894:16;1912;1962:32;1970:7;1979:6;1987;1962:7;:32::i;:::-;-1:-1:-1;;;;;1934:95:31;;:97;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1893:138;;;;;;;;;2074:6;-1:-1:-1;;;;;2064:16:31;:6;-1:-1:-1;;;;;2064:16:31;;:86;;2131:8;2141;2064:86;;;2096:8;2106;2064:86;2041:109;;;;-1:-1:-1;1667:490:31;-1:-1:-1;;;;;;;1667:490:31:o;2276:595::-;2408:17;2456:1;2445:8;:12;2437:68;;;;-1:-1:-1;;;2437:68:31;;5668:2:33;2437:68:31;;;5650:21:33;5707:2;5687:18;;;5680:30;5746:34;5726:18;;;5719:62;5817:13;5797:18;;;5790:41;5848:19;;2437:68:31;;;;;;;;;2548:1;2536:9;:13;:31;;;;;2566:1;2553:10;:14;2536:31;2515:118;;;;-1:-1:-1;;;2515:118:31;;6080:2:33;2515:118:31;;;6062:21:33;6119:2;6099:18;;;6092:30;6158:34;6138:18;;;6131:62;6229:10;6209:18;;;6202:38;6257:19;;2515:118:31;5878:404:33;2515:118:31;2643:23;2669:17;:8;2682:3;2669:12;:17::i;:::-;2643:43;-1:-1:-1;2696:17:31;2716:31;2643:43;2736:10;2716:19;:31::i;:::-;2696:51;-1:-1:-1;2757:19:31;2779:40;2803:15;2779:19;:9;2793:4;2779:13;:19::i;:::-;:23;;:40::i;:::-;2757:62;-1:-1:-1;2841:23:31;2757:62;2841:9;:23;:::i;:::-;2829:35;2276:595;-1:-1:-1;;;;;;;2276:595:31:o;321:397::-;420:14;436;484:6;-1:-1:-1;;;;;474:16:31;:6;-1:-1:-1;;;;;474:16:31;;466:66;;;;-1:-1:-1;;;466:66:31;;6957:2:33;466:66:31;;;6939:21:33;6996:2;6976:18;;;6969:30;7035:34;7015:18;;;7008:62;7106:7;7086:18;;;7079:35;7131:19;;466:66:31;6755:401:33;466:66:31;570:6;-1:-1:-1;;;;;561:15:31;:6;-1:-1:-1;;;;;561:15:31;;:77;;623:6;631;561:77;;;592:6;600;561:77;542:96;;-1:-1:-1;542:96:31;-1:-1:-1;;;;;;656:20:31;;648:63;;;;-1:-1:-1;;;648:63:31;;7363:2:33;648:63:31;;;7345:21:33;7402:2;7382:18;;;7375:30;7441:32;7421:18;;;7414:60;7491:18;;648:63:31;7161:354:33;648:63:31;321:397;;;;;:::o;807:805::-;926:12;951:14;967;985:26;996:6;1004;985:10;:26::i;:::-;1161:32;;;-1:-1:-1;;7747:2:33;7743:15;;;7739:24;;1161:32:31;;;;7727:37:33;;;;7798:15;;;7794:24;;7780:12;;;7773:46;1161:32:31;;;;;;;;;7835:12:33;;;1161:32:31;;1151:43;;;;;;1368:12;1322:197;;;8069:92:33;8194:15;;;;8190:53;;;8177:11;;;8170:74;8260:12;;;8253:28;;;;1059:66:31;8297:12:33;;;;8290:28;;;;1322:197:31;;;;;;;;;;8334:12:33;;;;1322:197:31;;;1287:254;;;;;;;;;;-1:-1:-1;;;;;807:805:31:o;3465:96:23:-;3523:7;3549:5;3553:1;3549;:5;:::i;:::-;3542:12;3465:96;-1:-1:-1;;;3465:96:23:o;2755:::-;2813:7;2839:5;2843:1;2839;:5;:::i;14:649:33:-;131:6;139;192:2;180:9;171:7;167:23;163:32;160:52;;;208:1;205;198:12;160:52;248:9;235:23;277:18;318:2;310:6;307:14;304:34;;;334:1;331;324:12;304:34;372:6;361:9;357:22;347:32;;417:7;410:4;406:2;402:13;398:27;388:55;;439:1;436;429:12;388:55;479:2;466:16;505:2;497:6;494:14;491:34;;;521:1;518;511:12;491:34;577:7;572:2;564:4;556:6;552:17;548:2;544:26;540:35;537:48;534:68;;;598:1;595;588:12;534:68;629:2;621:11;;;;;651:6;;-1:-1:-1;14:649:33;;-1:-1:-1;;;;14:649:33:o;850:156::-;916:20;;976:4;965:16;;955:27;;945:55;;996:1;993;986:12;945:55;850:156;;;:::o;1011:154::-;-1:-1:-1;;;;;1090:5:33;1086:54;1079:5;1076:65;1066:93;;1155:1;1152;1145:12;1066:93;1011:154;:::o;1170:134::-;1238:20;;1267:31;1238:20;1267:31;:::i;1309:161::-;1376:20;;1436:8;1425:20;;1415:31;;1405:59;;1460:1;1457;1450:12;1475:959;1563:6;1616:3;1604:9;1595:7;1591:23;1587:33;1584:53;;;1633:1;1630;1623:12;1584:53;1666:2;1660:9;1708:3;1700:6;1696:16;1778:6;1766:10;1763:22;1742:18;1730:10;1727:34;1724:62;1721:242;;;-1:-1:-1;;;1816:1:33;1809:88;1920:4;1917:1;1910:15;1948:4;1945:1;1938:15;1721:242;1979:2;1972:22;2018:27;2035:9;2018:27;:::i;:::-;2010:6;2003:43;2079:38;2113:2;2102:9;2098:18;2079:38;:::i;:::-;2074:2;2066:6;2062:15;2055:63;2151:38;2185:2;2174:9;2170:18;2151:38;:::i;:::-;2146:2;2138:6;2134:15;2127:63;2223:38;2257:2;2246:9;2242:18;2223:38;:::i;:::-;2218:2;2210:6;2206:15;2199:63;2296:38;2329:3;2318:9;2314:19;2296:38;:::i;:::-;2290:3;2282:6;2278:16;2271:64;2397:3;2386:9;2382:19;2369:33;2363:3;2355:6;2351:16;2344:59;2422:6;2412:16;;;1475:959;;;;:::o;2439:184::-;-1:-1:-1;;;2488:1:33;2481:88;2588:4;2585:1;2578:15;2612:4;2609:1;2602:15;2824:251;2894:6;2947:2;2935:9;2926:7;2922:23;2918:32;2915:52;;;2963:1;2960;2953:12;2915:52;2995:9;2989:16;3014:31;3039:5;3014:31;:::i;3432:184::-;3502:6;3555:2;3543:9;3534:7;3530:23;3526:32;3523:52;;;3571:1;3568;3561:12;3523:52;-1:-1:-1;3594:16:33;;3432:184;-1:-1:-1;3432:184:33:o;4258:167::-;4336:13;;4389:10;4378:22;;4368:33;;4358:61;;4415:1;4412;4405:12;4430:457;4526:6;4534;4542;4550;4603:3;4591:9;4582:7;4578:23;4574:33;4571:53;;;4620:1;4617;4610:12;4571:53;4649:9;4643:16;4633:26;;4702:2;4691:9;4687:18;4681:25;4715:31;4740:5;4715:31;:::i;:::-;4765:5;-1:-1:-1;4789:48:33;4833:2;4818:18;;4789:48;:::i;:::-;4877:2;4862:18;;;;4856:25;4430:457;;;;-1:-1:-1;;;4430:457:33:o;4892:188::-;4971:13;;5024:30;5013:42;;5003:53;;4993:81;;5070:1;5067;5060:12;5085:376;5172:6;5180;5188;5241:2;5229:9;5220:7;5216:23;5212:32;5209:52;;;5257:1;5254;5247:12;5209:52;5280:40;5310:9;5280:40;:::i;:::-;5270:50;;5339:49;5384:2;5373:9;5369:18;5339:49;:::i;:::-;5329:59;;5407:48;5451:2;5440:9;5436:18;5407:48;:::i;:::-;5397:58;;5085:376;;;;;:::o;6287:184::-;-1:-1:-1;;;6336:1:33;6329:88;6436:4;6433:1;6426:15;6460:4;6457:1;6450:15;6476:274;6516:1;6542;6532:189;;-1:-1:-1;;;6574:1:33;6567:88;6678:4;6675:1;6668:15;6706:4;6703:1;6696:15;6532:189;-1:-1:-1;6735:9:33;;6476:274::o;8357:168::-;8430:9;;;8461;;8478:15;;;8472:22;;8458:37;8448:71;;8499:18;;:::i;8530:125::-;8595:9;;;8616:10;;;8613:36;;;8629:18;;:::i\",\n    \"linkReferences\": {}\n  },\n  \"methodIdentifiers\": {\n    \"simulateCurveSwapIn((uint8,address,address,address,uint24,uint256))\": \"88dbf051\",\n    \"simulateSwapIn((uint8,address,address,address,uint24,uint256)[])\": \"55abbafc\",\n    \"simulateUniswapV2SwapIn((uint8,address,address,address,uint24,uint256))\": \"76637028\",\n    \"simulateUniswapV3SwapIn((uint8,address,address,address,uint24,uint256))\": \"8e888ccc\"\n  },\n  \"rawMetadata\": \"{\\\"compiler\\\":{\\\"version\\\":\\\"0.8.20+commit.a1b79de6\\\"},\\\"language\\\":\\\"Solidity\\\",\\\"output\\\":{\\\"abi\\\":[{\\\"inputs\\\":[],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"constructor\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"protocol\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"handler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"internalType\\\":\\\"struct SimulatorV1.SwapParams\\\",\\\"name\\\":\\\"params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"simulateCurveSwapIn\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"protocol\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"handler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"internalType\\\":\\\"struct SimulatorV1.SwapParams[]\\\",\\\"name\\\":\\\"paramsArray\\\",\\\"type\\\":\\\"tuple[]\\\"}],\\\"name\\\":\\\"simulateSwapIn\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"protocol\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"handler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"internalType\\\":\\\"struct SimulatorV1.SwapParams\\\",\\\"name\\\":\\\"params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"simulateUniswapV2SwapIn\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"view\\\",\\\"type\\\":\\\"function\\\"},{\\\"inputs\\\":[{\\\"components\\\":[{\\\"internalType\\\":\\\"uint8\\\",\\\"name\\\":\\\"protocol\\\",\\\"type\\\":\\\"uint8\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"handler\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenIn\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"address\\\",\\\"name\\\":\\\"tokenOut\\\",\\\"type\\\":\\\"address\\\"},{\\\"internalType\\\":\\\"uint24\\\",\\\"name\\\":\\\"fee\\\",\\\"type\\\":\\\"uint24\\\"},{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amount\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"internalType\\\":\\\"struct SimulatorV1.SwapParams\\\",\\\"name\\\":\\\"params\\\",\\\"type\\\":\\\"tuple\\\"}],\\\"name\\\":\\\"simulateUniswapV3SwapIn\\\",\\\"outputs\\\":[{\\\"internalType\\\":\\\"uint256\\\",\\\"name\\\":\\\"amountOut\\\",\\\"type\\\":\\\"uint256\\\"}],\\\"stateMutability\\\":\\\"nonpayable\\\",\\\"type\\\":\\\"function\\\"}],\\\"devdoc\\\":{\\\"kind\\\":\\\"dev\\\",\\\"methods\\\":{},\\\"version\\\":1},\\\"userdoc\\\":{\\\"kind\\\":\\\"user\\\",\\\"methods\\\":{},\\\"version\\\":1}},\\\"settings\\\":{\\\"compilationTarget\\\":{\\\"src/SimulatorV1.sol\\\":\\\"SimulatorV1\\\"},\\\"evmVersion\\\":\\\"paris\\\",\\\"libraries\\\":{},\\\"metadata\\\":{\\\"bytecodeHash\\\":\\\"ipfs\\\"},\\\"optimizer\\\":{\\\"enabled\\\":true,\\\"runs\\\":1000},\\\"remappings\\\":[\\\":ds-test/=lib/forge-std/lib/ds-test/src/\\\",\\\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\\\",\\\":forge-std/=lib/forge-std/src/\\\",\\\":openzeppelin-contracts/=lib/openzeppelin-contracts/\\\",\\\":openzeppelin/=lib/openzeppelin-contracts/contracts/\\\"]},\\\"sources\\\":{\\\"lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol\\\":{\\\"keccak256\\\":\\\"0x58b21219689909c4f8339af00813760337f7e2e7f169a97fe49e2896dcfb3b9a\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://ef8e012e946dec20e59f2d4446f4b44bb098f3fa8bac103b1b5112fff777447b\\\",\\\"dweb:/ipfs/QmVTooKWcLkJ9W68yNX4MgdrbAKiAXwuRN9A7f4NkdcdtQ\\\"]},\\\"src/SimulatorV1.sol\\\":{\\\"keccak256\\\":\\\"0xabab21e93d94da86614a987cb191c4af0cfd5f7935f93d84707c162b60aa50f1\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://a994d2922c656329461adc1448cf9bc75dbdc731a4d8e2a7c404b95baf353e26\\\",\\\"dweb:/ipfs/QmYqGBumM6nTN1jk66X7qnfJihSQGJomSNW9WAtSxFvbRY\\\"]},\\\"src/protocols/curve/ICurvePool.sol\\\":{\\\"keccak256\\\":\\\"0x70b4397964caf4fd4b2725bd5f082c4bc241930eee0ee3ec9035550d4edda568\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://17e257d37e0cafc4f3535a8771e10bca33da167fde6671a378c99d407934e193\\\",\\\"dweb:/ipfs/QmRcnzAEc269hkjeMofq9gsL57J5SnFFqxZbEmCQBNFxE1\\\"]},\\\"src/protocols/uniswap/IQuoterV2.sol\\\":{\\\"keccak256\\\":\\\"0x8c0ec4a66e8d84bf495a2ff565a36ac36f17ca84b33d5a103f8b42015f866557\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://e18478bae632cc3ff4270b94862dea82306f7d26241ff8d1635175f9c019aef3\\\",\\\"dweb:/ipfs/QmbimsEhnAWc8Yakd4x6ph5UzVMchmhf17YMf6inHx8HHe\\\"]},\\\"src/protocols/uniswap/IUniswapV2Pair.sol\\\":{\\\"keccak256\\\":\\\"0x3013d79abe422a873d9e7a74813ce3c84a0340c7d6ef0b6e56806f22e79439f6\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://318c65fb06fe1274eb933c4159e8be95eb341f0d43345fe1c6bbacf0bfc6d072\\\",\\\"dweb:/ipfs/QmVpeEb9RxHcMfR4sn9Typ3V7PDJjy6nYJcTgiKqv7mzgX\\\"]},\\\"src/protocols/uniswap/UniswapV2Library.sol\\\":{\\\"keccak256\\\":\\\"0x7809ddbb45e565b2ccd8c6840987e98c336647d43d66357bbd661b343eab627d\\\",\\\"license\\\":\\\"MIT\\\",\\\"urls\\\":[\\\"bzz-raw://6f79a573e59848ef66b0d7cc590d7eb86007fc6986654c6dd620741de618e726\\\",\\\"dweb:/ipfs/QmYfaKKtd6Kqz3ady9SHUyDJwRKf8co8qP6eh5QNcfdwxt\\\"]}},\\\"version\\\":1}\",\n  \"metadata\": {\n    \"compiler\": {\n      \"version\": \"0.8.20+commit.a1b79de6\"\n    },\n    \"language\": \"Solidity\",\n    \"output\": {\n      \"abi\": [\n        {\n          \"inputs\": [],\n          \"stateMutability\": \"nonpayable\",\n          \"type\": \"constructor\"\n        },\n        {\n          \"inputs\": [\n            {\n              \"internalType\": \"struct SimulatorV1.SwapParams\",\n              \"name\": \"params\",\n              \"type\": \"tuple\",\n              \"components\": [\n                {\n                  \"internalType\": \"uint8\",\n                  \"name\": \"protocol\",\n                  \"type\": \"uint8\"\n                },\n                {\n                  \"internalType\": \"address\",\n                  \"name\": \"handler\",\n                  \"type\": \"address\"\n                },\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\": \"uint256\",\n                  \"name\": \"amount\",\n                  \"type\": \"uint256\"\n                }\n              ]\n            }\n          ],\n          \"stateMutability\": \"nonpayable\",\n          \"type\": \"function\",\n          \"name\": \"simulateCurveSwapIn\",\n          \"outputs\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            }\n          ]\n        },\n        {\n          \"inputs\": [\n            {\n              \"internalType\": \"struct SimulatorV1.SwapParams[]\",\n              \"name\": \"paramsArray\",\n              \"type\": \"tuple[]\",\n              \"components\": [\n                {\n                  \"internalType\": \"uint8\",\n                  \"name\": \"protocol\",\n                  \"type\": \"uint8\"\n                },\n                {\n                  \"internalType\": \"address\",\n                  \"name\": \"handler\",\n                  \"type\": \"address\"\n                },\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\": \"uint256\",\n                  \"name\": \"amount\",\n                  \"type\": \"uint256\"\n                }\n              ]\n            }\n          ],\n          \"stateMutability\": \"nonpayable\",\n          \"type\": \"function\",\n          \"name\": \"simulateSwapIn\",\n          \"outputs\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"\",\n              \"type\": \"uint256\"\n            }\n          ]\n        },\n        {\n          \"inputs\": [\n            {\n              \"internalType\": \"struct SimulatorV1.SwapParams\",\n              \"name\": \"params\",\n              \"type\": \"tuple\",\n              \"components\": [\n                {\n                  \"internalType\": \"uint8\",\n                  \"name\": \"protocol\",\n                  \"type\": \"uint8\"\n                },\n                {\n                  \"internalType\": \"address\",\n                  \"name\": \"handler\",\n                  \"type\": \"address\"\n                },\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\": \"uint256\",\n                  \"name\": \"amount\",\n                  \"type\": \"uint256\"\n                }\n              ]\n            }\n          ],\n          \"stateMutability\": \"view\",\n          \"type\": \"function\",\n          \"name\": \"simulateUniswapV2SwapIn\",\n          \"outputs\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            }\n          ]\n        },\n        {\n          \"inputs\": [\n            {\n              \"internalType\": \"struct SimulatorV1.SwapParams\",\n              \"name\": \"params\",\n              \"type\": \"tuple\",\n              \"components\": [\n                {\n                  \"internalType\": \"uint8\",\n                  \"name\": \"protocol\",\n                  \"type\": \"uint8\"\n                },\n                {\n                  \"internalType\": \"address\",\n                  \"name\": \"handler\",\n                  \"type\": \"address\"\n                },\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\": \"uint256\",\n                  \"name\": \"amount\",\n                  \"type\": \"uint256\"\n                }\n              ]\n            }\n          ],\n          \"stateMutability\": \"nonpayable\",\n          \"type\": \"function\",\n          \"name\": \"simulateUniswapV3SwapIn\",\n          \"outputs\": [\n            {\n              \"internalType\": \"uint256\",\n              \"name\": \"amountOut\",\n              \"type\": \"uint256\"\n            }\n          ]\n        }\n      ],\n      \"devdoc\": {\n        \"kind\": \"dev\",\n        \"methods\": {},\n        \"version\": 1\n      },\n      \"userdoc\": {\n        \"kind\": \"user\",\n        \"methods\": {},\n        \"version\": 1\n      }\n    },\n    \"settings\": {\n      \"remappings\": [\n        \":ds-test/=lib/forge-std/lib/ds-test/src/\",\n        \":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\n        \":forge-std/=lib/forge-std/src/\",\n        \":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\n        \":openzeppelin/=lib/openzeppelin-contracts/contracts/\"\n      ],\n      \"optimizer\": {\n        \"enabled\": true,\n        \"runs\": 1000\n      },\n      \"metadata\": {\n        \"bytecodeHash\": \"ipfs\"\n      },\n      \"compilationTarget\": {\n        \"src/SimulatorV1.sol\": \"SimulatorV1\"\n      },\n      \"libraries\": {}\n    },\n    \"sources\": {\n      \"lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol\": {\n        \"keccak256\": \"0x58b21219689909c4f8339af00813760337f7e2e7f169a97fe49e2896dcfb3b9a\",\n        \"urls\": [\n          \"bzz-raw://ef8e012e946dec20e59f2d4446f4b44bb098f3fa8bac103b1b5112fff777447b\",\n          \"dweb:/ipfs/QmVTooKWcLkJ9W68yNX4MgdrbAKiAXwuRN9A7f4NkdcdtQ\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/SimulatorV1.sol\": {\n        \"keccak256\": \"0xabab21e93d94da86614a987cb191c4af0cfd5f7935f93d84707c162b60aa50f1\",\n        \"urls\": [\n          \"bzz-raw://a994d2922c656329461adc1448cf9bc75dbdc731a4d8e2a7c404b95baf353e26\",\n          \"dweb:/ipfs/QmYqGBumM6nTN1jk66X7qnfJihSQGJomSNW9WAtSxFvbRY\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/protocols/curve/ICurvePool.sol\": {\n        \"keccak256\": \"0x70b4397964caf4fd4b2725bd5f082c4bc241930eee0ee3ec9035550d4edda568\",\n        \"urls\": [\n          \"bzz-raw://17e257d37e0cafc4f3535a8771e10bca33da167fde6671a378c99d407934e193\",\n          \"dweb:/ipfs/QmRcnzAEc269hkjeMofq9gsL57J5SnFFqxZbEmCQBNFxE1\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/protocols/uniswap/IQuoterV2.sol\": {\n        \"keccak256\": \"0x8c0ec4a66e8d84bf495a2ff565a36ac36f17ca84b33d5a103f8b42015f866557\",\n        \"urls\": [\n          \"bzz-raw://e18478bae632cc3ff4270b94862dea82306f7d26241ff8d1635175f9c019aef3\",\n          \"dweb:/ipfs/QmbimsEhnAWc8Yakd4x6ph5UzVMchmhf17YMf6inHx8HHe\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/protocols/uniswap/IUniswapV2Pair.sol\": {\n        \"keccak256\": \"0x3013d79abe422a873d9e7a74813ce3c84a0340c7d6ef0b6e56806f22e79439f6\",\n        \"urls\": [\n          \"bzz-raw://318c65fb06fe1274eb933c4159e8be95eb341f0d43345fe1c6bbacf0bfc6d072\",\n          \"dweb:/ipfs/QmVpeEb9RxHcMfR4sn9Typ3V7PDJjy6nYJcTgiKqv7mzgX\"\n        ],\n        \"license\": \"MIT\"\n      },\n      \"src/protocols/uniswap/UniswapV2Library.sol\": {\n        \"keccak256\": \"0x7809ddbb45e565b2ccd8c6840987e98c336647d43d66357bbd661b343eab627d\",\n        \"urls\": [\n          \"bzz-raw://6f79a573e59848ef66b0d7cc590d7eb86007fc6986654c6dd620741de618e726\",\n          \"dweb:/ipfs/QmYfaKKtd6Kqz3ady9SHUyDJwRKf8co8qP6eh5QNcfdwxt\"\n        ],\n        \"license\": \"MIT\"\n      }\n    },\n    \"version\": 1\n  },\n  \"ast\": {\n    \"absolutePath\": \"src/SimulatorV1.sol\",\n    \"id\": 30823,\n    \"exportedSymbols\": {\n      \"ICurvePool\": [\n        31411\n      ],\n      \"IQuoterV2\": [\n        31504\n      ],\n      \"IUniswapV2Pair\": [\n        31746\n      ],\n      \"SafeMath\": [\n        30539\n      ],\n      \"SimulatorV1\": [\n        30822\n      ],\n      \"UniswapV2Library\": [\n        32281\n      ]\n    },\n    \"nodeType\": \"SourceUnit\",\n    \"src\": \"32:3150:24\",\n    \"nodes\": [\n      {\n        \"id\": 30541,\n        \"nodeType\": \"PragmaDirective\",\n        \"src\": \"32:23:24\",\n        \"nodes\": [],\n        \"literals\": [\n          \"solidity\",\n          \"^\",\n          \"0.8\",\n          \".9\"\n        ]\n      },\n      {\n        \"id\": 30542,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"57:66:24\",\n        \"nodes\": [],\n        \"absolutePath\": \"lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol\",\n        \"file\": \"openzeppelin-contracts/contracts/utils/math/SafeMath.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 30823,\n        \"sourceUnit\": 30540,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30543,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"125:50:24\",\n        \"nodes\": [],\n        \"absolutePath\": \"src/protocols/uniswap/UniswapV2Library.sol\",\n        \"file\": \"./protocols/uniswap/UniswapV2Library.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 30823,\n        \"sourceUnit\": 32282,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30544,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"176:43:24\",\n        \"nodes\": [],\n        \"absolutePath\": \"src/protocols/uniswap/IQuoterV2.sol\",\n        \"file\": \"./protocols/uniswap/IQuoterV2.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 30823,\n        \"sourceUnit\": 31505,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30545,\n        \"nodeType\": \"ImportDirective\",\n        \"src\": \"220:42:24\",\n        \"nodes\": [],\n        \"absolutePath\": \"src/protocols/curve/ICurvePool.sol\",\n        \"file\": \"./protocols/curve/ICurvePool.sol\",\n        \"nameLocation\": \"-1:-1:-1\",\n        \"scope\": 30823,\n        \"sourceUnit\": 31412,\n        \"symbolAliases\": [],\n        \"unitAlias\": \"\"\n      },\n      {\n        \"id\": 30822,\n        \"nodeType\": \"ContractDefinition\",\n        \"src\": \"322:2859:24\",\n        \"nodes\": [\n          {\n            \"id\": 30548,\n            \"nodeType\": \"UsingForDirective\",\n            \"src\": \"349:27:24\",\n            \"nodes\": [],\n            \"global\": false,\n            \"libraryName\": {\n              \"id\": 30546,\n              \"name\": \"SafeMath\",\n              \"nameLocations\": [\n                \"355:8:24\"\n              ],\n              \"nodeType\": \"IdentifierPath\",\n              \"referencedDeclaration\": 30539,\n              \"src\": \"355:8:24\"\n            },\n            \"typeName\": {\n              \"id\": 30547,\n              \"name\": \"uint256\",\n              \"nodeType\": \"ElementaryTypeName\",\n              \"src\": \"368:7:24\",\n              \"typeDescriptions\": {\n                \"typeIdentifier\": \"t_uint256\",\n                \"typeString\": \"uint256\"\n              }\n            }\n          },\n          {\n            \"id\": 30561,\n            \"nodeType\": \"StructDefinition\",\n            \"src\": \"382:360:24\",\n            \"nodes\": [],\n            \"canonicalName\": \"SimulatorV1.SwapParams\",\n            \"members\": [\n              {\n                \"constant\": false,\n                \"id\": 30550,\n                \"mutability\": \"mutable\",\n                \"name\": \"protocol\",\n                \"nameLocation\": \"416:8:24\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30561,\n                \"src\": \"410:14:24\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_uint8\",\n                  \"typeString\": \"uint8\"\n                },\n                \"typeName\": {\n                  \"id\": 30549,\n                  \"name\": \"uint8\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"410:5:24\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint8\",\n                    \"typeString\": \"uint8\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30552,\n                \"mutability\": \"mutable\",\n                \"name\": \"handler\",\n                \"nameLocation\": \"493:7:24\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30561,\n                \"src\": \"485:15:24\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_address\",\n                  \"typeString\": \"address\"\n                },\n                \"typeName\": {\n                  \"id\": 30551,\n                  \"name\": \"address\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"485:7:24\",\n                  \"stateMutability\": \"nonpayable\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_address\",\n                    \"typeString\": \"address\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30554,\n                \"mutability\": \"mutable\",\n                \"name\": \"tokenIn\",\n                \"nameLocation\": \"572:7:24\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30561,\n                \"src\": \"564:15:24\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_address\",\n                  \"typeString\": \"address\"\n                },\n                \"typeName\": {\n                  \"id\": 30553,\n                  \"name\": \"address\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"564:7:24\",\n                  \"stateMutability\": \"nonpayable\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_address\",\n                    \"typeString\": \"address\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30556,\n                \"mutability\": \"mutable\",\n                \"name\": \"tokenOut\",\n                \"nameLocation\": \"597:8:24\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30561,\n                \"src\": \"589:16:24\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_address\",\n                  \"typeString\": \"address\"\n                },\n                \"typeName\": {\n                  \"id\": 30555,\n                  \"name\": \"address\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"589:7:24\",\n                  \"stateMutability\": \"nonpayable\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_address\",\n                    \"typeString\": \"address\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30558,\n                \"mutability\": \"mutable\",\n                \"name\": \"fee\",\n                \"nameLocation\": \"622:3:24\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30561,\n                \"src\": \"615:10:24\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_uint24\",\n                  \"typeString\": \"uint24\"\n                },\n                \"typeName\": {\n                  \"id\": 30557,\n                  \"name\": \"uint24\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"615:6:24\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint24\",\n                    \"typeString\": \"uint24\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              },\n              {\n                \"constant\": false,\n                \"id\": 30560,\n                \"mutability\": \"mutable\",\n                \"name\": \"amount\",\n                \"nameLocation\": \"670:6:24\",\n                \"nodeType\": \"VariableDeclaration\",\n                \"scope\": 30561,\n                \"src\": \"662:14:24\",\n                \"stateVariable\": false,\n                \"storageLocation\": \"default\",\n                \"typeDescriptions\": {\n                  \"typeIdentifier\": \"t_uint256\",\n                  \"typeString\": \"uint256\"\n                },\n                \"typeName\": {\n                  \"id\": 30559,\n                  \"name\": \"uint256\",\n                  \"nodeType\": \"ElementaryTypeName\",\n                  \"src\": \"662:7:24\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  }\n                },\n                \"visibility\": \"internal\"\n              }\n            ],\n            \"name\": \"SwapParams\",\n            \"nameLocation\": \"389:10:24\",\n            \"scope\": 30822,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 30565,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"748:16:24\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30564,\n              \"nodeType\": \"Block\",\n              \"src\": \"762:2:24\",\n              \"nodes\": [],\n              \"statements\": []\n            },\n            \"implemented\": true,\n            \"kind\": \"constructor\",\n            \"modifiers\": [],\n            \"name\": \"\",\n            \"nameLocation\": \"-1:-1:-1\",\n            \"parameters\": {\n              \"id\": 30562,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"759:2:24\"\n            },\n            \"returnParameters\": {\n              \"id\": 30563,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [],\n              \"src\": \"762:0:24\"\n            },\n            \"scope\": 30822,\n            \"stateMutability\": \"nonpayable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 30645,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"770:772:24\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30644,\n              \"nodeType\": \"Block\",\n              \"src\": \"868:674:24\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    30575\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30575,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"amountOut\",\n                      \"nameLocation\": \"886:9:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30644,\n                      \"src\": \"878:17:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30574,\n                        \"name\": \"uint256\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"878:7:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30576,\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"878:17:24\"\n                },\n                {\n                  \"assignments\": [\n                    30578\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30578,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"paramsArrayLength\",\n                      \"nameLocation\": \"913:17:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30644,\n                      \"src\": \"905:25:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30577,\n                        \"name\": \"uint256\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"905:7:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30581,\n                  \"initialValue\": {\n                    \"expression\": {\n                      \"id\": 30579,\n                      \"name\": \"paramsArray\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30569,\n                      \"src\": \"933:11:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30561_calldata_ptr_$dyn_calldata_ptr\",\n                        \"typeString\": \"struct SimulatorV1.SwapParams calldata[] calldata\"\n                      }\n                    },\n                    \"id\": 30580,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"memberLocation\": \"945:6:24\",\n                    \"memberName\": \"length\",\n                    \"nodeType\": \"MemberAccess\",\n                    \"src\": \"933:18:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"905:46:24\"\n                },\n                {\n                  \"body\": {\n                    \"id\": 30640,\n                    \"nodeType\": \"Block\",\n                    \"src\": \"1003:506:24\",\n                    \"statements\": [\n                      {\n                        \"assignments\": [\n                          30590\n                        ],\n                        \"declarations\": [\n                          {\n                            \"constant\": false,\n                            \"id\": 30590,\n                            \"mutability\": \"mutable\",\n                            \"name\": \"params\",\n                            \"nameLocation\": \"1035:6:24\",\n                            \"nodeType\": \"VariableDeclaration\",\n                            \"scope\": 30640,\n                            \"src\": \"1017:24:24\",\n                            \"stateVariable\": false,\n                            \"storageLocation\": \"memory\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                              \"typeString\": \"struct SimulatorV1.SwapParams\"\n                            },\n                            \"typeName\": {\n                              \"id\": 30589,\n                              \"nodeType\": \"UserDefinedTypeName\",\n                              \"pathNode\": {\n                                \"id\": 30588,\n                                \"name\": \"SwapParams\",\n                                \"nameLocations\": [\n                                  \"1017:10:24\"\n                                ],\n                                \"nodeType\": \"IdentifierPath\",\n                                \"referencedDeclaration\": 30561,\n                                \"src\": \"1017:10:24\"\n                              },\n                              \"referencedDeclaration\": 30561,\n                              \"src\": \"1017:10:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_struct$_SwapParams_$30561_storage_ptr\",\n                                \"typeString\": \"struct SimulatorV1.SwapParams\"\n                              }\n                            },\n                            \"visibility\": \"internal\"\n                          }\n                        ],\n                        \"id\": 30594,\n                        \"initialValue\": {\n                          \"baseExpression\": {\n                            \"id\": 30591,\n                            \"name\": \"paramsArray\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30569,\n                            \"src\": \"1044:11:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30561_calldata_ptr_$dyn_calldata_ptr\",\n                              \"typeString\": \"struct SimulatorV1.SwapParams calldata[] calldata\"\n                            }\n                          },\n                          \"id\": 30593,\n                          \"indexExpression\": {\n                            \"id\": 30592,\n                            \"name\": \"i\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30583,\n                            \"src\": \"1056:1:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint256\",\n                              \"typeString\": \"uint256\"\n                            }\n                          },\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"nodeType\": \"IndexAccess\",\n                          \"src\": \"1044:14:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30561_calldata_ptr\",\n                            \"typeString\": \"struct SimulatorV1.SwapParams calldata\"\n                          }\n                        },\n                        \"nodeType\": \"VariableDeclarationStatement\",\n                        \"src\": \"1017:41:24\"\n                      },\n                      {\n                        \"condition\": {\n                          \"commonType\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          },\n                          \"id\": 30597,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"leftExpression\": {\n                            \"id\": 30595,\n                            \"name\": \"amountOut\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30575,\n                            \"src\": \"1077:9:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint256\",\n                              \"typeString\": \"uint256\"\n                            }\n                          },\n                          \"nodeType\": \"BinaryOperation\",\n                          \"operator\": \"==\",\n                          \"rightExpression\": {\n                            \"hexValue\": \"30\",\n                            \"id\": 30596,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": true,\n                            \"kind\": \"number\",\n                            \"lValueRequested\": false,\n                            \"nodeType\": \"Literal\",\n                            \"src\": \"1090:1:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_rational_0_by_1\",\n                              \"typeString\": \"int_const 0\"\n                            },\n                            \"value\": \"0\"\n                          },\n                          \"src\": \"1077:14:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_bool\",\n                            \"typeString\": \"bool\"\n                          }\n                        },\n                        \"falseBody\": {\n                          \"id\": 30610,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"1157:58:24\",\n                          \"statements\": [\n                            {\n                              \"expression\": {\n                                \"id\": 30608,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"leftHandSide\": {\n                                  \"expression\": {\n                                    \"id\": 30604,\n                                    \"name\": \"params\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30590,\n                                    \"src\": \"1175:6:24\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                      \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                    }\n                                  },\n                                  \"id\": 30606,\n                                  \"isConstant\": false,\n                                  \"isLValue\": true,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": true,\n                                  \"memberLocation\": \"1182:6:24\",\n                                  \"memberName\": \"amount\",\n                                  \"nodeType\": \"MemberAccess\",\n                                  \"referencedDeclaration\": 30560,\n                                  \"src\": \"1175:13:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"nodeType\": \"Assignment\",\n                                \"operator\": \"=\",\n                                \"rightHandSide\": {\n                                  \"id\": 30607,\n                                  \"name\": \"amountOut\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30575,\n                                  \"src\": \"1191:9:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"src\": \"1175:25:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"id\": 30609,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"1175:25:24\"\n                            }\n                          ]\n                        },\n                        \"id\": 30611,\n                        \"nodeType\": \"IfStatement\",\n                        \"src\": \"1073:142:24\",\n                        \"trueBody\": {\n                          \"id\": 30603,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"1093:58:24\",\n                          \"statements\": [\n                            {\n                              \"expression\": {\n                                \"id\": 30601,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"leftHandSide\": {\n                                  \"id\": 30598,\n                                  \"name\": \"amountOut\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30575,\n                                  \"src\": \"1111:9:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"nodeType\": \"Assignment\",\n                                \"operator\": \"=\",\n                                \"rightHandSide\": {\n                                  \"expression\": {\n                                    \"id\": 30599,\n                                    \"name\": \"params\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30590,\n                                    \"src\": \"1123:6:24\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                      \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                    }\n                                  },\n                                  \"id\": 30600,\n                                  \"isConstant\": false,\n                                  \"isLValue\": true,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": false,\n                                  \"memberLocation\": \"1130:6:24\",\n                                  \"memberName\": \"amount\",\n                                  \"nodeType\": \"MemberAccess\",\n                                  \"referencedDeclaration\": 30560,\n                                  \"src\": \"1123:13:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"src\": \"1111:25:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"id\": 30602,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"1111:25:24\"\n                            }\n                          ]\n                        }\n                      },\n                      {\n                        \"condition\": {\n                          \"commonType\": {\n                            \"typeIdentifier\": \"t_uint8\",\n                            \"typeString\": \"uint8\"\n                          },\n                          \"id\": 30615,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"leftExpression\": {\n                            \"expression\": {\n                              \"id\": 30612,\n                              \"name\": \"params\",\n                              \"nodeType\": \"Identifier\",\n                              \"overloadedDeclarations\": [],\n                              \"referencedDeclaration\": 30590,\n                              \"src\": \"1233:6:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                              }\n                            },\n                            \"id\": 30613,\n                            \"isConstant\": false,\n                            \"isLValue\": true,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"memberLocation\": \"1240:8:24\",\n                            \"memberName\": \"protocol\",\n                            \"nodeType\": \"MemberAccess\",\n                            \"referencedDeclaration\": 30550,\n                            \"src\": \"1233:15:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_uint8\",\n                              \"typeString\": \"uint8\"\n                            }\n                          },\n                          \"nodeType\": \"BinaryOperation\",\n                          \"operator\": \"==\",\n                          \"rightExpression\": {\n                            \"hexValue\": \"30\",\n                            \"id\": 30614,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": true,\n                            \"kind\": \"number\",\n                            \"lValueRequested\": false,\n                            \"nodeType\": \"Literal\",\n                            \"src\": \"1252:1:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_rational_0_by_1\",\n                              \"typeString\": \"int_const 0\"\n                            },\n                            \"value\": \"0\"\n                          },\n                          \"src\": \"1233:20:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_bool\",\n                            \"typeString\": \"bool\"\n                          }\n                        },\n                        \"falseBody\": {\n                          \"condition\": {\n                            \"commonType\": {\n                              \"typeIdentifier\": \"t_uint8\",\n                              \"typeString\": \"uint8\"\n                            },\n                            \"id\": 30626,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"leftExpression\": {\n                              \"expression\": {\n                                \"id\": 30623,\n                                \"name\": \"params\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30590,\n                                \"src\": \"1341:6:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                  \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                }\n                              },\n                              \"id\": 30624,\n                              \"isConstant\": false,\n                              \"isLValue\": true,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"memberLocation\": \"1348:8:24\",\n                              \"memberName\": \"protocol\",\n                              \"nodeType\": \"MemberAccess\",\n                              \"referencedDeclaration\": 30550,\n                              \"src\": \"1341:15:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint8\",\n                                \"typeString\": \"uint8\"\n                              }\n                            },\n                            \"nodeType\": \"BinaryOperation\",\n                            \"operator\": \"==\",\n                            \"rightExpression\": {\n                              \"hexValue\": \"31\",\n                              \"id\": 30625,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": true,\n                              \"kind\": \"number\",\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"Literal\",\n                              \"src\": \"1360:1:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_rational_1_by_1\",\n                                \"typeString\": \"int_const 1\"\n                              },\n                              \"value\": \"1\"\n                            },\n                            \"src\": \"1341:20:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_bool\",\n                              \"typeString\": \"bool\"\n                            }\n                          },\n                          \"id\": 30634,\n                          \"nodeType\": \"IfStatement\",\n                          \"src\": \"1337:102:24\",\n                          \"trueBody\": {\n                            \"id\": 30633,\n                            \"nodeType\": \"Block\",\n                            \"src\": \"1363:76:24\",\n                            \"statements\": [\n                              {\n                                \"expression\": {\n                                  \"id\": 30631,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": false,\n                                  \"leftHandSide\": {\n                                    \"id\": 30627,\n                                    \"name\": \"amountOut\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30575,\n                                    \"src\": \"1381:9:24\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_uint256\",\n                                      \"typeString\": \"uint256\"\n                                    }\n                                  },\n                                  \"nodeType\": \"Assignment\",\n                                  \"operator\": \"=\",\n                                  \"rightHandSide\": {\n                                    \"arguments\": [\n                                      {\n                                        \"id\": 30629,\n                                        \"name\": \"params\",\n                                        \"nodeType\": \"Identifier\",\n                                        \"overloadedDeclarations\": [],\n                                        \"referencedDeclaration\": 30590,\n                                        \"src\": \"1417:6:24\",\n                                        \"typeDescriptions\": {\n                                          \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                          \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                        }\n                                      }\n                                    ],\n                                    \"expression\": {\n                                      \"argumentTypes\": [\n                                        {\n                                          \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                          \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                        }\n                                      ],\n                                      \"id\": 30628,\n                                      \"name\": \"simulateUniswapV3SwapIn\",\n                                      \"nodeType\": \"Identifier\",\n                                      \"overloadedDeclarations\": [],\n                                      \"referencedDeclaration\": 30743,\n                                      \"src\": \"1393:23:24\",\n                                      \"typeDescriptions\": {\n                                        \"typeIdentifier\": \"t_function_internal_nonpayable$_t_struct$_SwapParams_$30561_memory_ptr_$returns$_t_uint256_$\",\n                                        \"typeString\": \"function (struct SimulatorV1.SwapParams memory) returns (uint256)\"\n                                      }\n                                    },\n                                    \"id\": 30630,\n                                    \"isConstant\": false,\n                                    \"isLValue\": false,\n                                    \"isPure\": false,\n                                    \"kind\": \"functionCall\",\n                                    \"lValueRequested\": false,\n                                    \"nameLocations\": [],\n                                    \"names\": [],\n                                    \"nodeType\": \"FunctionCall\",\n                                    \"src\": \"1393:31:24\",\n                                    \"tryCall\": false,\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_uint256\",\n                                      \"typeString\": \"uint256\"\n                                    }\n                                  },\n                                  \"src\": \"1381:43:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"id\": 30632,\n                                \"nodeType\": \"ExpressionStatement\",\n                                \"src\": \"1381:43:24\"\n                              }\n                            ]\n                          }\n                        },\n                        \"id\": 30635,\n                        \"nodeType\": \"IfStatement\",\n                        \"src\": \"1229:210:24\",\n                        \"trueBody\": {\n                          \"id\": 30622,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"1255:76:24\",\n                          \"statements\": [\n                            {\n                              \"expression\": {\n                                \"id\": 30620,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"leftHandSide\": {\n                                  \"id\": 30616,\n                                  \"name\": \"amountOut\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30575,\n                                  \"src\": \"1273:9:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"nodeType\": \"Assignment\",\n                                \"operator\": \"=\",\n                                \"rightHandSide\": {\n                                  \"arguments\": [\n                                    {\n                                      \"id\": 30618,\n                                      \"name\": \"params\",\n                                      \"nodeType\": \"Identifier\",\n                                      \"overloadedDeclarations\": [],\n                                      \"referencedDeclaration\": 30590,\n                                      \"src\": \"1309:6:24\",\n                                      \"typeDescriptions\": {\n                                        \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                        \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                      }\n                                    }\n                                  ],\n                                  \"expression\": {\n                                    \"argumentTypes\": [\n                                      {\n                                        \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                        \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                      }\n                                    ],\n                                    \"id\": 30617,\n                                    \"name\": \"simulateUniswapV2SwapIn\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30678,\n                                    \"src\": \"1285:23:24\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_function_internal_view$_t_struct$_SwapParams_$30561_memory_ptr_$returns$_t_uint256_$\",\n                                      \"typeString\": \"function (struct SimulatorV1.SwapParams memory) view returns (uint256)\"\n                                    }\n                                  },\n                                  \"id\": 30619,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"kind\": \"functionCall\",\n                                  \"lValueRequested\": false,\n                                  \"nameLocations\": [],\n                                  \"names\": [],\n                                  \"nodeType\": \"FunctionCall\",\n                                  \"src\": \"1285:31:24\",\n                                  \"tryCall\": false,\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_uint256\",\n                                    \"typeString\": \"uint256\"\n                                  }\n                                },\n                                \"src\": \"1273:43:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"id\": 30621,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"1273:43:24\"\n                            }\n                          ]\n                        }\n                      },\n                      {\n                        \"id\": 30639,\n                        \"nodeType\": \"UncheckedBlock\",\n                        \"src\": \"1453:46:24\",\n                        \"statements\": [\n                          {\n                            \"expression\": {\n                              \"id\": 30637,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"UnaryOperation\",\n                              \"operator\": \"++\",\n                              \"prefix\": true,\n                              \"src\": \"1481:3:24\",\n                              \"subExpression\": {\n                                \"id\": 30636,\n                                \"name\": \"i\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30583,\n                                \"src\": \"1483:1:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_uint256\",\n                                  \"typeString\": \"uint256\"\n                                }\n                              },\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_uint256\",\n                                \"typeString\": \"uint256\"\n                              }\n                            },\n                            \"id\": 30638,\n                            \"nodeType\": \"ExpressionStatement\",\n                            \"src\": \"1481:3:24\"\n                          }\n                        ]\n                      }\n                    ]\n                  },\n                  \"condition\": {\n                    \"commonType\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    },\n                    \"id\": 30587,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftExpression\": {\n                      \"id\": 30585,\n                      \"name\": \"i\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30583,\n                      \"src\": \"978:1:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"BinaryOperation\",\n                    \"operator\": \"<\",\n                    \"rightExpression\": {\n                      \"id\": 30586,\n                      \"name\": \"paramsArrayLength\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30578,\n                      \"src\": \"982:17:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"978:21:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_bool\",\n                      \"typeString\": \"bool\"\n                    }\n                  },\n                  \"id\": 30641,\n                  \"initializationExpression\": {\n                    \"assignments\": [\n                      30583\n                    ],\n                    \"declarations\": [\n                      {\n                        \"constant\": false,\n                        \"id\": 30583,\n                        \"mutability\": \"mutable\",\n                        \"name\": \"i\",\n                        \"nameLocation\": \"975:1:24\",\n                        \"nodeType\": \"VariableDeclaration\",\n                        \"scope\": 30641,\n                        \"src\": \"967:9:24\",\n                        \"stateVariable\": false,\n                        \"storageLocation\": \"default\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        },\n                        \"typeName\": {\n                          \"id\": 30582,\n                          \"name\": \"uint256\",\n                          \"nodeType\": \"ElementaryTypeName\",\n                          \"src\": \"967:7:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        \"visibility\": \"internal\"\n                      }\n                    ],\n                    \"id\": 30584,\n                    \"nodeType\": \"VariableDeclarationStatement\",\n                    \"src\": \"967:9:24\"\n                  },\n                  \"nodeType\": \"ForStatement\",\n                  \"src\": \"962:547:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30642,\n                    \"name\": \"amountOut\",\n                    \"nodeType\": \"Identifier\",\n                    \"overloadedDeclarations\": [],\n                    \"referencedDeclaration\": 30575,\n                    \"src\": \"1526:9:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"functionReturnParameters\": 30573,\n                  \"id\": 30643,\n                  \"nodeType\": \"Return\",\n                  \"src\": \"1519:16:24\"\n                }\n              ]\n            },\n            \"functionSelector\": \"55abbafc\",\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"simulateSwapIn\",\n            \"nameLocation\": \"779:14:24\",\n            \"parameters\": {\n              \"id\": 30570,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30569,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"paramsArray\",\n                  \"nameLocation\": \"825:11:24\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30645,\n                  \"src\": \"803:33:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"calldata\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30561_calldata_ptr_$dyn_calldata_ptr\",\n                    \"typeString\": \"struct SimulatorV1.SwapParams[]\"\n                  },\n                  \"typeName\": {\n                    \"baseType\": {\n                      \"id\": 30567,\n                      \"nodeType\": \"UserDefinedTypeName\",\n                      \"pathNode\": {\n                        \"id\": 30566,\n                        \"name\": \"SwapParams\",\n                        \"nameLocations\": [\n                          \"803:10:24\"\n                        ],\n                        \"nodeType\": \"IdentifierPath\",\n                        \"referencedDeclaration\": 30561,\n                        \"src\": \"803:10:24\"\n                      },\n                      \"referencedDeclaration\": 30561,\n                      \"src\": \"803:10:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_struct$_SwapParams_$30561_storage_ptr\",\n                        \"typeString\": \"struct SimulatorV1.SwapParams\"\n                      }\n                    },\n                    \"id\": 30568,\n                    \"nodeType\": \"ArrayTypeName\",\n                    \"src\": \"803:12:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_array$_t_struct$_SwapParams_$30561_storage_$dyn_storage_ptr\",\n                      \"typeString\": \"struct SimulatorV1.SwapParams[]\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"793:49:24\"\n            },\n            \"returnParameters\": {\n              \"id\": 30573,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30572,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"\",\n                  \"nameLocation\": \"-1:-1:-1\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30645,\n                  \"src\": \"859:7:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 30571,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"859:7:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"858:9:24\"\n            },\n            \"scope\": 30822,\n            \"stateMutability\": \"nonpayable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 30678,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"1548:424:24\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30677,\n              \"nodeType\": \"Block\",\n              \"src\": \"1661:311:24\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    30654,\n                    30656\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30654,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"reserveIn\",\n                      \"nameLocation\": \"1677:9:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30677,\n                      \"src\": \"1672:14:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30653,\n                        \"name\": \"uint\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"1672:4:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    },\n                    {\n                      \"constant\": false,\n                      \"id\": 30656,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"reserveOut\",\n                      \"nameLocation\": \"1693:10:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30677,\n                      \"src\": \"1688:15:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30655,\n                        \"name\": \"uint\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"1688:4:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_uint256\",\n                          \"typeString\": \"uint256\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30666,\n                  \"initialValue\": {\n                    \"arguments\": [\n                      {\n                        \"expression\": {\n                          \"id\": 30659,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30648,\n                          \"src\": \"1749:6:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                            \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 30660,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"1756:7:24\",\n                        \"memberName\": \"handler\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30552,\n                        \"src\": \"1749:14:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      },\n                      {\n                        \"expression\": {\n                          \"id\": 30661,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30648,\n                          \"src\": \"1777:6:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                            \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 30662,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"1784:7:24\",\n                        \"memberName\": \"tokenIn\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30554,\n                        \"src\": \"1777:14:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      },\n                      {\n                        \"expression\": {\n                          \"id\": 30663,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30648,\n                          \"src\": \"1805:6:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                            \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 30664,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"1812:8:24\",\n                        \"memberName\": \"tokenOut\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30556,\n                        \"src\": \"1805:15:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      }\n                    ],\n                    \"expression\": {\n                      \"argumentTypes\": [\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        },\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      ],\n                      \"expression\": {\n                        \"id\": 30657,\n                        \"name\": \"UniswapV2Library\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 32281,\n                        \"src\": \"1707:16:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_type$_t_contract$_UniswapV2Library_$32281_$\",\n                          \"typeString\": \"type(library UniswapV2Library)\"\n                        }\n                      },\n                      \"id\": 30658,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"1724:11:24\",\n                      \"memberName\": \"getReserves\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31994,\n                      \"src\": \"1707:28:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_function_internal_view$_t_address_$_t_address_$_t_address_$returns$_t_uint256_$_t_uint256_$\",\n                        \"typeString\": \"function (address,address,address) view returns (uint256,uint256)\"\n                      }\n                    },\n                    \"id\": 30665,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"kind\": \"functionCall\",\n                    \"lValueRequested\": false,\n                    \"nameLocations\": [],\n                    \"names\": [],\n                    \"nodeType\": \"FunctionCall\",\n                    \"src\": \"1707:123:24\",\n                    \"tryCall\": false,\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_tuple$_t_uint256_$_t_uint256_$\",\n                      \"typeString\": \"tuple(uint256,uint256)\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"1671:159:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30675,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"id\": 30667,\n                      \"name\": \"amountOut\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30651,\n                      \"src\": \"1840:9:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"arguments\": [\n                        {\n                          \"expression\": {\n                            \"id\": 30670,\n                            \"name\": \"params\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30648,\n                            \"src\": \"1895:6:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                              \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                            }\n                          },\n                          \"id\": 30671,\n                          \"isConstant\": false,\n                          \"isLValue\": true,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"memberLocation\": \"1902:6:24\",\n                          \"memberName\": \"amount\",\n                          \"nodeType\": \"MemberAccess\",\n                          \"referencedDeclaration\": 30560,\n                          \"src\": \"1895:13:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        {\n                          \"id\": 30672,\n                          \"name\": \"reserveIn\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30654,\n                          \"src\": \"1922:9:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        {\n                          \"id\": 30673,\n                          \"name\": \"reserveOut\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30656,\n                          \"src\": \"1945:10:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        }\n                      ],\n                      \"expression\": {\n                        \"argumentTypes\": [\n                          {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          },\n                          {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          },\n                          {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        ],\n                        \"expression\": {\n                          \"id\": 30668,\n                          \"name\": \"UniswapV2Library\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 32281,\n                          \"src\": \"1852:16:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_type$_t_contract$_UniswapV2Library_$32281_$\",\n                            \"typeString\": \"type(library UniswapV2Library)\"\n                          }\n                        },\n                        \"id\": 30669,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"1869:12:24\",\n                        \"memberName\": \"getAmountOut\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 32054,\n                        \"src\": \"1852:29:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_function_internal_pure$_t_uint256_$_t_uint256_$_t_uint256_$returns$_t_uint256_$\",\n                          \"typeString\": \"function (uint256,uint256,uint256) pure returns (uint256)\"\n                        }\n                      },\n                      \"id\": 30674,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"kind\": \"functionCall\",\n                      \"lValueRequested\": false,\n                      \"nameLocations\": [],\n                      \"names\": [],\n                      \"nodeType\": \"FunctionCall\",\n                      \"src\": \"1852:113:24\",\n                      \"tryCall\": false,\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"1840:125:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"id\": 30676,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"1840:125:24\"\n                }\n              ]\n            },\n            \"functionSelector\": \"76637028\",\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"simulateUniswapV2SwapIn\",\n            \"nameLocation\": \"1557:23:24\",\n            \"parameters\": {\n              \"id\": 30649,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30648,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"params\",\n                  \"nameLocation\": \"1608:6:24\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30678,\n                  \"src\": \"1590:24:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"memory\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                    \"typeString\": \"struct SimulatorV1.SwapParams\"\n                  },\n                  \"typeName\": {\n                    \"id\": 30647,\n                    \"nodeType\": \"UserDefinedTypeName\",\n                    \"pathNode\": {\n                      \"id\": 30646,\n                      \"name\": \"SwapParams\",\n                      \"nameLocations\": [\n                        \"1590:10:24\"\n                      ],\n                      \"nodeType\": \"IdentifierPath\",\n                      \"referencedDeclaration\": 30561,\n                      \"src\": \"1590:10:24\"\n                    },\n                    \"referencedDeclaration\": 30561,\n                    \"src\": \"1590:10:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_struct$_SwapParams_$30561_storage_ptr\",\n                      \"typeString\": \"struct SimulatorV1.SwapParams\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"1580:40:24\"\n            },\n            \"returnParameters\": {\n              \"id\": 30652,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30651,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"amountOut\",\n                  \"nameLocation\": \"1650:9:24\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30678,\n                  \"src\": \"1642:17:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 30650,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"1642:7:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"1641:19:24\"\n            },\n            \"scope\": 30822,\n            \"stateMutability\": \"view\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 30743,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"1978:534:24\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30742,\n              \"nodeType\": \"Block\",\n              \"src\": \"2086:426:24\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    30688\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30688,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"quoter\",\n                      \"nameLocation\": \"2106:6:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30742,\n                      \"src\": \"2096:16:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_contract$_IQuoterV2_$31504\",\n                        \"typeString\": \"contract IQuoterV2\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30687,\n                        \"nodeType\": \"UserDefinedTypeName\",\n                        \"pathNode\": {\n                          \"id\": 30686,\n                          \"name\": \"IQuoterV2\",\n                          \"nameLocations\": [\n                            \"2096:9:24\"\n                          ],\n                          \"nodeType\": \"IdentifierPath\",\n                          \"referencedDeclaration\": 31504,\n                          \"src\": \"2096:9:24\"\n                        },\n                        \"referencedDeclaration\": 31504,\n                        \"src\": \"2096:9:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_contract$_IQuoterV2_$31504\",\n                          \"typeString\": \"contract IQuoterV2\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30693,\n                  \"initialValue\": {\n                    \"arguments\": [\n                      {\n                        \"expression\": {\n                          \"id\": 30690,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30681,\n                          \"src\": \"2125:6:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                            \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 30691,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"2132:7:24\",\n                        \"memberName\": \"handler\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30552,\n                        \"src\": \"2125:14:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      }\n                    ],\n                    \"expression\": {\n                      \"argumentTypes\": [\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      ],\n                      \"id\": 30689,\n                      \"name\": \"IQuoterV2\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31504,\n                      \"src\": \"2115:9:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_type$_t_contract$_IQuoterV2_$31504_$\",\n                        \"typeString\": \"type(contract IQuoterV2)\"\n                      }\n                    },\n                    \"id\": 30692,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"kind\": \"typeConversion\",\n                    \"lValueRequested\": false,\n                    \"nameLocations\": [],\n                    \"names\": [],\n                    \"nodeType\": \"FunctionCall\",\n                    \"src\": \"2115:25:24\",\n                    \"tryCall\": false,\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_contract$_IQuoterV2_$31504\",\n                      \"typeString\": \"contract IQuoterV2\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2096:44:24\"\n                },\n                {\n                  \"assignments\": [\n                    30698\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30698,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"quoterParams\",\n                      \"nameLocation\": \"2195:12:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30742,\n                      \"src\": \"2150:57:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"memory\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                        \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30697,\n                        \"nodeType\": \"UserDefinedTypeName\",\n                        \"pathNode\": {\n                          \"id\": 30696,\n                          \"name\": \"IQuoterV2.QuoteExactInputSingleParams\",\n                          \"nameLocations\": [\n                            \"2150:9:24\",\n                            \"2160:27:24\"\n                          ],\n                          \"nodeType\": \"IdentifierPath\",\n                          \"referencedDeclaration\": 31444,\n                          \"src\": \"2150:37:24\"\n                        },\n                        \"referencedDeclaration\": 31444,\n                        \"src\": \"2150:37:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_storage_ptr\",\n                          \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30699,\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2150:57:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30705,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"expression\": {\n                        \"id\": 30700,\n                        \"name\": \"quoterParams\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30698,\n                        \"src\": \"2217:12:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                          \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams memory\"\n                        }\n                      },\n                      \"id\": 30702,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"memberLocation\": \"2230:7:24\",\n                      \"memberName\": \"tokenIn\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31435,\n                      \"src\": \"2217:20:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"expression\": {\n                        \"id\": 30703,\n                        \"name\": \"params\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30681,\n                        \"src\": \"2240:6:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                          \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                        }\n                      },\n                      \"id\": 30704,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"2247:7:24\",\n                      \"memberName\": \"tokenIn\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 30554,\n                      \"src\": \"2240:14:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"src\": \"2217:37:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_address\",\n                      \"typeString\": \"address\"\n                    }\n                  },\n                  \"id\": 30706,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"2217:37:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30712,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"expression\": {\n                        \"id\": 30707,\n                        \"name\": \"quoterParams\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30698,\n                        \"src\": \"2264:12:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                          \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams memory\"\n                        }\n                      },\n                      \"id\": 30709,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"memberLocation\": \"2277:8:24\",\n                      \"memberName\": \"tokenOut\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31437,\n                      \"src\": \"2264:21:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"expression\": {\n                        \"id\": 30710,\n                        \"name\": \"params\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30681,\n                        \"src\": \"2288:6:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                          \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                        }\n                      },\n                      \"id\": 30711,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"2295:8:24\",\n                      \"memberName\": \"tokenOut\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 30556,\n                      \"src\": \"2288:15:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_address\",\n                        \"typeString\": \"address\"\n                      }\n                    },\n                    \"src\": \"2264:39:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_address\",\n                      \"typeString\": \"address\"\n                    }\n                  },\n                  \"id\": 30713,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"2264:39:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30719,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"expression\": {\n                        \"id\": 30714,\n                        \"name\": \"quoterParams\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30698,\n                        \"src\": \"2313:12:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                          \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams memory\"\n                        }\n                      },\n                      \"id\": 30716,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"memberLocation\": \"2326:8:24\",\n                      \"memberName\": \"amountIn\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31439,\n                      \"src\": \"2313:21:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"expression\": {\n                        \"id\": 30717,\n                        \"name\": \"params\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30681,\n                        \"src\": \"2337:6:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                          \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                        }\n                      },\n                      \"id\": 30718,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"2344:6:24\",\n                      \"memberName\": \"amount\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 30560,\n                      \"src\": \"2337:13:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"2313:37:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"id\": 30720,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"2313:37:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30726,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"expression\": {\n                        \"id\": 30721,\n                        \"name\": \"quoterParams\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30698,\n                        \"src\": \"2360:12:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                          \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams memory\"\n                        }\n                      },\n                      \"id\": 30723,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"memberLocation\": \"2373:3:24\",\n                      \"memberName\": \"fee\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31441,\n                      \"src\": \"2360:16:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint24\",\n                        \"typeString\": \"uint24\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"expression\": {\n                        \"id\": 30724,\n                        \"name\": \"params\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30681,\n                        \"src\": \"2379:6:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                          \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                        }\n                      },\n                      \"id\": 30725,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": false,\n                      \"memberLocation\": \"2386:3:24\",\n                      \"memberName\": \"fee\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 30558,\n                      \"src\": \"2379:10:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint24\",\n                        \"typeString\": \"uint24\"\n                      }\n                    },\n                    \"src\": \"2360:29:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint24\",\n                      \"typeString\": \"uint24\"\n                    }\n                  },\n                  \"id\": 30727,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"2360:29:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30732,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"expression\": {\n                        \"id\": 30728,\n                        \"name\": \"quoterParams\",\n                        \"nodeType\": \"Identifier\",\n                        \"overloadedDeclarations\": [],\n                        \"referencedDeclaration\": 30698,\n                        \"src\": \"2399:12:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                          \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams memory\"\n                        }\n                      },\n                      \"id\": 30730,\n                      \"isConstant\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"memberLocation\": \"2412:17:24\",\n                      \"memberName\": \"sqrtPriceLimitX96\",\n                      \"nodeType\": \"MemberAccess\",\n                      \"referencedDeclaration\": 31443,\n                      \"src\": \"2399:30:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint160\",\n                        \"typeString\": \"uint160\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"hexValue\": \"30\",\n                      \"id\": 30731,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": true,\n                      \"kind\": \"number\",\n                      \"lValueRequested\": false,\n                      \"nodeType\": \"Literal\",\n                      \"src\": \"2432:1:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_rational_0_by_1\",\n                        \"typeString\": \"int_const 0\"\n                      },\n                      \"value\": \"0\"\n                    },\n                    \"src\": \"2399:34:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint160\",\n                      \"typeString\": \"uint160\"\n                    }\n                  },\n                  \"id\": 30733,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"2399:34:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30740,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"components\": [\n                        {\n                          \"id\": 30734,\n                          \"name\": \"amountOut\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30684,\n                          \"src\": \"2444:9:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        },\n                        null,\n                        null,\n                        null\n                      ],\n                      \"id\": 30735,\n                      \"isConstant\": false,\n                      \"isInlineArray\": false,\n                      \"isLValue\": true,\n                      \"isPure\": false,\n                      \"lValueRequested\": true,\n                      \"nodeType\": \"TupleExpression\",\n                      \"src\": \"2443:17:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_tuple$_t_uint256_$__$__$__$\",\n                        \"typeString\": \"tuple(uint256,,,)\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"arguments\": [\n                        {\n                          \"id\": 30738,\n                          \"name\": \"quoterParams\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30698,\n                          \"src\": \"2492:12:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                            \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams memory\"\n                          }\n                        }\n                      ],\n                      \"expression\": {\n                        \"argumentTypes\": [\n                          {\n                            \"typeIdentifier\": \"t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr\",\n                            \"typeString\": \"struct IQuoterV2.QuoteExactInputSingleParams memory\"\n                          }\n                        ],\n                        \"expression\": {\n                          \"id\": 30736,\n                          \"name\": \"quoter\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30688,\n                          \"src\": \"2463:6:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_contract$_IQuoterV2_$31504\",\n                            \"typeString\": \"contract IQuoterV2\"\n                          }\n                        },\n                        \"id\": 30737,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"2470:21:24\",\n                        \"memberName\": \"quoteExactInputSingle\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 31459,\n                        \"src\": \"2463:28:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_function_external_nonpayable$_t_struct$_QuoteExactInputSingleParams_$31444_memory_ptr_$returns$_t_uint256_$_t_uint160_$_t_uint32_$_t_uint256_$\",\n                          \"typeString\": \"function (struct IQuoterV2.QuoteExactInputSingleParams memory) external returns (uint256,uint160,uint32,uint256)\"\n                        }\n                      },\n                      \"id\": 30739,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"kind\": \"functionCall\",\n                      \"lValueRequested\": false,\n                      \"nameLocations\": [],\n                      \"names\": [],\n                      \"nodeType\": \"FunctionCall\",\n                      \"src\": \"2463:42:24\",\n                      \"tryCall\": false,\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_tuple$_t_uint256_$_t_uint160_$_t_uint32_$_t_uint256_$\",\n                        \"typeString\": \"tuple(uint256,uint160,uint32,uint256)\"\n                      }\n                    },\n                    \"src\": \"2443:62:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_tuple$__$\",\n                      \"typeString\": \"tuple()\"\n                    }\n                  },\n                  \"id\": 30741,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"2443:62:24\"\n                }\n              ]\n            },\n            \"functionSelector\": \"8e888ccc\",\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"simulateUniswapV3SwapIn\",\n            \"nameLocation\": \"1987:23:24\",\n            \"parameters\": {\n              \"id\": 30682,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30681,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"params\",\n                  \"nameLocation\": \"2038:6:24\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30743,\n                  \"src\": \"2020:24:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"memory\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                    \"typeString\": \"struct SimulatorV1.SwapParams\"\n                  },\n                  \"typeName\": {\n                    \"id\": 30680,\n                    \"nodeType\": \"UserDefinedTypeName\",\n                    \"pathNode\": {\n                      \"id\": 30679,\n                      \"name\": \"SwapParams\",\n                      \"nameLocations\": [\n                        \"2020:10:24\"\n                      ],\n                      \"nodeType\": \"IdentifierPath\",\n                      \"referencedDeclaration\": 30561,\n                      \"src\": \"2020:10:24\"\n                    },\n                    \"referencedDeclaration\": 30561,\n                    \"src\": \"2020:10:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_struct$_SwapParams_$30561_storage_ptr\",\n                      \"typeString\": \"struct SimulatorV1.SwapParams\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"2010:40:24\"\n            },\n            \"returnParameters\": {\n              \"id\": 30685,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30684,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"amountOut\",\n                  \"nameLocation\": \"2075:9:24\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30743,\n                  \"src\": \"2067:17:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 30683,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"2067:7:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"2066:19:24\"\n            },\n            \"scope\": 30822,\n            \"stateMutability\": \"nonpayable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          },\n          {\n            \"id\": 30821,\n            \"nodeType\": \"FunctionDefinition\",\n            \"src\": \"2518:661:24\",\n            \"nodes\": [],\n            \"body\": {\n              \"id\": 30820,\n              \"nodeType\": \"Block\",\n              \"src\": \"2622:557:24\",\n              \"nodes\": [],\n              \"statements\": [\n                {\n                  \"assignments\": [\n                    30753\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30753,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"pool\",\n                      \"nameLocation\": \"2643:4:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30820,\n                      \"src\": \"2632:15:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_contract$_ICurvePool_$31411\",\n                        \"typeString\": \"contract ICurvePool\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30752,\n                        \"nodeType\": \"UserDefinedTypeName\",\n                        \"pathNode\": {\n                          \"id\": 30751,\n                          \"name\": \"ICurvePool\",\n                          \"nameLocations\": [\n                            \"2632:10:24\"\n                          ],\n                          \"nodeType\": \"IdentifierPath\",\n                          \"referencedDeclaration\": 31411,\n                          \"src\": \"2632:10:24\"\n                        },\n                        \"referencedDeclaration\": 31411,\n                        \"src\": \"2632:10:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_contract$_ICurvePool_$31411\",\n                          \"typeString\": \"contract ICurvePool\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30758,\n                  \"initialValue\": {\n                    \"arguments\": [\n                      {\n                        \"expression\": {\n                          \"id\": 30755,\n                          \"name\": \"params\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30746,\n                          \"src\": \"2661:6:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                            \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                          }\n                        },\n                        \"id\": 30756,\n                        \"isConstant\": false,\n                        \"isLValue\": true,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"2668:7:24\",\n                        \"memberName\": \"handler\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 30552,\n                        \"src\": \"2661:14:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      }\n                    ],\n                    \"expression\": {\n                      \"argumentTypes\": [\n                        {\n                          \"typeIdentifier\": \"t_address\",\n                          \"typeString\": \"address\"\n                        }\n                      ],\n                      \"id\": 30754,\n                      \"name\": \"ICurvePool\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 31411,\n                      \"src\": \"2650:10:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_type$_t_contract$_ICurvePool_$31411_$\",\n                        \"typeString\": \"type(contract ICurvePool)\"\n                      }\n                    },\n                    \"id\": 30757,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"kind\": \"typeConversion\",\n                    \"lValueRequested\": false,\n                    \"nameLocations\": [],\n                    \"names\": [],\n                    \"nodeType\": \"FunctionCall\",\n                    \"src\": \"2650:26:24\",\n                    \"tryCall\": false,\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_contract$_ICurvePool_$31411\",\n                      \"typeString\": \"contract ICurvePool\"\n                    }\n                  },\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2632:44:24\"\n                },\n                {\n                  \"assignments\": [\n                    30760\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30760,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"i\",\n                      \"nameLocation\": \"2694:1:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30820,\n                      \"src\": \"2687:8:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_int128\",\n                        \"typeString\": \"int128\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30759,\n                        \"name\": \"int128\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"2687:6:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_int128\",\n                          \"typeString\": \"int128\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30761,\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2687:8:24\"\n                },\n                {\n                  \"assignments\": [\n                    30763\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30763,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"j\",\n                      \"nameLocation\": \"2712:1:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30820,\n                      \"src\": \"2705:8:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_int128\",\n                        \"typeString\": \"int128\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30762,\n                        \"name\": \"int128\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"2705:6:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_int128\",\n                          \"typeString\": \"int128\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30764,\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2705:8:24\"\n                },\n                {\n                  \"assignments\": [\n                    30766\n                  ],\n                  \"declarations\": [\n                    {\n                      \"constant\": false,\n                      \"id\": 30766,\n                      \"mutability\": \"mutable\",\n                      \"name\": \"coinIdx\",\n                      \"nameLocation\": \"2731:7:24\",\n                      \"nodeType\": \"VariableDeclaration\",\n                      \"scope\": 30820,\n                      \"src\": \"2724:14:24\",\n                      \"stateVariable\": false,\n                      \"storageLocation\": \"default\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_int128\",\n                        \"typeString\": \"int128\"\n                      },\n                      \"typeName\": {\n                        \"id\": 30765,\n                        \"name\": \"int128\",\n                        \"nodeType\": \"ElementaryTypeName\",\n                        \"src\": \"2724:6:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_int128\",\n                          \"typeString\": \"int128\"\n                        }\n                      },\n                      \"visibility\": \"internal\"\n                    }\n                  ],\n                  \"id\": 30767,\n                  \"nodeType\": \"VariableDeclarationStatement\",\n                  \"src\": \"2724:14:24\"\n                },\n                {\n                  \"body\": {\n                    \"id\": 30808,\n                    \"nodeType\": \"Block\",\n                    \"src\": \"2764:354:24\",\n                    \"statements\": [\n                      {\n                        \"assignments\": [\n                          30772\n                        ],\n                        \"declarations\": [\n                          {\n                            \"constant\": false,\n                            \"id\": 30772,\n                            \"mutability\": \"mutable\",\n                            \"name\": \"coin\",\n                            \"nameLocation\": \"2786:4:24\",\n                            \"nodeType\": \"VariableDeclaration\",\n                            \"scope\": 30808,\n                            \"src\": \"2778:12:24\",\n                            \"stateVariable\": false,\n                            \"storageLocation\": \"default\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            },\n                            \"typeName\": {\n                              \"id\": 30771,\n                              \"name\": \"address\",\n                              \"nodeType\": \"ElementaryTypeName\",\n                              \"src\": \"2778:7:24\",\n                              \"stateMutability\": \"nonpayable\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            },\n                            \"visibility\": \"internal\"\n                          }\n                        ],\n                        \"id\": 30777,\n                        \"initialValue\": {\n                          \"arguments\": [\n                            {\n                              \"id\": 30775,\n                              \"name\": \"coinIdx\",\n                              \"nodeType\": \"Identifier\",\n                              \"overloadedDeclarations\": [],\n                              \"referencedDeclaration\": 30766,\n                              \"src\": \"2804:7:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_int128\",\n                                \"typeString\": \"int128\"\n                              }\n                            }\n                          ],\n                          \"expression\": {\n                            \"argumentTypes\": [\n                              {\n                                \"typeIdentifier\": \"t_int128\",\n                                \"typeString\": \"int128\"\n                              }\n                            ],\n                            \"expression\": {\n                              \"id\": 30773,\n                              \"name\": \"pool\",\n                              \"nodeType\": \"Identifier\",\n                              \"overloadedDeclarations\": [],\n                              \"referencedDeclaration\": 30753,\n                              \"src\": \"2793:4:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_contract$_ICurvePool_$31411\",\n                                \"typeString\": \"contract ICurvePool\"\n                              }\n                            },\n                            \"id\": 30774,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"memberLocation\": \"2798:5:24\",\n                            \"memberName\": \"coins\",\n                            \"nodeType\": \"MemberAccess\",\n                            \"referencedDeclaration\": 31346,\n                            \"src\": \"2793:10:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_function_external_nonpayable$_t_int128_$returns$_t_address_$\",\n                              \"typeString\": \"function (int128) external returns (address)\"\n                            }\n                          },\n                          \"id\": 30776,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"kind\": \"functionCall\",\n                          \"lValueRequested\": false,\n                          \"nameLocations\": [],\n                          \"names\": [],\n                          \"nodeType\": \"FunctionCall\",\n                          \"src\": \"2793:19:24\",\n                          \"tryCall\": false,\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_address\",\n                            \"typeString\": \"address\"\n                          }\n                        },\n                        \"nodeType\": \"VariableDeclarationStatement\",\n                        \"src\": \"2778:34:24\"\n                      },\n                      {\n                        \"condition\": {\n                          \"commonType\": {\n                            \"typeIdentifier\": \"t_address\",\n                            \"typeString\": \"address\"\n                          },\n                          \"id\": 30781,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"leftExpression\": {\n                            \"id\": 30778,\n                            \"name\": \"coin\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30772,\n                            \"src\": \"2831:4:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            }\n                          },\n                          \"nodeType\": \"BinaryOperation\",\n                          \"operator\": \"==\",\n                          \"rightExpression\": {\n                            \"expression\": {\n                              \"id\": 30779,\n                              \"name\": \"params\",\n                              \"nodeType\": \"Identifier\",\n                              \"overloadedDeclarations\": [],\n                              \"referencedDeclaration\": 30746,\n                              \"src\": \"2839:6:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                              }\n                            },\n                            \"id\": 30780,\n                            \"isConstant\": false,\n                            \"isLValue\": true,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"memberLocation\": \"2846:7:24\",\n                            \"memberName\": \"tokenIn\",\n                            \"nodeType\": \"MemberAccess\",\n                            \"referencedDeclaration\": 30554,\n                            \"src\": \"2839:14:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            }\n                          },\n                          \"src\": \"2831:22:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_bool\",\n                            \"typeString\": \"bool\"\n                          }\n                        },\n                        \"falseBody\": {\n                          \"condition\": {\n                            \"commonType\": {\n                              \"typeIdentifier\": \"t_address\",\n                              \"typeString\": \"address\"\n                            },\n                            \"id\": 30790,\n                            \"isConstant\": false,\n                            \"isLValue\": false,\n                            \"isPure\": false,\n                            \"lValueRequested\": false,\n                            \"leftExpression\": {\n                              \"id\": 30787,\n                              \"name\": \"coin\",\n                              \"nodeType\": \"Identifier\",\n                              \"overloadedDeclarations\": [],\n                              \"referencedDeclaration\": 30772,\n                              \"src\": \"2909:4:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            },\n                            \"nodeType\": \"BinaryOperation\",\n                            \"operator\": \"==\",\n                            \"rightExpression\": {\n                              \"expression\": {\n                                \"id\": 30788,\n                                \"name\": \"params\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30746,\n                                \"src\": \"2917:6:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                                  \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                                }\n                              },\n                              \"id\": 30789,\n                              \"isConstant\": false,\n                              \"isLValue\": true,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"memberLocation\": \"2924:8:24\",\n                              \"memberName\": \"tokenOut\",\n                              \"nodeType\": \"MemberAccess\",\n                              \"referencedDeclaration\": 30556,\n                              \"src\": \"2917:15:24\",\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_address\",\n                                \"typeString\": \"address\"\n                              }\n                            },\n                            \"src\": \"2909:23:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_bool\",\n                              \"typeString\": \"bool\"\n                            }\n                          },\n                          \"id\": 30796,\n                          \"nodeType\": \"IfStatement\",\n                          \"src\": \"2905:73:24\",\n                          \"trueBody\": {\n                            \"id\": 30795,\n                            \"nodeType\": \"Block\",\n                            \"src\": \"2934:44:24\",\n                            \"statements\": [\n                              {\n                                \"expression\": {\n                                  \"id\": 30793,\n                                  \"isConstant\": false,\n                                  \"isLValue\": false,\n                                  \"isPure\": false,\n                                  \"lValueRequested\": false,\n                                  \"leftHandSide\": {\n                                    \"id\": 30791,\n                                    \"name\": \"j\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30763,\n                                    \"src\": \"2952:1:24\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_int128\",\n                                      \"typeString\": \"int128\"\n                                    }\n                                  },\n                                  \"nodeType\": \"Assignment\",\n                                  \"operator\": \"=\",\n                                  \"rightHandSide\": {\n                                    \"id\": 30792,\n                                    \"name\": \"coinIdx\",\n                                    \"nodeType\": \"Identifier\",\n                                    \"overloadedDeclarations\": [],\n                                    \"referencedDeclaration\": 30766,\n                                    \"src\": \"2956:7:24\",\n                                    \"typeDescriptions\": {\n                                      \"typeIdentifier\": \"t_int128\",\n                                      \"typeString\": \"int128\"\n                                    }\n                                  },\n                                  \"src\": \"2952:11:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_int128\",\n                                    \"typeString\": \"int128\"\n                                  }\n                                },\n                                \"id\": 30794,\n                                \"nodeType\": \"ExpressionStatement\",\n                                \"src\": \"2952:11:24\"\n                              }\n                            ]\n                          }\n                        },\n                        \"id\": 30797,\n                        \"nodeType\": \"IfStatement\",\n                        \"src\": \"2827:151:24\",\n                        \"trueBody\": {\n                          \"id\": 30786,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"2855:44:24\",\n                          \"statements\": [\n                            {\n                              \"expression\": {\n                                \"id\": 30784,\n                                \"isConstant\": false,\n                                \"isLValue\": false,\n                                \"isPure\": false,\n                                \"lValueRequested\": false,\n                                \"leftHandSide\": {\n                                  \"id\": 30782,\n                                  \"name\": \"i\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30760,\n                                  \"src\": \"2873:1:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_int128\",\n                                    \"typeString\": \"int128\"\n                                  }\n                                },\n                                \"nodeType\": \"Assignment\",\n                                \"operator\": \"=\",\n                                \"rightHandSide\": {\n                                  \"id\": 30783,\n                                  \"name\": \"coinIdx\",\n                                  \"nodeType\": \"Identifier\",\n                                  \"overloadedDeclarations\": [],\n                                  \"referencedDeclaration\": 30766,\n                                  \"src\": \"2877:7:24\",\n                                  \"typeDescriptions\": {\n                                    \"typeIdentifier\": \"t_int128\",\n                                    \"typeString\": \"int128\"\n                                  }\n                                },\n                                \"src\": \"2873:11:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_int128\",\n                                  \"typeString\": \"int128\"\n                                }\n                              },\n                              \"id\": 30785,\n                              \"nodeType\": \"ExpressionStatement\",\n                              \"src\": \"2873:11:24\"\n                            }\n                          ]\n                        }\n                      },\n                      {\n                        \"condition\": {\n                          \"commonType\": {\n                            \"typeIdentifier\": \"t_int128\",\n                            \"typeString\": \"int128\"\n                          },\n                          \"id\": 30800,\n                          \"isConstant\": false,\n                          \"isLValue\": false,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"leftExpression\": {\n                            \"id\": 30798,\n                            \"name\": \"i\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30760,\n                            \"src\": \"2996:1:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_int128\",\n                              \"typeString\": \"int128\"\n                            }\n                          },\n                          \"nodeType\": \"BinaryOperation\",\n                          \"operator\": \"!=\",\n                          \"rightExpression\": {\n                            \"id\": 30799,\n                            \"name\": \"j\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30763,\n                            \"src\": \"3001:1:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_int128\",\n                              \"typeString\": \"int128\"\n                            }\n                          },\n                          \"src\": \"2996:6:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_bool\",\n                            \"typeString\": \"bool\"\n                          }\n                        },\n                        \"id\": 30803,\n                        \"nodeType\": \"IfStatement\",\n                        \"src\": \"2992:50:24\",\n                        \"trueBody\": {\n                          \"id\": 30802,\n                          \"nodeType\": \"Block\",\n                          \"src\": \"3004:38:24\",\n                          \"statements\": [\n                            {\n                              \"id\": 30801,\n                              \"nodeType\": \"Break\",\n                              \"src\": \"3022:5:24\"\n                            }\n                          ]\n                        }\n                      },\n                      {\n                        \"id\": 30807,\n                        \"nodeType\": \"UncheckedBlock\",\n                        \"src\": \"3056:52:24\",\n                        \"statements\": [\n                          {\n                            \"expression\": {\n                              \"id\": 30805,\n                              \"isConstant\": false,\n                              \"isLValue\": false,\n                              \"isPure\": false,\n                              \"lValueRequested\": false,\n                              \"nodeType\": \"UnaryOperation\",\n                              \"operator\": \"++\",\n                              \"prefix\": true,\n                              \"src\": \"3084:9:24\",\n                              \"subExpression\": {\n                                \"id\": 30804,\n                                \"name\": \"coinIdx\",\n                                \"nodeType\": \"Identifier\",\n                                \"overloadedDeclarations\": [],\n                                \"referencedDeclaration\": 30766,\n                                \"src\": \"3086:7:24\",\n                                \"typeDescriptions\": {\n                                  \"typeIdentifier\": \"t_int128\",\n                                  \"typeString\": \"int128\"\n                                }\n                              },\n                              \"typeDescriptions\": {\n                                \"typeIdentifier\": \"t_int128\",\n                                \"typeString\": \"int128\"\n                              }\n                            },\n                            \"id\": 30806,\n                            \"nodeType\": \"ExpressionStatement\",\n                            \"src\": \"3084:9:24\"\n                          }\n                        ]\n                      }\n                    ]\n                  },\n                  \"condition\": {\n                    \"commonType\": {\n                      \"typeIdentifier\": \"t_int128\",\n                      \"typeString\": \"int128\"\n                    },\n                    \"id\": 30770,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftExpression\": {\n                      \"id\": 30768,\n                      \"name\": \"i\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30760,\n                      \"src\": \"2756:1:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_int128\",\n                        \"typeString\": \"int128\"\n                      }\n                    },\n                    \"nodeType\": \"BinaryOperation\",\n                    \"operator\": \"==\",\n                    \"rightExpression\": {\n                      \"id\": 30769,\n                      \"name\": \"j\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30763,\n                      \"src\": \"2761:1:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_int128\",\n                        \"typeString\": \"int128\"\n                      }\n                    },\n                    \"src\": \"2756:6:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_bool\",\n                      \"typeString\": \"bool\"\n                    }\n                  },\n                  \"id\": 30809,\n                  \"nodeType\": \"WhileStatement\",\n                  \"src\": \"2749:369:24\"\n                },\n                {\n                  \"expression\": {\n                    \"id\": 30818,\n                    \"isConstant\": false,\n                    \"isLValue\": false,\n                    \"isPure\": false,\n                    \"lValueRequested\": false,\n                    \"leftHandSide\": {\n                      \"id\": 30810,\n                      \"name\": \"amountOut\",\n                      \"nodeType\": \"Identifier\",\n                      \"overloadedDeclarations\": [],\n                      \"referencedDeclaration\": 30749,\n                      \"src\": \"3128:9:24\",\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"nodeType\": \"Assignment\",\n                    \"operator\": \"=\",\n                    \"rightHandSide\": {\n                      \"arguments\": [\n                        {\n                          \"id\": 30813,\n                          \"name\": \"i\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30760,\n                          \"src\": \"3152:1:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_int128\",\n                            \"typeString\": \"int128\"\n                          }\n                        },\n                        {\n                          \"id\": 30814,\n                          \"name\": \"j\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30763,\n                          \"src\": \"3155:1:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_int128\",\n                            \"typeString\": \"int128\"\n                          }\n                        },\n                        {\n                          \"expression\": {\n                            \"id\": 30815,\n                            \"name\": \"params\",\n                            \"nodeType\": \"Identifier\",\n                            \"overloadedDeclarations\": [],\n                            \"referencedDeclaration\": 30746,\n                            \"src\": \"3158:6:24\",\n                            \"typeDescriptions\": {\n                              \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                              \"typeString\": \"struct SimulatorV1.SwapParams memory\"\n                            }\n                          },\n                          \"id\": 30816,\n                          \"isConstant\": false,\n                          \"isLValue\": true,\n                          \"isPure\": false,\n                          \"lValueRequested\": false,\n                          \"memberLocation\": \"3165:6:24\",\n                          \"memberName\": \"amount\",\n                          \"nodeType\": \"MemberAccess\",\n                          \"referencedDeclaration\": 30560,\n                          \"src\": \"3158:13:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        }\n                      ],\n                      \"expression\": {\n                        \"argumentTypes\": [\n                          {\n                            \"typeIdentifier\": \"t_int128\",\n                            \"typeString\": \"int128\"\n                          },\n                          {\n                            \"typeIdentifier\": \"t_int128\",\n                            \"typeString\": \"int128\"\n                          },\n                          {\n                            \"typeIdentifier\": \"t_uint256\",\n                            \"typeString\": \"uint256\"\n                          }\n                        ],\n                        \"expression\": {\n                          \"id\": 30811,\n                          \"name\": \"pool\",\n                          \"nodeType\": \"Identifier\",\n                          \"overloadedDeclarations\": [],\n                          \"referencedDeclaration\": 30753,\n                          \"src\": \"3140:4:24\",\n                          \"typeDescriptions\": {\n                            \"typeIdentifier\": \"t_contract$_ICurvePool_$31411\",\n                            \"typeString\": \"contract ICurvePool\"\n                          }\n                        },\n                        \"id\": 30812,\n                        \"isConstant\": false,\n                        \"isLValue\": false,\n                        \"isPure\": false,\n                        \"lValueRequested\": false,\n                        \"memberLocation\": \"3145:6:24\",\n                        \"memberName\": \"get_dy\",\n                        \"nodeType\": \"MemberAccess\",\n                        \"referencedDeclaration\": 31231,\n                        \"src\": \"3140:11:24\",\n                        \"typeDescriptions\": {\n                          \"typeIdentifier\": \"t_function_external_nonpayable$_t_int128_$_t_int128_$_t_uint256_$returns$_t_uint256_$\",\n                          \"typeString\": \"function (int128,int128,uint256) external returns (uint256)\"\n                        }\n                      },\n                      \"id\": 30817,\n                      \"isConstant\": false,\n                      \"isLValue\": false,\n                      \"isPure\": false,\n                      \"kind\": \"functionCall\",\n                      \"lValueRequested\": false,\n                      \"nameLocations\": [],\n                      \"names\": [],\n                      \"nodeType\": \"FunctionCall\",\n                      \"src\": \"3140:32:24\",\n                      \"tryCall\": false,\n                      \"typeDescriptions\": {\n                        \"typeIdentifier\": \"t_uint256\",\n                        \"typeString\": \"uint256\"\n                      }\n                    },\n                    \"src\": \"3128:44:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"id\": 30819,\n                  \"nodeType\": \"ExpressionStatement\",\n                  \"src\": \"3128:44:24\"\n                }\n              ]\n            },\n            \"functionSelector\": \"88dbf051\",\n            \"implemented\": true,\n            \"kind\": \"function\",\n            \"modifiers\": [],\n            \"name\": \"simulateCurveSwapIn\",\n            \"nameLocation\": \"2527:19:24\",\n            \"parameters\": {\n              \"id\": 30747,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30746,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"params\",\n                  \"nameLocation\": \"2574:6:24\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30821,\n                  \"src\": \"2556:24:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"memory\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_struct$_SwapParams_$30561_memory_ptr\",\n                    \"typeString\": \"struct SimulatorV1.SwapParams\"\n                  },\n                  \"typeName\": {\n                    \"id\": 30745,\n                    \"nodeType\": \"UserDefinedTypeName\",\n                    \"pathNode\": {\n                      \"id\": 30744,\n                      \"name\": \"SwapParams\",\n                      \"nameLocations\": [\n                        \"2556:10:24\"\n                      ],\n                      \"nodeType\": \"IdentifierPath\",\n                      \"referencedDeclaration\": 30561,\n                      \"src\": \"2556:10:24\"\n                    },\n                    \"referencedDeclaration\": 30561,\n                    \"src\": \"2556:10:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_struct$_SwapParams_$30561_storage_ptr\",\n                      \"typeString\": \"struct SimulatorV1.SwapParams\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"2546:40:24\"\n            },\n            \"returnParameters\": {\n              \"id\": 30750,\n              \"nodeType\": \"ParameterList\",\n              \"parameters\": [\n                {\n                  \"constant\": false,\n                  \"id\": 30749,\n                  \"mutability\": \"mutable\",\n                  \"name\": \"amountOut\",\n                  \"nameLocation\": \"2611:9:24\",\n                  \"nodeType\": \"VariableDeclaration\",\n                  \"scope\": 30821,\n                  \"src\": \"2603:17:24\",\n                  \"stateVariable\": false,\n                  \"storageLocation\": \"default\",\n                  \"typeDescriptions\": {\n                    \"typeIdentifier\": \"t_uint256\",\n                    \"typeString\": \"uint256\"\n                  },\n                  \"typeName\": {\n                    \"id\": 30748,\n                    \"name\": \"uint256\",\n                    \"nodeType\": \"ElementaryTypeName\",\n                    \"src\": \"2603:7:24\",\n                    \"typeDescriptions\": {\n                      \"typeIdentifier\": \"t_uint256\",\n                      \"typeString\": \"uint256\"\n                    }\n                  },\n                  \"visibility\": \"internal\"\n                }\n              ],\n              \"src\": \"2602:19:24\"\n            },\n            \"scope\": 30822,\n            \"stateMutability\": \"nonpayable\",\n            \"virtual\": false,\n            \"visibility\": \"public\"\n          }\n        ],\n        \"abstract\": false,\n        \"baseContracts\": [],\n        \"canonicalName\": \"SimulatorV1\",\n        \"contractDependencies\": [],\n        \"contractKind\": \"contract\",\n        \"fullyImplemented\": true,\n        \"linearizedBaseContracts\": [\n          30822\n        ],\n        \"name\": \"SimulatorV1\",\n        \"nameLocation\": \"331:11:24\",\n        \"scope\": 30823,\n        \"usedErrors\": [],\n        \"usedEvents\": []\n      }\n    ],\n    \"license\": \"MIT\"\n  },\n  \"id\": 24\n}"
  },
  {
    "path": "simulation/__init__.py",
    "content": "from simulation.uniswap_v2 import *\nfrom simulation.uniswap_v3 import *\nfrom simulation.online_simulator import *"
  },
  {
    "path": "simulation/online_simulator.py",
    "content": "import os\nimport json\nfrom web3 import Web3\nfrom pathlib import Path\nfrom typing import Any, Dict, List\n\nPROTOCOL_TO_ID = {\n    'uniswap_v2': 0,\n    'sushiswap_v2': 0,\n    'uniswap_v3': 1,\n    'sushiswap_v3': 1,\n}\n\nDIR = os.path.dirname(os.path.abspath(__file__))\nABI_FILE_PATH = Path(DIR) / 'SimulatorV1.json'\nSIMULATOR_ABI = json.load(open(ABI_FILE_PATH, 'r'))['abi']\n\n\nclass OnlineSimulator:\n    \"\"\"\n    This class will be used temporarily before an offline simulator is built.\n\n    Using an online simulator is easy, but comes with a cost of latency.\n    \"\"\"\n\n    def __init__(self,\n                 rpc_endpoints: Dict[str, str],\n                 tokens: Dict[str, Dict[str, List[str or int]]],\n                 pools: List[Dict[str, Any]],\n                 contracts: Dict[str, str],\n                 handlers: Dict[str, Dict[str, str]]):\n        \"\"\"\n        :param rpc_endpoints: refer to data.dex.DEX\n        :param tokens: refer to data.dex.DEX\n        :param pools: refer to dadta.dex.DEX\n\n        :param contracts: the dict of address of SimulatorV1 contract deployed\n        ex) {'ethereum': '<ADDRESS>', 'polygon': '<ADDRESS>', ... }\n\n        :param handlers: dict of handler addresses for uniswap_v2, sushiswap_v2, uniswap_v3, sushiswap_v3, etc...\n        For simulations an Uniswap V2 variant uses Factory, and an Uniswap V3 variant uses QuoterV2 to simulate swaps.\n        ex) {'ethereum': {'uniswap_v2': '<FACTORY_ADDRESS>', ... }, ... }\n        \"\"\"\n        self.rpc_endpoints = rpc_endpoints\n        self.tokens = tokens\n        self.pools = pools\n        self.contracts = contracts\n        self.handlers = handlers\n\n        # extract keys from tokens, pools\n        self.chains_list = sorted(list(tokens.keys()))\n        self.exchanges_list = sorted(set([p['exchange'] for p in pools]))\n\n        tokens_list = []\n        for exchange, tokens_dict in tokens.items():\n            tokens_list.extend(list(tokens_dict.keys()))\n        self.tokens_list = sorted(list(set(tokens_list)))\n\n        # map chains, exchanges, tokens to int id value\n        # this is used to map chains/exchanges/tokens to numpy array index values\n        self.chain_to_id = {k: i for i, k in enumerate(self.chains_list)}\n        self.exchange_to_id = {k: i for i, k in enumerate(self.exchanges_list)}\n        self.token_to_id = {k: i for i, k in enumerate(self.tokens_list)}\n\n        self.web3 = {k: Web3(Web3.HTTPProvider(v)) for k, v in rpc_endpoints.items()}\n\n        self.sim = {\n            chain: self.web3[chain].eth.contract(address=self.contracts[chain], abi=SIMULATOR_ABI)\n            for chain in self.chains_list\n        }\n\n    def make_params(self,\n                    amount_in: float,\n                    buy_path: List[List[int]],\n                    sell_path: List[List[int]],\n                    buy_pools: List[int],\n                    sell_pools: List[int]) -> List[Dict[str, Any]]:\n\n        params = []\n        params.extend(self._make_buy_params(amount_in, buy_path, buy_pools))\n        params.extend(self._make_sell_params(sell_path, sell_pools))\n        return params\n\n    def _make_buy_params(self,\n                         amount_in: float,\n                         path: List[List[int]],\n                         pools: List[int]):\n\n        params_list = []\n\n        for i in range(len(path)):\n            _path = path[i]\n            if not sum(_path):\n                continue\n\n            _pool_idx = pools[i]\n\n            pool = self.pools[_pool_idx]\n            chain = pool['chain']\n            exchange = pool['exchange']\n            version = pool['version']\n            exchange_key = f'{exchange}_v{version}'\n\n            token_in = self.tokens_list[_path[2]]\n            token_out = self.tokens_list[_path[3]]\n\n            amount_in_scaled = amount_in if i == 0 else 0\n\n            params = {\n                'protocol': PROTOCOL_TO_ID[exchange_key],\n                'handler': self.handlers[chain][exchange_key],\n                'tokenIn': self.tokens[chain][token_in][0],\n                'tokenOut': self.tokens[chain][token_out][0],\n                'fee': pool['fee'],\n                'amount': int(amount_in_scaled),\n            }\n            params_list.append(params)\n\n        return params_list\n\n    def _make_sell_params(self, path: List[List[int]], pools: List[int]):\n        params_list = []\n\n        for i in range(len(path)):\n            _path = path[i]\n            if not sum(_path):\n                continue\n\n            _pool_idx = pools[i]\n\n            pool = self.pools[_pool_idx]\n            chain = pool['chain']\n            exchange = pool['exchange']\n            version = pool['version']\n            exchange_key = f'{exchange}_v{version}'\n\n            # not the index difference with buy_params\n            token_in = self.tokens_list[_path[3]]\n            token_out = self.tokens_list[_path[2]]\n\n            params = {\n                'protocol': PROTOCOL_TO_ID[exchange_key],\n                'handler': self.handlers[chain][exchange_key],\n                'tokenIn': self.tokens[chain][token_in][0],\n                'tokenOut': self.tokens[chain][token_out][0],\n                'fee': pool['fee'],\n                'amount': 0,  # no need to set amount\n            }\n            params_list.append(params)\n\n        return list(reversed(params_list))\n\n    def simulate(self, chain: str, params: List[Dict[str, Any]]) -> int:\n        return self.sim[chain].functions.simulateSwapIn(params).call()\n\n\nif __name__ == '__main__':\n    import os\n    from dotenv import load_dotenv\n\n    from configs import RPC_ENDPOINTS\n    from addresses.ethereum import TOKENS, POOLS, SIMULATION_HANDLERS\n\n    load_dotenv(override=True)\n\n    ETHEREUM_SIMULATOR_ADDRESS = os.getenv('ETHEREUM_SIMULATOR_ADDRESS')\n\n    chain = 'ethereum'\n\n    rpc_endpoints = {chain: RPC_ENDPOINTS[chain]}\n    tokens = {chain: TOKENS}\n    pools = [pool for pool in POOLS if pool['chain'] == chain]\n    contracts = {chain: ETHEREUM_SIMULATOR_ADDRESS}\n    handlers = {chain: SIMULATION_HANDLERS}\n\n    sim = OnlineSimulator(rpc_endpoints, tokens, pools, contracts, handlers)\n\n    \"\"\"\n    ETH/USDT\n    - Buy: USDT -> ETH\n    - Sell: ETH -> USDT\n\n    Buy, sell should work like CEXs\n    \"\"\"\n    for i in range(900, 1300, 100):\n        amount_in = i * 10 ** 6\n        print('==========')\n        print('Amount in: ', amount_in)\n\n        buy_path = [[0, 1, 5, 2, 1], [0, 0, 0, 0, 0]]\n        sell_path = [[0, 0, 5, 2, 1], [0, 0, 0, 0, 0]]\n\n        buy_pools = [0]\n        sell_pools = [9]\n\n        params = sim.make_params(amount_in, buy_path, sell_path, buy_pools, sell_pools)\n\n        for param in params:\n            print(param)\n        \"\"\"\n        SUS3ETHUSDT/UNI3ETHUSDT\n        \n        - Buy: SUS3ETHUSDT\n        - Sell: UNI3ETHUSDT\n        \n        Output:\n        \n        {'protocol': 1, 'handler': '0x64e8802FE490fa7cc61d3463958199161Bb608A7', 'tokenIn': '0xdAC17F958D2ee523a2206206994597C13D831ec7', 'tokenOut': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'fee': 500, 'amount': 20000000000}\n        {'protocol': 1, 'handler': '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', 'tokenIn': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'tokenOut': '0xdAC17F958D2ee523a2206206994597C13D831ec7', 'fee': 500, 'amount': 0}\n        \"\"\"\n\n        simulated_amount_out = sim.simulate(chain, params)\n        print(f'Simulated amount out: {simulated_amount_out / 10 ** 6} USDT')\n\n        simulated_profit_in_usdt = (simulated_amount_out - amount_in) / 10 ** 6\n        print(f'Simulated profit: {simulated_profit_in_usdt} USDT')\n"
  },
  {
    "path": "simulation/uniswap_v2.py",
    "content": "class UniswapV2Simulator:\n\n    def __init__(self):\n        pass\n\n    def reserves_to_price(self,\n                          reserve0: float,\n                          reserve1: float,\n                          decimals0: float,\n                          decimals1: float,\n                          token0_in: bool):\n        \"\"\"\n        Returns the price quote of Uniswap V2 variant pools\n        This is a simple quote, thus, does not account for price impact\n\n        To get the amount out of amount in, use UniswapV2Simulator.get_amount_out\n        for consideration of both fees and price impact\n        \"\"\"\n        price = reserve1 / reserve0 * 10 ** (decimals0 - decimals1)\n        return price if token0_in else 1 / price\n\n    def get_amount_out(self,\n                       amount_in: float,\n                       reserve_in: float,\n                       reserve_out: float,\n                       fee: float = 3000):\n        \"\"\"\n        Fee in Uniswap V2 variants are 0.3%\n        However, for variants that have different fee rates,\n        fee can be overrided\n\n        fee in get_amount_out, get_amount_in are used in the format\n        that is saved into storage_array from dex.DEX class for consistency\n        with Uniswap V3 variant pools\n        \"\"\"\n        fee = fee // 1000\n        amount_in_with_fee = amount_in * (1000 - fee)\n        numerator = amount_in_with_fee * reserve_out\n        denominator = (reserve_in * 1000) + amount_in_with_fee\n        return int(numerator / denominator)\n\n    def get_amount_in(self,\n                      amount_out: float,\n                      reserve_in: float,\n                      reserve_out: float,\n                      fee: float = 3000):\n\n        fee = fee // 1000\n        numerator = reserve_in * amount_out * 1000\n        denominator = (reserve_out - amount_out) * (1000 - fee)\n        return int(numerator / denominator + 1)\n\n    def get_max_amount_in(self,\n                          reserve0: float,\n                          reserve1: float,\n                          decimals0: float,\n                          decimals1: float,\n                          fee: float,\n                          token0_in: bool,\n                          max_amount_in: float,\n                          step_size: float,\n                          slippage_tolerance_lower: float,\n                          slippage_tolerance_upper: float) -> float:\n        \"\"\"\n        Calculates the maximum amount_in we can swap to get amount_out\n        This method accounts for both: 1. fee, 2. price impact\n        Also, we calculate the price quote using reserves and use that price\n        to account for slippage tolerance\n        We make sure that:\n\n        amount_out >= price_quote * (1 - slippage_tolerance)\n\n        This method uses binary search to find the optimized amount_in value\n        To reduce the search space, we pre-set values such as: max_amount_in, step_size,\n                                                               slippage_tolerance_lower/upper\n\n        * Slippage tips:\n\n        1. Setting slippage_tolerance_lower: 0, slippage_tolerance_upper: 0.001\n        will find the amount_in with a slippage below 0.1% --> this method is faster\n\n        2. However, if you want to fine tune your amount_in, you should set the tolerance level like:\n        slippage_tolerance_lower: 0.0009, slippage_tolerance_upper: 0.001\n\n        :param max_amount_in: the max_amount_in used in binary search\n        :param step_size: the order step_size. ex) 0.01, 0.1, 1, 10, etc...\n        :param slippage_tolerance_lower: 0.01 (1%), 0.005 (0.5%), ...\n        :param slippage_tolerance_upper: 0.01 (1%), ...\n        \"\"\"\n        fee_pct = fee / 10000.0 / 100.0\n        price_quote = self.reserves_to_price(reserve0,\n                                             reserve1,\n                                             decimals0,\n                                             decimals1,\n                                             token0_in)\n        price_quote = price_quote * (1 - fee_pct)\n\n        if token0_in:\n            decimal_in, decimal_out = decimals0, decimals1\n            reserve_in, reserve_out = reserve0, reserve1\n        else:\n            decimal_in, decimal_out = decimals1, decimals0\n            reserve_in, reserve_out = reserve1, reserve0\n\n        optimized_in = 0\n\n        left = 0\n        right = max_amount_in\n\n        max_amount_out = self.get_amount_out(right * (10 ** decimal_in),\n                                             reserve_in,\n                                             reserve_out,\n                                             fee)\n        amount_out_rate = max_amount_out / right / (10 ** decimal_out)\n        slippage = (price_quote - amount_out_rate) / price_quote\n\n        if slippage < slippage_tolerance_lower:\n            \"\"\"\n            If the maximum amount_in value is within the slippage tolerance level,\n            we simply return that value\n            \"\"\"\n            optimized_in = right\n        else:\n            while left <= right:\n                mid = ((left + right) / 2) // step_size / (1 / step_size)\n                amount_out = self.get_amount_out(mid * (10 ** decimal_in),\n                                                 reserve_in,\n                                                 reserve_out,\n                                                 fee)\n                amount_out_rate = amount_out / mid / (10 ** decimal_out)\n                slippage = (price_quote - amount_out_rate) / price_quote\n                if slippage_tolerance_lower <= slippage <= slippage_tolerance_upper:\n                    optimized_in = mid\n                    break\n                else:\n                    if slippage < slippage_tolerance_lower:\n                        left = mid\n                    else:\n                        right = mid\n\n        return optimized_in\n\n\nif __name__ == '__main__':\n    pass"
  },
  {
    "path": "simulation/uniswap_v3.py",
    "content": "import math\nimport numpy as np\n\n\nclass UniswapV3Simulator:\n    \"\"\"\n    For the time being, V3 simulator limits swap simulations to\n    single tick swaps for simplicity\n\n    This is a design to enforce less price impact on swap actions.\n    It also makes sense to limit swaps to single tick swaps, because that is how\n    arbitrage/market making is done in most cases using limit orders.\n\n    Strategies don't utilize market orders (in the case of CEXs) or multi-tick swaps\n    that much when slippage is an important factor in profitability.\n\n    TODO: Add TickMap and TickMath to support simulation of multi-tick swaps\n    However, I mark this as TODO.\n    Market orders / Multi-tick swaps can help to increase order size and reduce leg outs,\n    so this is a feature that should be implemented in the future.\n\n    * Reference: https://blog.uniswap.org/uniswap-v3-math-primer\n    \"\"\"\n\n    def __init__(self):\n        pass\n\n    def sqrtx96_to_tick(self, sqrtx96: float):\n        return math.floor(\n            math.log(\n                sqrtx96 * 2 ** (-96),\n                math.sqrt(1.0001)\n            )\n        )\n\n    def sqrtx96_to_price(self,\n                         sqrtx96: float,\n                         decimals0: int,\n                         decimals1: int,\n                         token0_in: bool):\n        \"\"\"\n        Returns the quote price of buying token_out with 1 token_in\n\n        - token_in_is_token0 == true: price of buying token1 with 1 token0\n        - token_in_is_token1 == false: price of buying token0 with 1 token1\n        \"\"\"\n        price = ((sqrtx96 / (2 ** 96)) ** 2) * (10 ** (decimals0 - decimals1))\n        return price if token0_in else 1 / price\n\n    def tick_to_price(self,\n                      tick: float or np.ndarray,\n                      decimals0: float,\n                      decimals1: float) -> float or np.ndarray:\n        return (1.0001 ** tick) * (10 ** (decimals0 - decimals1))\n\n    def tick_to_price_range(self,\n                            current_tick: float,\n                            tick_spacing: float,\n                            decimals0: float,\n                            decimals1: float,\n                            token0_in: bool):\n        \"\"\"\n        Returns the tick price range of a single tick\n        \"\"\"\n        lower_tick = tick_spacing * (current_tick // tick_spacing)\n        upper_tick = tick_spacing * (current_tick // tick_spacing + 1)\n        ticks = np.array([lower_tick, upper_tick])\n        price_range = self.tick_to_price(ticks, decimals0, decimals1)\n        return price_range if token0_in else (1 / price_range)[::-1]\n\n    def get_amount_out(self):\n        pass\n\n    def get_amount_in(self):\n        pass\n\n\n\nif __name__ == '__main__':\n    pass"
  },
  {
    "path": "strategies/dex_arb_base.py",
    "content": "import os\nimport time\nimport asyncio\nimport datetime\nimport aioprocessing\nfrom functools import partial\nfrom dotenv import load_dotenv\nfrom multiprocessing import Process\nfrom typing import Any, Dict, Optional, List\n\nfrom configs import *\nfrom execution import DexOrder\nfrom data import DEX, DexStream\nfrom simulation import OnlineSimulator\nfrom external import InfluxDB, Telegram\n\nload_dotenv(override=True)\n\nFLASHBOTS_SIGNING_KEY = os.getenv('FLASHBOTS_SIGNING_KEY')\nFLASHBOTS_PRIVATE_KEY = os.getenv('FLASHBOTS_PRIVATE_KEY')\n\nETHEREUM_BOT_ADDRESS = os.getenv('ETHEREUM_BOT_ADDRESS')\nETHEREUM_SIMULATOR_ADDRESS = os.getenv('ETHEREUM_SIMULATOR_ADDRESS')\n\n\ndef cycle_name(pools_1: List[int],\n               pools_2: List[int],\n               pools: List[Dict[str, Any]]) -> str:\n    \"\"\"\n    Returns the name for cycle consisting of pools_1 and pools_2\n    ex) UNI3ETHUSDT/UNI2ETHUSDT,\n        UNI3ETHUSDT/UNI3USDCUSDT-UNI2USDCETH,\n        UNI3USDCUSDT-SUS3USDCETH/SUS3USDCUSDT-SUS2USDCETH\n\n    This is for logging/debugging purposes.\n    Actual bot logic does not depend on this name.\n    \"\"\"\n\n    def _pool_name(pool: Dict[str, Any]) -> str:\n        exchange = pool['exchange'][:3].upper()\n        version = pool['version']\n        name = pool['name'].replace('/', '')\n        return f'{exchange}{version}{name}'\n\n    path_1_name = '-'.join([_pool_name(pools[i]) for i in pools_1])\n    path_2_name = '-'.join([_pool_name(pools[i]) for i in pools_2])\n\n    return f'{path_1_name}/{path_2_name}'\n\n\ndef dex_stream_process(publisher: aioprocessing.AioQueue,\n                       chain: str,\n                       trading_symbols: List[str],\n                       max_swaps: int = 3):\n    pools = [pool for pool in POOLS if pool['chain'] == chain]\n\n    dex = DEX({chain: RPC_ENDPOINTS[chain]},\n              {chain: TOKENS[chain]},\n              pools,\n              trading_symbols,\n              max_swaps)\n\n    dex_stream = DexStream(dex, WS_ENDPOINTS, publisher)\n\n    \"\"\"\n    Trying to find possible cyclic arbitrage paths\n    Say there are paths as such:\n    - [0], [5]\n\n    Path 0: Uniswap V3 ETH/USDT\n    Path 5: Uniswap V2 ETH/USDT\n\n    In this case, this is a possible cyclic arbitrage path:\n\n    1. Uniswap V3 BUY and Uniswap V2 SELL\n    BUY: Uniswap V3 USDT -> ETH\n    SELL: Uniswap V2 ETH -> USDT\n\n    2. Uniswap V2 BUY and Uniswap V3 SELL\n    BUY: Uniswap V2 USDT -> ETH\n    SELL: Uniswap V3 ETH -> USDT\n\n    This type of cyclic arbitrage paths only work when two conditions are met:\n    Condition #1: the first pool is different\n    Condition #2: the last pool is different\n\n    compare_paths is a dictionary of possible cyclic arbitrage path pairs\n    \"\"\"\n    compare_paths = {s: {} for s in trading_symbols}\n\n    for symbol in trading_symbols:\n        pool_indexes = dex.swap_paths[symbol]['pool_indexes']\n        for i in range(len(pool_indexes)):\n            p_1 = pool_indexes[i]\n            for j in range(i + 1, len(pool_indexes)):\n                p_2 = pool_indexes[j]\n                condition_1 = p_1[0] != p_2[0]\n                condition_2 = p_1[-1] != p_2[-1]\n                if condition_1 and condition_2:\n                    name = cycle_name(p_1, p_2, pools)\n                    compare_paths[symbol][name] = (i, j)\n\n    # send compare_paths data to data_collector through publisher\n    publisher.put({\n        'source': 'dex',\n        'type': 'setup',\n        'compare_paths': compare_paths,\n    })\n\n    dex_stream.start_streams()\n\n\nclass Pending:\n\n    def __init__(self):\n        self.info = None\n\n    def can_add(self):\n        no_info = self.info is None\n        if no_info:\n            return True\n        if not self.info['order_processing']:\n            return True\n\n    def get_pending(self):\n        return self.info\n\n    def add_pending(self, pending: Dict[str, Any]):\n        self.info = pending\n\n    def set_order_processing(self):\n        self.info['order_processing'] = True\n\n    def delete_pending(self):\n        self.info = None\n\n\nasync def strategy(subscriber: aioprocessing.AioQueue,\n                   chain: str,\n                   max_bet_size: float,\n                   target_spread: float = 0.0,\n                   retry_number: int = 2,\n                   debug: bool = False):\n    rpc_endpoints = {chain: RPC_ENDPOINTS[chain]}\n    tokens = {chain: TOKENS[chain]}\n    pools = [pool for pool in POOLS if pool['chain'] == chain]\n    simulator_contracts = {chain: ETHEREUM_SIMULATOR_ADDRESS}\n    simulator_handlers = {chain: SIMULATION_HANDLERS[chain]}\n    execution_contracts = {chain: ETHEREUM_BOT_ADDRESS}\n    execution_handlers = {chain: EXECUTION_HANDLERS[chain]}\n\n    # If .env vars relavant to InfluxDB, Telegram aren't set,\n    # they'll simply stand there as placeholders, doing nothing on send calls\n    influxdb = InfluxDB()\n    telegram = Telegram()\n\n    simulator = OnlineSimulator(rpc_endpoints=rpc_endpoints,\n                                tokens=tokens,\n                                pools=pools,\n                                contracts=simulator_contracts,\n                                handlers=simulator_handlers)\n\n    execution = DexOrder(private_key=FLASHBOTS_PRIVATE_KEY,\n                         signing_key=FLASHBOTS_SIGNING_KEY,\n                         rpc_endpoints=rpc_endpoints,\n                         tokens=tokens,\n                         pools=pools,\n                         contracts=execution_contracts,\n                         handlers=execution_handlers)\n\n    compare_paths = {}\n    gas_info = {}\n\n    spreads = {}\n    pending = Pending()\n\n    \"\"\"\n    The estimated cost of WhackAMoleBotV1 swaps\n    Current gas amount is a rough estimation, for a optimized result,\n    make sure to find better estimates.\n    These values are overestimated for a more strict/conservative simulation result.\n    \"\"\"\n    gas_costs = {\n        0: 100000,  # base cost\n        2: 40000,  # V2 1-hop cost\n        3: 50000,  # V3 1-hop cost\n    }\n\n    async def _process_pending_order(pending: Pending):\n        \"\"\"\n        1. Simulate using SimulatorV1\n        2. Execute order using Flashbots\n        \"\"\"\n        if pending.can_add():\n            return\n\n        pending_info = pending.get_pending()\n\n        if 'block' not in gas_info or pending_info['block'] != gas_info['block']:\n            return\n\n        spread = spreads[pending_info['key']]\n\n        if spread <= target_spread:\n            pending.delete_pending()\n            return\n\n        \"\"\"\n        We simulate using max_fee_per_gas as the gas price\n        This is to conservatively calculate the min_amount_in to be profitable\n        assuming we use gas at the highest cost\n\n        We also assume the quote of gas_price is at sell_price,\n        which is higher than that of buy_price.\n        This is another mechanism to overestimate the cost for a more realistic simulation result.\n        \"\"\"\n        buy_price = pending_info['max_buy_sell_price'][0]\n        sell_price = pending_info['max_buy_sell_price'][1]\n\n        gas_cost = (pending_info['estimated_gas_used'] * gas_info['max_fee_per_gas']) * 10 ** (-18)  # in ETH\n        gas_cost_in_usdt = gas_cost * sell_price  # the sell_price has to be price of ETH/USDT\n\n        usdt_profit_per_unit_of_token = buy_price * (spread / 100.0)\n\n        min_amount_in_token = gas_cost_in_usdt / usdt_profit_per_unit_of_token\n        min_amount_in_usdt = min_amount_in_token * buy_price\n\n        \"\"\"\n        Since we're not using flashloans yet, we can't over leverage our bets.\n        The max_bet_size should be less than the amount of USDT you have in your WhackAMoleBotV1 contract.\n        This would naturally mean that to cover the gas costs, we can only aim for spreads that\n        are greater than other well optimized bots either 1. using flashloans, or 2. using more capital.\n        \"\"\"\n        if min_amount_in_usdt <= max_bet_size:\n            # we simulate using max_bet_size and if the result is promising we send the order to Flashbots\n            usdt_decimals = simulator.tokens[chain]['USDT'][1]\n            # min_amount_in = max_bet_size * 10 ** usdt_decimals\n            min_amount_in = int(min_amount_in_usdt * 1.1) * 10 ** usdt_decimals\n            sim_params = simulator.make_params(amount_in=min_amount_in,\n                                               buy_path=pending_info['buy_path'],\n                                               sell_path=pending_info['sell_path'],\n                                               buy_pools=pending_info['buy_pools'],\n                                               sell_pools=pending_info['sell_pools'])\n            s = time.time()\n            simulated_amount_out = simulator.simulate(chain, sim_params)\n            e = time.time()\n            simulation_took = e - s\n            simulated_profit_in_usdt = (simulated_amount_out - min_amount_in) / 10 ** usdt_decimals\n\n            final_profit = simulated_profit_in_usdt - gas_cost_in_usdt\n            print(f'Simulated profit in USDT: {final_profit} (Took: {round(simulation_took, 3)} secs)')\n\n            if final_profit > 0:\n                pending.set_order_processing()\n\n                # execute order here if program started as non-debug mode\n                if not debug:\n                    exe_params = execution.make_params(amount_in=min_amount_in,\n                                                       buy_path=pending_info['buy_path'],\n                                                       sell_path=pending_info['sell_path'],\n                                                       buy_pools=pending_info['buy_pools'],\n                                                       sell_pools=pending_info['sell_pools'])\n                    s = time.time()\n                    receipts = execution.send_order(chain=chain,\n                                                    params=exe_params,\n                                                    min_amount_out=int(simulated_amount_out * 0.999),\n                                                    # 0.1% slippage tolerance\n                                                    max_priority_fee_per_gas=gas_info['max_priority_fee_per_gas'],\n                                                    max_fee_per_gas=gas_info['max_fee_per_gas'],\n                                                    retry=retry_number,\n                                                    block_number=gas_info['block'])\n                    e = time.time()\n                    execution_took = e - s\n                    print(f'Execution success. Took: {round(execution_took, 3)} secs: {receipts}')\n\n            await telegram.send(\n                f'Block #{pending_info[\"block\"]} {pending_info[\"key\"]} ({round(spread, 2)}%): {final_profit} USDT')\n        else:\n            await telegram.send(\n                f'Block #{pending_info[\"block\"]} {pending_info[\"key\"]} ({round(spread, 2)}%) min amount of USDT needed to profit: {round(min_amount_in_usdt, 3)} USDT')\n        pending.delete_pending()\n\n    # Main strategy loop\n    while True:\n        try:\n            data = await subscriber.coro_get()\n            data_type = data['type']\n\n            if data_type == 'setup':\n                # data sent from: strategies.dex_arb_base.dex_stream_process\n                compare_paths = data['compare_paths']\n\n            elif data_type == 'block':\n                # data sent from: data.dex_streams.DexStream.stream_new_blocks\n                gas_info = data\n                print('[New block] ', gas_info)\n\n                await _process_pending_order(pending)\n\n            elif data_type == 'event':\n                s = time.time()\n                # data sent from: data.dex_streams.DexStream.stream_uniswap_v2_events/stream_uniswap_v3_events\n\n                \"\"\"\n                Take 2-step operation before sending order transaction:\n\n                1. Filtering: Calculate simple spread using price quotes (w/o consideration of price impact)\n                              Filter out paths that had a spread over 0\n\n                2. Simulating: If simple spread calculated above was above 0, it is worth simulating for price impact\n                   Thus, use SimulatorV1 contract to simulate the amount_out of the potentially profitable paths\n                   But to make this simpler, we simply simulate the most profitable path\n\n                This means that our simulations are done online. This will take some time, and will need to be\n                ported offline to get the best performance out\n                \"\"\"\n                max_spread = -1\n                max_spread_key = ''\n                max_buy_sell_price = []\n                max_path_index = None\n\n                symbol = data['symbol']\n                for path_name, path_index in compare_paths[symbol].items():\n                    \"\"\"\n                    If path_name were: UNI3ETHUSDT/UNI2ETHUSDT\n                    We want to calculate the spread for both:\n                    - UNI3ETHUSDT BUY -> UNI2ETHUSDT SELL\n                    - UNI2ETHUSDT SELL -> UNI3ETHUSDT SELL\n                    \"\"\"\n                    name_1, name_2 = path_name.split('/')\n                    key_1 = f'{name_1}/{name_2}'\n                    key_2 = f'{name_2}/{name_1}'\n\n                    price_1 = data['price'][path_index[0]]\n                    price_2 = data['price'][path_index[1]]\n\n                    fee_1 = data['fee'][path_index[0]]\n                    fee_2 = data['fee'][path_index[1]]\n                    total_fee = fee_1 + fee_2\n\n                    spread_1 = ((price_1 / price_2 - 1) - total_fee) * 100\n                    spread_2 = ((price_2 / price_1 - 1) - total_fee) * 100\n\n                    if spread_1 > max_spread:\n                        max_spread_key = key_1\n                        max_spread = spread_1\n                        max_buy_sell_price = [price_2, price_1]\n                        max_path_index = list(reversed(path_index))  # buy pool index, sell pool index\n\n                    if spread_2 > max_spread:\n                        max_spread_key = key_2\n                        max_spread = spread_2\n                        max_buy_sell_price = [price_1, price_2]\n                        max_path_index = list(path_index)  # buy pool index, sell pool index\n\n                    spreads[key_1] = spread_1\n                    spreads[key_2] = spread_2\n\n                await influxdb.send('DEX_ARB_BASE_ETHUSDT', spreads)\n                e = time.time()\n                max_msg = f'{max_spread_key}: {round(spreads[max_spread_key], 3)}%'\n                print(f'[{datetime.datetime.now()}] Update took: {round(e - s, 4)} secs. {max_msg}')\n\n                # add newly detected edge (positive spread) to pending\n                # we process one edge a time to make our lives easier\n                if pending.can_add() and max_spread > target_spread:\n                    # before we add the new max_spread_key, first check if the spread can cover\n                    # gas costs with our max_bet_size\n                    buy_path = data['path'][max_path_index[0]]\n                    sell_path = data['path'][max_path_index[1]]\n\n                    \"\"\"\n                    Calculate the estimated_gas_used given:\n                    - buy_path = [[0, 0, 5, 4, 1], [0, 0, 4, 2, 1]]\n                    - sell_path = [[0, 1, 5, 2, 1], [0, 0, 0, 0, 0]]\n                    \"\"\"\n                    estimated_gas_used = gas_costs[0]  # base cost\n                    for buy_sell_path in [buy_path, sell_path]:\n                        for p in buy_sell_path:\n                            if sum(p) == 0:\n                                continue\n                            version = p[4]\n                            estimated_gas_used += gas_costs[version + 2]  # V2 = 0, V3 = 1\n\n                    \"\"\"\n                    The actual simulation will occur in _process_pending_order\n                    This is because a newly updated block may not be avaialble yet.\n                    We send a REST API call to Blocknative for gas info, so we need to wait for the response\n                    to arrive before we run our simulation.\n                    \"\"\"\n                    pending_info = {\n                        'key': max_spread_key,\n                        'max_buy_sell_price': max_buy_sell_price,\n                        'block': data['block'],  # block at which the edge was detected\n                        'cancel_at': data['block'] + 1,  # cancel after 1 block\n                        'buy_path': buy_path,\n                        'sell_path': sell_path,\n                        'buy_pools': data['pool_indexes'][max_path_index[0]],\n                        'sell_pools': data['pool_indexes'][max_path_index[1]],\n                        'estimated_gas_used': estimated_gas_used,\n                        'order_processing': False,\n                    }\n                    pending.add_pending(pending_info)\n                    print(pending_info)\n\n                await _process_pending_order(pending)\n\n        except Exception as e:\n            await influxdb.close()\n            raise e\n\n\nasync def main():\n    chain = 'ethereum'\n    max_swaps = 3\n    trading_symbols = ['ETH/USDT']  # other symbols won't work at the moment, because of gas cost calculations\n    max_bet_size = 20000  # in USDT, because we are buying ETH with USDT\n    target_spread = 0.15  # minimum target of 0.4% spread\n    retry_number = 2\n    debug = True  # running in debug mode won't execute orders. It'll simply send data to InfluxDB, Telegram\n\n    queue = aioprocessing.AioQueue()\n\n    p1 = Process(target=dex_stream_process, args=(queue, chain, trading_symbols, max_swaps,))\n    p1.start()\n\n    await strategy(queue, chain, max_bet_size, target_spread, retry_number, debug)\n\n\nif __name__ == '__main__':\n    import nest_asyncio\n\n    nest_asyncio.apply()\n    asyncio.run(main())\n"
  },
  {
    "path": "tests/test_WhackAMoleBotV1.py",
    "content": "import json\nfrom web3 import Web3\nfrom unittest import TestCase\nfrom eth_account.account import Account\n\nPOOL_V2_ABI = json.load(open('../abi/UniswapV2Pool.json', 'r'))\nPOOL_V3_ABI = json.load(open('../abi/UniswapV3Pool.json', 'r'))\n\nROUTER2_ABI = json.load(open('../abi/UniswapV2Router2.json', 'r'))\nQUOTER2_ABI = json.load(open('../abi/UniswapV3Quoter2.json', 'r'))\n\nSWAP_ROUTER2_ABI = json.load(open('../abi/UniswapV3SwapRouter2.json', 'r'))\n\nWETH_ABI = json.load(open('../abi/WETH.json', 'r'))\nERC20_ABI = json.load(open('../abi/ERC20.json', 'r'))\n\nBOT_ABI = json.load(open('../contracts/out/WhackAMoleBotV1.sol/WhackAMoleBotV1.json', 'r'))['abi']\nSIMULATOR_ABI = json.load(open('../contracts/out/SimulatorV1.sol/SimulatorV1.json', 'r'))['abi']\n\n\nclass WhackAMoleBotV1Tests(TestCase):\n    \"\"\"\n    WhackAMoleBotV1 tests are dependent on WhackAMoleBotV1 contract\n    Make sure to deploy the contract to mainnet hardfork before testing\n\n    forge create --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> src/WhackAMoleBotV1.sol:WhackAMoleBotV1\n    \"\"\"\n\n    HARDFORK_RPC_URL = 'http://localhost:8545'\n    FLASHBOTS_URL = 'https://relay.flashbots.net'\n\n    # Private key is from Anvil\n    TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'\n\n    WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'\n    USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'\n\n    WETH_DECIMALS = 18\n    USDT_DECIMALS = 6\n\n    POOL_V3_FEE = 500\n\n    # WETH-USDT Uniswap V2 pool\n    POOL_V2 = '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852'\n    ROUTER2 = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'\n\n    # WETH-USDT Uniswap V3 pool\n    POOL_V3 = '0x11b815efB8f581194ae79006d24E0d814B7697F6'\n    QUOTER2 = '0x61fFE014bA17989E743c5F6cB21bF9697530B21e'\n    SWAP_ROUTER = '0xE592427A0AEce92De3Edee1F18E0157C05861564'\n\n    # WhackAMoleBotV1\n    BOT = '0x9155497EAE31D432C0b13dBCc0615a37f55a2c87'\n    SIMULATOR = '0xfB12F7170FF298CDed84C793dAb9aBBEcc01E798'\n\n    def setUp(self):\n        self.signer = Account.from_key(self.TEST_PRIVATE_KEY)\n\n        self.web3 = Web3(Web3.HTTPProvider(self.HARDFORK_RPC_URL))\n\n        self.weth = self.web3.eth.contract(address=self.WETH, abi=WETH_ABI)\n        self.usdt = self.web3.eth.contract(address=self.USDT, abi=ERC20_ABI)\n\n        # V2 contracts\n        self.pool_v2 = self.web3.eth.contract(address=self.POOL_V2, abi=POOL_V2_ABI)\n        self.router2 = self.web3.eth.contract(address=self.ROUTER2, abi=ROUTER2_ABI)\n\n        # V3 contracts\n        self.pool_v3 = self.web3.eth.contract(address=self.POOL_V3, abi=POOL_V3_ABI)\n        self.quoter2 = self.web3.eth.contract(address=self.QUOTER2, abi=QUOTER2_ABI)\n        self.swap_router = self.web3.eth.contract(address=self.SWAP_ROUTER, abi=SWAP_ROUTER2_ABI)\n\n        # WhackAMoleBotV1\n        self.bot = self.web3.eth.contract(address=self.BOT, abi=BOT_ABI)\n        self.sim = self.web3.eth.contract(address=self.SIMULATOR, abi=SIMULATOR_ABI)\n\n        # Wrap ETH to WETH\n        # Transfer ETH to WETH contract\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transaction = {\n            'from': self.signer.address,\n            'to': self.WETH,\n            'value': self.web3.to_wei(10, 'ether'),\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 200000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),  # set at randomly high gas price\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),  # set at random\n        }\n        signed = self.signer.sign_transaction(transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        # transfer WETH to bot contract\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transfer_transaction = self.weth.functions.transfer(\n            self.BOT, self.web3.to_wei(3, 'ether')\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 200000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(transfer_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        bot_weth_balance = self.weth.functions.balanceOf(self.BOT).call()\n        print('Bot WETH balance: ', bot_weth_balance)\n        self.assertTrue(bot_weth_balance >= self.web3.to_wei(3, 'ether'))\n\n        # approve usage of WETH, USDT to Uniswap V2, V3 routers\n        tokens = [self.WETH, self.USDT]\n        protocols = [self.ROUTER2, self.SWAP_ROUTER]\n\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transfer_transaction = self.bot.functions.approveHandlers(\n            tokens, protocols\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 200000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(transfer_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        max_int = 2 ** 256 - 1\n\n        for protocol in protocols:\n            weth_allowance = self.weth.functions.allowance(self.BOT, protocol).call()\n            self.assertEqual(weth_allowance, max_int)\n\n            usdt_allowance = self.usdt.functions.allowance(self.BOT, protocol).call()\n            self.assertEqual(usdt_allowance, max_int)\n\n    def test_recover_tokens(self):\n        # test recoverTokens\n        bot_weth_balance_before = self.weth.functions.balanceOf(self.BOT).call()\n        signer_weth_balance_before = self.weth.functions.balanceOf(self.signer.address).call()\n\n        tokens = [self.WETH]\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transfer_transaction = self.bot.functions.recoverTokens(\n            tokens\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 300000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(transfer_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        bot_weth_balance_after = self.weth.functions.balanceOf(self.BOT).call()\n        signer_weth_balance_after = self.weth.functions.balanceOf(self.signer.address).call()\n\n        # print(bot_weth_balance_before, bot_weth_balance_after)\n        # print(signer_weth_balance_before, signer_weth_balance_after)\n        self.assertEqual(bot_weth_balance_before, signer_weth_balance_after)\n\n    def test_v2_swap(self):\n        factory = self.pool_v2.functions.factory().call()\n        params = {\n            'protocol': 0,\n            'handler': factory,\n            'tokenIn': self.WETH,\n            'tokenOut': self.USDT,\n            'fee': 3000,\n            'amount': self.web3.to_wei(1, 'ether'),\n        }\n        simulated_amount_out = self.sim.functions.simulateSwapIn([params]).call()\n\n        usdt_balance_before = self.usdt.functions.balanceOf(self.BOT).call()\n\n        swap_params = {\n            **params,\n            'handler': self.ROUTER2,\n        }\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transfer_transaction = self.bot.functions.whack(\n            [swap_params], 0\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 300000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(transfer_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        usdt_balance_after = self.usdt.functions.balanceOf(self.BOT).call()\n\n        self.assertEqual(simulated_amount_out, usdt_balance_after - usdt_balance_before)\n\n    def test_v3_swap(self):\n        params = {\n            'protocol': 1,\n            'handler': self.QUOTER2,\n            'tokenIn': self.WETH,\n            'tokenOut': self.USDT,\n            'fee': self.POOL_V3_FEE,\n            'amount': self.web3.to_wei(1, 'ether'),\n        }\n        simulated_amount_out = self.sim.functions.simulateSwapIn([params]).call()\n\n        usdt_balance_before = self.usdt.functions.balanceOf(self.BOT).call()\n\n        swap_params = {\n            **params,\n            'handler': self.SWAP_ROUTER,\n        }\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transfer_transaction = self.bot.functions.whack(\n            [swap_params], 0\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 300000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(transfer_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        usdt_balance_after = self.usdt.functions.balanceOf(self.BOT).call()\n\n        self.assertEqual(simulated_amount_out, usdt_balance_after - usdt_balance_before)\n\n    def test_2_hop_swaps(self):\n        factory = self.pool_v2.functions.factory().call()\n        params_1 = {\n            'protocol': 0,\n            'handler': factory,\n            'tokenIn': self.WETH,\n            'tokenOut': self.USDT,\n            'fee': 3000,\n            'amount': self.web3.to_wei(1, 'ether'),\n        }\n        params_2 = {\n            'protocol': 1,\n            'handler': self.QUOTER2,\n            'tokenIn': self.USDT,\n            'tokenOut': self.WETH,\n            'fee': self.POOL_V3_FEE,\n            'amount': 0,\n        }\n        simulated_amount_out = self.sim.functions.simulateSwapIn(\n            [params_1, params_2]\n        ).call()\n\n        weth_balance_before = self.weth.functions.balanceOf(self.BOT).call()\n\n        swap_params_1 = {\n            **params_1,\n            'handler': self.ROUTER2,\n        }\n        swap_params_2 = {\n            **params_2,\n            'handler': self.SWAP_ROUTER,\n        }\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transfer_transaction = self.bot.functions.whack(\n            [swap_params_1, swap_params_2], 0\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 300000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(transfer_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        weth_balance_after = self.weth.functions.balanceOf(self.BOT).call()\n\n        weth_amount_out = weth_balance_after - (weth_balance_before - self.web3.to_wei(1, 'ether'))\n        self.assertEqual(simulated_amount_out, weth_amount_out)\n\n    def test_n_hop_swap_gas(self):\n        \"\"\"\n        V2 1-hop: 116040\n           2-hop: 145834\n           3-hop: 182965\n           4-hop: 208761\n\n        V3 1-hop: 117267\n           2-hop: 161362\n           3-hop: 207317\n           4-hop: 242614\n\n        V2 1-hop / V3 1-hop: 186354\n        V2 2-hop / V3 1-hop: 220666\n        V2 1-hop / V3 2-hop: 235437\n        V2 2-hop / V3 2-hop: 262089\n\n        For simplicity:\n        Base cost: 100000\n        V2 1-hop costs: 40000\n        V3 1-hop costs: 50000\n        \"\"\"\n        params_1 = {\n            'protocol': 0,\n            'handler': self.ROUTER2,\n            'tokenIn': self.WETH,\n            'tokenOut': self.USDT,\n            'fee': 3000,\n            'amount': self.web3.to_wei(0.1, 'ether'),\n        }\n        params_2 = {\n            'protocol': 1,\n            'handler': self.SWAP_ROUTER,\n            'tokenIn': self.USDT,\n            'tokenOut': self.WETH,\n            'fee': 500,\n            'amount': 0,\n        }\n        params_3 = {\n            'protocol': 1,\n            'handler': self.SWAP_ROUTER,\n            'tokenIn': self.WETH,\n            'tokenOut': self.USDT,\n            'fee': 500,\n            'amount': 0,\n        }\n        params_4 = {\n            'protocol': 0,\n            'handler': self.ROUTER2,\n            'tokenIn': self.USDT,\n            'tokenOut': self.WETH,\n            'fee': 3000,\n            'amount': 0,\n        }\n\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        transfer_transaction = self.bot.functions.whack(\n            [params_1, params_4, params_1, params_4], 0\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 300000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(transfer_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        tx = self.web3.eth.get_transaction(tx_hash)\n        print(tx)\n\n    def test_price_impact_simulation(self):\n        uniswap_quoter2 = '0x61fFE014bA17989E743c5F6cB21bF9697530B21e'\n        sushiswap_quoter2 = '0x64e8802FE490fa7cc61d3463958199161Bb608A7'\n\n        # Scenario 1: WETH -> USDT -> WETH\n        amount_in = 1 * 10 ** self.WETH_DECIMALS\n\n        params_1 = {\n            'protocol': 1,\n            'handler': uniswap_quoter2,\n            'tokenIn': self.WETH,\n            'tokenOut': self.USDT,\n            'fee': 500,\n            'amount': amount_in,\n        }\n        params_2 = {\n            'protocol': 1,\n            'handler': sushiswap_quoter2,\n            'tokenIn': self.USDT,\n            'tokenOut': self.WETH,\n            'fee': 500,\n            'amount': 0,\n        }\n        simulated_amount_out = self.sim.functions.simulateSwapIn(\n            [params_1, params_2]\n        ).call()\n\n        # Scenario 2: USDT -> WETH -> USDT\n        amount_in = 1 * 10 ** self.USDT_DECIMALS\n"
  },
  {
    "path": "tests/test_simulation.py",
    "content": "import json\nimport eth_abi\nimport datetime\nfrom web3 import Web3\nfrom unittest import TestCase\nfrom eth_account.account import Account\n\nfrom simulation import UniswapV2Simulator, UniswapV3Simulator\n\nPOOL_V2_ABI = json.load(open('../abi/UniswapV2Pool.json', 'r'))\nPOOL_V3_ABI = json.load(open('../abi/UniswapV3Pool.json', 'r'))\n\nROUTER2_ABI = json.load(open('../abi/UniswapV2Router2.json', 'r'))\nQUOTER2_ABI = json.load(open('../abi/UniswapV3Quoter2.json', 'r'))\n\nSWAP_ROUTER2_ABI = json.load(open('../abi/UniswapV3SwapRouter2.json', 'r'))\n\nWETH_ABI = json.load(open('../abi/WETH.json', 'r'))\nERC20_ABI = json.load(open('../abi/ERC20.json', 'r'))\n\n\nclass SimulationTests(TestCase):\n    \"\"\"\n    Simulation tests are dependent on mainnet hardforks\n    Make sure to have a local mainnet hardfork running before testing\n\n    For people using Foundry, running Anvil Ethereum mainnet hardfork is easy:\n\n    anvil --fork-url <RPC_URL>\n    \"\"\"\n\n    HARDFORK_RPC_URL = 'http://localhost:8545'\n\n    # Private key is from Anvil\n    TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'\n\n    WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'\n    USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'\n    DAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F'\n\n    WETH_DECIMALS = 18\n    USDT_DECIMALS = 6\n    DAI_DECIMALS = 18\n\n    POOL_V3_FEE = 500\n\n    # WETH-USDT Uniswap V2 pool\n    POOL_V2 = '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852'\n    ROUTER2 = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'\n\n    # WETH-USDT Uniswap V3 pool\n    # POOL_V3 = '0x11b815efB8f581194ae79006d24E0d814B7697F6'\n    POOL_V3 = '0xC2e9F25Be6257c210d7Adf0D4Cd6E3E881ba25f8'\n    QUOTER2 = '0x61fFE014bA17989E743c5F6cB21bF9697530B21e'\n    SWAP_ROUTER = '0xE592427A0AEce92De3Edee1F18E0157C05861564'\n\n    # WhackAMoleBotV1\n    BOT = '0x46d4674578a2daBbD0CEAB0500c6c7867999db34'\n\n    def setUp(self):\n        self.signer = Account.from_key(self.TEST_PRIVATE_KEY)\n\n        self.web3 = Web3(Web3.HTTPProvider(self.HARDFORK_RPC_URL))\n\n        self.weth = self.web3.eth.contract(address=self.WETH, abi=WETH_ABI)\n        self.usdt = self.web3.eth.contract(address=self.USDT, abi=ERC20_ABI)\n\n        # V2 contracts\n        self.pool_v2 = self.web3.eth.contract(address=self.POOL_V2, abi=POOL_V2_ABI)\n        self.router2 = self.web3.eth.contract(address=self.ROUTER2, abi=ROUTER2_ABI)\n\n        # V3 contracts\n        self.pool_v3 = self.web3.eth.contract(address=self.POOL_V3, abi=POOL_V3_ABI)\n        self.quoter2 = self.web3.eth.contract(address=self.QUOTER2, abi=QUOTER2_ABI)\n        self.swap_router = self.web3.eth.contract(address=self.SWAP_ROUTER, abi=SWAP_ROUTER2_ABI)\n\n        self.sim_v2 = UniswapV2Simulator()\n        self.sim_v3 = UniswapV3Simulator()\n\n    # def test_sim_v2_get_amount_out(self):\n    #     token_in = self.WETH\n    #     token0 = self.pool_v2.functions.token0().call()\n    #     token0_in = token_in == token0\n    #\n    #     reserve0, reserve1, _ = self.pool_v2.functions.getReserves().call()\n    #\n    #     if token0_in:\n    #         reserve_in, reserve_out = reserve0, reserve1\n    #     else:\n    #         reserve_in, reserve_out = reserve1, reserve0\n    #\n    #     amount_in = self.web3.toWei(1, 'ether')\n    #\n    #     # First check that the simulation results equal that of Router2\n    #     router_amount_out = self.router2.functions.getAmountOut(\n    #         amount_in, reserve_in, reserve_out\n    #     ).call()\n    #\n    #     sim_amount_out = self.sim_v2.get_amount_out(\n    #         amount_in, reserve_in, reserve_out\n    #     )\n    #\n    #     self.assertEqual(router_amount_out, sim_amount_out)\n    #\n    #     # Next, check that swapping 1 WETH does in fact result in amount_out USDT\n    #     nonce = self.web3.eth.get_transaction_count(self.signer.address)\n    #     approve_transaction = self.weth.functions.approve(self.ROUTER2, amount_in).build_transaction({\n    #         'from': self.signer.address,\n    #         'chainId': 1,\n    #         'nonce': nonce,\n    #         'gas': 200000,\n    #         'maxFeePerGas': self.web3.toWei(100, 'gwei'),\n    #         'maxPriorityFeePerGas': self.web3.toWei(50, 'gwei'),\n    #     })\n    #     signed = self.signer.sign_transaction(approve_transaction)\n    #     tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n    #     _ = self.web3.eth.get_transaction(tx_hash)\n    #\n    #     allowance_amount = self.weth.functions.allowance(self.signer.address, self.ROUTER2).call()\n    #     self.assertEqual(amount_in, allowance_amount)  # approve was successful\n    #\n    #     usdt_balance_before = self.usdt.functions.balanceOf(self.signer.address).call()\n    #\n    #     path = [self.WETH, self.USDT]\n    #     nonce = self.web3.eth.get_transaction_count(self.signer.address)\n    #     # I'm not including slippage tolerance here, so this transaction\n    #     # will most likely fail in real life scenarios unless your transaction is at the top of the block\n    #     swap_transaction = self.router2.functions.swapExactTokensForTokens(\n    #         amount_in,\n    #         sim_amount_out,\n    #         path,\n    #         self.signer.address,\n    #         int(datetime.datetime.now().timestamp()) + 60000  # 1 minute\n    #     ).build_transaction({\n    #         'from': self.signer.address,\n    #         'chainId': 1,\n    #         'nonce': nonce,\n    #         'gas': 200000,\n    #         'maxFeePerGas': self.web3.toWei(100, 'gwei'),\n    #         'maxPriorityFeePerGas': self.web3.toWei(50, 'gwei'),\n    #     })\n    #     signed = self.signer.sign_transaction(swap_transaction)\n    #     tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n    #     _ = self.web3.eth.get_transaction(tx_hash)\n    #\n    #     usdt_balance_after = self.usdt.functions.balanceOf(self.signer.address).call()\n    #\n    #     self.assertEqual(usdt_balance_before + sim_amount_out, usdt_balance_after)\n\n    def test_sim_v3_get_amount_out(self):\n        \"\"\"\n        Currently only implements single tick swap\n        \"\"\"\n        import math\n\n        # # Wrap ETH to WETH\n        # nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        # transaction = {\n        #     'from': self.signer.address,\n        #     'to': self.WETH,\n        #     'value': self.web3.to_wei(100, 'ether'),\n        #     'chainId': 1,\n        #     'nonce': nonce,\n        #     'gas': 200000,\n        #     'maxFeePerGas': self.web3.to_wei(100, 'gwei'),  # set at randomly high gas price\n        #     'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),  # set at random\n        # }\n        # signed = self.signer.sign_transaction(transaction)\n        # tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        # _ = self.web3.eth.get_transaction(tx_hash)\n        #\n        # weth_balance = self.weth.functions.balanceOf(self.signer.address).call()\n        # print('WETH: ', weth_balance)\n\n        # Approve WETH\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        approve_transaction = self.weth.functions.approve(\n            self.pool_v3.address, 100 * 10 ** 18\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 200000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        signed = self.signer.sign_transaction(approve_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        _ = self.web3.eth.get_transaction(tx_hash)\n\n        allowance = self.weth.functions.allowance(self.signer.address, self.SWAP_ROUTER).call()\n        print('WETH allowance: ', allowance)\n\n\n        token_in = self.WETH\n        token0 = self.pool_v3.functions.token0().call()\n        token0_in = token_in == token0\n\n        slot0 = self.pool_v3.functions.slot0().call()\n        tick_spacing = self.pool_v3.functions.tickSpacing().call()\n        liquidity = self.pool_v3.functions.liquidity().call()\n\n        sqrt_price, current_tick, *_ = slot0\n\n        upper_tick_idx = tick_spacing * (current_tick // tick_spacing + 1)\n        lower_tick_idx = tick_spacing * (current_tick // tick_spacing)\n\n        print(upper_tick_idx, current_tick, lower_tick_idx)\n\n        print(slot0)\n        print(tick_spacing)\n        print(liquidity)\n\n        price_range = self.sim_v3.tick_to_price_range(current_tick, tick_spacing, self.DAI_DECIMALS, self.WETH_DECIMALS, token0_in)\n        print('Price range: ', price_range)\n\n        curr_price = self.sim_v3.sqrtx96_to_price(sqrt_price, self.DAI_DECIMALS, self.WETH_DECIMALS, token0_in)\n        print('Curr price: ', curr_price)\n\n        sqrt_price_tick = self.sim_v3.sqrtx96_to_tick(sqrt_price)\n        print(sqrt_price_tick)\n\n        p = self.sim_v3.tick_to_price(sqrt_price_tick, self.DAI_DECIMALS, self.WETH_DECIMALS)\n        print(p)\n\n        target_price = self.sim_v3.tick_to_price(lower_tick_idx, self.DAI_DECIMALS, self.WETH_DECIMALS)\n        print('target price: ', 1 / target_price)\n        price_diff = (1 / target_price) - curr_price\n        price_diff_liq = price_diff * liquidity\n        print(price_diff_liq / 10 ** self.DAI_DECIMALS)\n\n\n\n        nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        params = (\n            self.WETH,\n            self.DAI,\n            3000,\n            self.signer.address,\n            99999999999999999,\n            1 * 10 ** self.WETH_DECIMALS,\n            0,\n            0,\n        )\n        swap_transaction = self.pool_v3.functions.swap(\n            self.signer.address,\n            False,\n            1 * 10 ** 18,\n            4400000000,\n            ''\n        ).build_transaction({\n            'from': self.signer.address,\n            'chainId': 1,\n            'nonce': nonce,\n            'gas': 1200000,\n            'maxFeePerGas': self.web3.to_wei(100, 'gwei'),\n            'maxPriorityFeePerGas': self.web3.to_wei(50, 'gwei'),\n        })\n        print(swap_transaction)\n        signed = self.signer.sign_transaction(swap_transaction)\n        tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        tx = self.web3.eth.get_transaction(tx_hash)\n\n        replay_tx = {\n            'to': tx['to'],\n            'from': tx['from'],\n            'value': tx['value'],\n            'data': tx['input'],\n        }\n\n        self.web3.eth.call(replay_tx, tx.blockNumber - 1)\n\n        print('swapped')\n\n        slot0 = self.pool_v3.functions.slot0().call()\n        liquidity = self.pool_v3.functions.liquidity().call()\n\n        print('slot0: ', slot0)\n        print('liquidity: ', liquidity)\n\n\n\n        # upper_price = 1.0001 ** (upper_tick_idx / 2)\n        # print(upper_tick_idx, upper_price)\n        # print(sqrt_price * 2 ** (-96))\n        # max_amount_in = (upper_price - (sqrt_price * 2 ** (-96))) * liquidity\n        # print(max_amount_in)\n        # max_amount_in = max_amount_in / 10 ** self.WETH_DECIMALS\n        # print('max_amount_in: ', max_amount_in)\n        #\n        # q96 = 2 ** 96\n        # eth = 10 ** self.WETH_DECIMALS\n        # amount_in = int(max_amount_in * eth)\n        # price_diff = int((amount_in * q96) // liquidity)\n        # print('amount_in: ', amount_in)\n        # print('price_diff: ', price_diff)\n        #\n        # sqrt_price_next = sqrt_price + price_diff\n        # print(sqrt_price, price_diff, sqrt_price_next)\n        # price_next = self.sim_v3.sqrtx96_to_price(sqrt_price_next, self.WETH_DECIMALS, self.USDT_DECIMALS, token0_in)\n        #\n        # print('price next: ', sqrt_price_next)\n        # print('new price: ', price_next)\n        #\n        # usdt_balance_before = self.usdt.functions.balanceOf(self.signer.address).call()\n\n\n\n        #     path = [self.WETH, self.USDT]\n        #     nonce = self.web3.eth.get_transaction_count(self.signer.address)\n        #     # I'm not including slippage tolerance here, so this transaction\n        #     # will most likely fail in real life scenarios unless your transaction is at the top of the block\n        #     swap_transaction = self.router2.functions.swapExactTokensForTokens(\n        #         amount_in,\n        #         sim_amount_out,\n        #         path,\n        #         self.signer.address,\n        #         int(datetime.datetime.now().timestamp()) + 60000  # 1 minute\n        #     ).build_transaction({\n        #         'from': self.signer.address,\n        #         'chainId': 1,\n        #         'nonce': nonce,\n        #         'gas': 200000,\n        #         'maxFeePerGas': self.web3.toWei(100, 'gwei'),\n        #         'maxPriorityFeePerGas': self.web3.toWei(50, 'gwei'),\n        #     })\n        #     signed = self.signer.sign_transaction(swap_transaction)\n        #     tx_hash = self.web3.eth.send_raw_transaction(signed.rawTransaction)\n        #     _ = self.web3.eth.get_transaction(tx_hash)\n\n    # def test_sim_v2_get_max_amount_in(self):\n    #     token_in = self.WETH\n    #     token0 = self.pool_v2.functions.token0().call()\n    #     token0_in = token_in == token0\n    #\n    #     reserve0, reserve1, _ = self.pool_v2.functions.getReserves().call()\n    #\n    #     self.sim_v2.get_max_amount_in(reserve0,\n    #                                   reserve1,\n    #                                   self.WETH_DECIMALS,\n    #                                   self.USDT_DECIMALS,\n    #                                   3000,\n    #                                   token0_in,\n    #                                   100,\n    #                                   0.1,\n    #                                   0.0,\n    #                                   0.0001)\n"
  }
]