diff --git a/contracts/interfaces/external/IArrakisVaultV1.sol b/contracts/interfaces/external/IArrakisVaultV1.sol new file mode 100644 index 000000000..7e3f8918b --- /dev/null +++ b/contracts/interfaces/external/IArrakisVaultV1.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-3.0 + +/* + Copyright 2022 Set Labs Inc. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import { + IUniswapV3Pool +} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; + +interface IArrakisVaultV1 { + function mint(uint256 mintAmount, address receiver) + external + returns ( + uint256 amount0, + uint256 amount1, + uint128 liquidityMinted + ); + + function burn(uint256 burnAmount, address receiver) + external + returns ( + uint256 amount0, + uint256 amount1, + uint128 liquidityBurned + ); + + function getMintAmounts(uint256 amount0Max, uint256 amount1Max) + external + view + returns ( + uint256 amount0, + uint256 amount1, + uint256 mintAmount + ); + + function getUnderlyingBalances() + external + view + returns (uint256 amount0, uint256 amount1); + + function getUnderlyingBalancesAtPrice(uint160 sqrtRatioX96) + external + view + returns (uint256 amount0Current, uint256 amount1Current); + + function getPositionID() external view returns (bytes32 positionID); + + function token0() external view returns (IERC20); + + function token1() external view returns (IERC20); + + function upperTick() external view returns (int24); + + function lowerTick() external view returns (int24); + + function pool() external view returns (IUniswapV3Pool); + + function totalSupply() external view returns (uint256); + + function balanceOf(address account) external view returns (uint256); + + function executiveRebalance( + int24 newLowerTick, + int24 newUpperTick, + uint160 swapThresholdPrice, + uint256 swapAmountBPS, + bool zeroForOne + ) external; + + function withdrawManagerBalance() external; +} \ No newline at end of file diff --git a/contracts/protocol/integration/amm/ArrakisUniswapV3AmmAdapter.sol b/contracts/protocol/integration/amm/ArrakisUniswapV3AmmAdapter.sol new file mode 100644 index 000000000..afbf52a4a --- /dev/null +++ b/contracts/protocol/integration/amm/ArrakisUniswapV3AmmAdapter.sol @@ -0,0 +1,281 @@ +/* + Copyright 2022 Set Labs Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + SPDX-License-Identifier: Apache License, Version 2.0 +*/ + +pragma solidity 0.6.10; + +import "@openzeppelin/contracts/math/SafeMath.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; +import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol"; + +import "../../../interfaces/IAmmAdapter.sol"; +import "../../../interfaces/external/IArrakisVaultV1.sol"; + +/** + * @title UniswapV3AmmAdapter + * @author Zishan Sami + * + * Adapter for Arrakis Vault representing Uniswap V3 liquidity position that encodes adding and removing liquidty + */ +contract ArrakisUniswapV3AmmAdapter is IAmmAdapter { + using SafeMath for uint256; + + /* ============ State Variables ============ */ + + // Address of Arrakis Router contract + address public immutable router; + + // UniswapV3 factory contract + IUniswapV3Factory public immutable uniV3Factory; + + // Internal function string for adding liquidity + string internal constant ADD_LIQUIDITY = + "addLiquidity(address,uint256,uint256,uint256,uint256,address)"; + // Internal function string for removing liquidity + string internal constant REMOVE_LIQUIDITY = + "removeLiquidity(address,uint256,uint256,uint256,address)"; + + /* ============ Constructor ============ */ + + /** + * Set state variables + * + * @param _router Address of Arrakis Router contract + * @param _uniV3Factory Address of UniswapV3 Factory contract + */ + constructor(address _router, address _uniV3Factory) public { + require(_router != address(0),"_router address must not be zero address"); + require(_uniV3Factory != address(0),"_uniV3Factory address must not be zero address"); + router = _router; + uniV3Factory = IUniswapV3Factory(_uniV3Factory); + } + + /* ============ External Getter Functions ============ */ + + /** + * Return calldata for the add liquidity call + * + * @param _setToken Address of the SetToken + * @param _pool Address of liquidity token + * @param _components Token address array required to remove liquidity + * @param _maxTokensIn AmountsIn desired to add liquidity + * @param _minLiquidity Min liquidity amount to add + */ + function getProvideLiquidityCalldata( + address _setToken, + address _pool, + address[] calldata _components, + uint256[] calldata _maxTokensIn, + uint256 _minLiquidity + ) + external + view + override + returns (address target, uint256 value, bytes memory data) + { + address setToken = _setToken; + address[] memory components = _components; + uint256[] memory maxTokensIn = _maxTokensIn; + uint256 minLiquidity = _minLiquidity; + + require(maxTokensIn[0] > 0 && maxTokensIn[1] > 0, "Component quantity must be nonzero"); + + IArrakisVaultV1 arrakisVaultPool = IArrakisVaultV1(_pool); + + // Sort the amount in order of tokens stored in Arrakis Pool + (uint256 maxTokensInA, uint256 maxTokensInB) = _getOrderedAmount(components[0], components[1], maxTokensIn[0], maxTokensIn[1]); + + (uint256 amountAMin, uint256 amountBMin, uint256 liquidityExpectedFromSuppliedTokens) = arrakisVaultPool.getMintAmounts(maxTokensInA, maxTokensInB); + + require( + minLiquidity <= liquidityExpectedFromSuppliedTokens, + "_minLiquidity is too high for input token limit" + ); + + target = router; + value = 0; + data = abi.encodeWithSignature( + ADD_LIQUIDITY, + arrakisVaultPool, + maxTokensInA, + maxTokensInB, + amountAMin, + amountBMin, + setToken + ); + } + + /** + * Return calldata for the add liquidity call for a single asset + */ + function getProvideLiquiditySingleAssetCalldata( + address /*_setToken*/, + address /*_pool*/, + address /*_component*/, + uint256 /*_maxTokenIn*/, + uint256 /*_minLiquidity*/ + ) + external + view + override + returns (address /*target*/, uint256 /*value*/, bytes memory /*data*/) + { + revert("Arrakis single asset addition is not supported"); + } + + /** + * Return calldata for the remove liquidity call + * + * @param _setToken Address of the SetToken + * @param _pool Address of liquidity token + * @param _components Token address array required to remove liquidity + * @param _minTokensOut AmountsOut minimum to remove liquidity + * @param _liquidity Liquidity amount to remove + */ + function getRemoveLiquidityCalldata( + address _setToken, + address _pool, + address[] calldata _components, + uint256[] calldata _minTokensOut, + uint256 _liquidity + ) + external + view + override + returns (address target, uint256 value, bytes memory data) + { + address setToken = _setToken; + address[] memory components = _components; + uint256[] memory minTokensOut = _minTokensOut; + uint256 liquidity = _liquidity; + IArrakisVaultV1 arrakisVaultPool = IArrakisVaultV1(_pool); + + // Make sure that only up to the amount of liquidity tokens owned by the Set Token are redeemed + uint256 setTokenLiquidityBalance = arrakisVaultPool.balanceOf(setToken); + require(liquidity <= setTokenLiquidityBalance, "_liquidity must be <= to current balance"); + + // Checks for minTokensOut + require(minTokensOut[0] > 0 && minTokensOut[1] > 0, "Minimum quantity must be nonzero"); + + // Sort the amount in order of tokens stored in Arrakis Pool + (uint256 minTokensOutA, uint256 minTokensOutB) = _getOrderedAmount(components[0], components[1], minTokensOut[0], minTokensOut[1]); + + target = router; + value = 0; + data = abi.encodeWithSignature( + REMOVE_LIQUIDITY, + arrakisVaultPool, + liquidity, + minTokensOutA, + minTokensOutB, + setToken + ); + } + + /** + * Return calldata for the remove liquidity single asset call + */ + function getRemoveLiquiditySingleAssetCalldata( + address /* _setToken */, + address /*_pool*/, + address /*_component*/, + uint256 /*_minTokenOut*/, + uint256 /*_liquidity*/ + ) + external + view + override + returns (address /*target*/, uint256 /*value*/, bytes memory /*data*/) + { + revert("Arrakis single asset removal is not supported"); + } + + /** + * Returns the address of the spender + */ + function getSpenderAddress(address /*_pool*/) + external + view + override + returns (address spender) + { + spender = router; + } + + /** + * Verifies that this is an Arrakis Vault pool holding valid UniswapV3 position + * + * @param _pool Address of liquidity token + * @param _components Address array of supplied/requested tokens + */ + function isValidPool(address _pool, address[] memory _components) + external + view + override + returns (bool) + { + // Attempt to get the tokens of the provided pool + address token0; + address token1; + try IArrakisVaultV1(_pool).token0() returns (IERC20 _token0) { + token0 = address(_token0); + } catch { + return false; + } + try IArrakisVaultV1(_pool).token1() returns (IERC20 _token1) { + token1 = address(_token1); + } catch { + return false; + } + + // Make sure that components length is two + if (_components.length != 2) { + return false; + } + + // Make sure that _components[0] is either of token0 or token1 + if (!(_components[0] == token0 || _components[0] == token1) ) { + return false; + } + + // Make sure that _components[1] is either of token0 or token1 + if (!(_components[1] == token0 || _components[1] == token1) ) { + return false; + } + + // Make sure the pool address follows IERC20 interface + try IArrakisVaultV1(_pool).totalSupply() returns (uint256) { + } catch { + return false; + } + + return true; + } + + /** + * Sorts the amount in order of tokens stored in Arrakis/UniswapV3 Pool + * + * @param _token0 Address of token0 + * @param _token1 Address of token1 + * @param _amount0 Amount of token0 + * @param _amount1 Amount of token1 + */ + function _getOrderedAmount(address _token0, address _token1, uint256 _amount0, uint256 _amount1) private pure returns(uint256, uint256) { + return _token0 < _token1 ? (_amount0, _amount1) : (_amount1, _amount0); + } +} \ No newline at end of file diff --git a/external/abi/arrakis/ArrakisFactoryV1.json b/external/abi/arrakis/ArrakisFactoryV1.json new file mode 100644 index 000000000..a1181ba5b --- /dev/null +++ b/external/abi/arrakis/ArrakisFactoryV1.json @@ -0,0 +1,459 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ArrakisFactoryV1", + "sourceName": "contracts/ArrakisFactoryV1.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_uniswapV3Factory", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newManager", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "uniPool", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "UpdatePoolImplementation", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "uint24", + "name": "uniFee", + "type": "uint24" + }, + { + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "managerFee", + "type": "uint16" + }, + { + "internalType": "int24", + "name": "lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "upperTick", + "type": "int24" + } + ], + "name": "deployVault", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gelatoDeployer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDeployers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGelatoPools", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "deployer", + "type": "address" + } + ], + "name": "getPools", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + } + ], + "name": "getTokenName", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "index", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_manager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPoolImmutable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "pools", + "type": "address[]" + } + ], + "name": "makePoolsImmutable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numDeployers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numPools", + "outputs": [ + { + "internalType": "uint256", + "name": "result", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "deployer", + "type": "address" + } + ], + "name": "numPools", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "nextImplementation", + "type": "address" + } + ], + "name": "setPoolImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "pools", + "type": "address[]" + } + ], + "name": "upgradePools", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "pools", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "datas", + "type": "bytes[]" + } + ], + "name": "upgradePoolsAndCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a060405234801561001057600080fd5b506040516128a63803806128a683398101604081905261002f91610044565b60601b6001600160601b031916608052610072565b600060208284031215610055578081fd5b81516001600160a01b038116811461006b578182fd5b9392505050565b60805160601c61280f610097600039600081816102cb0152611177015261280f6000f3fe60806040523480156200001157600080fd5b5060043610620001365760003560e01c8063098eddb1146200013b5780630dfc574b1462000158578063260fc2b814620001715780632986c0e5146200018857806335c62bc2146200019257806340aee041146200019c57806342f5de9914620001b3578063481c6a7514620001ca578063485cc95514620001e357806354fd4d5014620001fa578063562b8103146200022e5780635c39f4671462000247578063607c12b5146200025e578063715018a6146200026857806386238765146200027257806395d807f11462000286578063bd30dfb914620002ae578063c45a015514620002c5578063cefa779914620002ed578063d6f748981462000301578063f2fde38b1462000318578063f3b7dead146200032f578063fef46b281462000346575b600080fd5b620001456200035d565b6040519081526020015b60405180910390f35b6200016f62000169366004620018a0565b62000370565b005b6200016f6200018236600462001862565b620004f9565b6200014560065481565b62000145620005df565b6200016f620001ad36600462001862565b62000656565b62000145620001c436600462001738565b62000740565b620001d462000769565b6040516200014f919062001aa8565b6200016f620001f436600462001776565b62000778565b6200021f604051806040016040528060058152602001640312e302e360dc1b81525081565b6040516200014f919062001b65565b6200023862000875565b6040516200014f919062001b16565b620002386200025836600462001738565b6200088a565b620002386200095f565b6200016f62000a31565b600254620001d4906001600160a01b031681565b6200029d6200029736600462001738565b62000a9e565b60405190151581526020016200014f565b6200021f620002bf36600462001776565b62000abb565b620001d47f000000000000000000000000000000000000000000000000000000000000000081565b600154620001d4906001600160a01b031681565b6200016f6200031236600462001738565b62000c10565b6200016f6200032936600462001738565b62000caf565b620001d46200034036600462001738565b62000d96565b620001d462000357366004620017b3565b62000e0d565b60006200036b600362000e2c565b905090565b336200037b62000769565b6001600160a01b031614620003ad5760405162461bcd60e51b8152600401620003a49062001be5565b60405180910390fd5b82518114620003fa5760405162461bcd60e51b81526020600482015260186024820152770dad2e6dac2e8c6d0d2dcce40c2e4e4c2f240d8cadccee8d60431b6044820152606401620003a4565b60005b8351811015620004f3578381815181106200042857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316634f1ef286600160009054906101000a90046001600160a01b03168585858181106200047557634e487b7160e01b600052603260045260246000fd5b905060200281019062000489919062001c27565b6040518463ffffffff1660e01b8152600401620004a99392919062001ad6565b600060405180830381600087803b158015620004c457600080fd5b505af1158015620004d9573d6000803e3d6000fd5b505050508080620004ea9062001d66565b915050620003fd565b50505050565b336200050462000769565b6001600160a01b0316146200052d5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db578181815181106200055b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316638356ca4f60006040518263ffffffff1660e01b815260040162000591919062001aa8565b600060405180830381600087803b158015620005ac57600080fd5b505af1158015620005c1573d6000803e3d6000fd5b505050508080620005d29062001d66565b91505062000530565b5050565b600080620005ec6200095f565b905060005b815181101562000651576200062e8282815181106200062057634e487b7160e01b600052603260045260246000fd5b602002602001015162000740565b6200063a908462001ca1565b925080620006488162001d66565b915050620005f1565b505090565b336200066162000769565b6001600160a01b0316146200068a5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db57818181518110620006b857634e487b7160e01b600052603260045260246000fd5b6020908102919091010151600154604051631b2ce7f360e11b81526001600160a01b0392831692633659cfe692620006f69291169060040162001aa8565b600060405180830381600087803b1580156200071157600080fd5b505af115801562000726573d6000803e3d6000fd5b505050508080620007379062001d66565b9150506200068d565b6001600160a01b0381166000908152600560205260408120620007639062000e2c565b92915050565b6000546001600160a01b031690565b600054600160a81b900460ff16806200079b5750600054600160a01b900460ff16155b620008005760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620003a4565b600054600160a81b900460ff161580156200082b576000805461ffff60a01b191661010160a01b1790555b600180546001600160a01b038086166001600160a01b0319928316179092556000805492851692909116919091179055801562000870576000805460ff60a81b191690555b505050565b6002546060906200036b906001600160a01b03165b60606000620008998362000740565b90506000816001600160401b03811115620008c457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620008ee578160200160208202803683370190505b50905060005b82811015620009575762000909858262000e37565b8282815181106200092a57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806200094e8162001d66565b915050620008f4565b509392505050565b606060006200096d6200035d565b90506000816001600160401b038111156200099857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620009c2578160200160208202803683370190505b50905060005b8281101562000a2a57620009dc8162000e62565b828281518110620009fd57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528062000a218162001d66565b915050620009c8565b5092915050565b3362000a3c62000769565b6001600160a01b03161462000a655760405162461bcd60e51b8152600401620003a49062001be5565b600080546040516001600160a01b0390911690600080516020620027ba833981519152908390a3600080546001600160a01b0319169055565b600062000aab8262000d96565b6001600160a01b03161592915050565b60606000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000af957600080fd5b505afa15801562000b0e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000b3891908101906200195a565b90506000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000b7657600080fd5b505afa15801562000b8b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000bb591908101906200195a565b905062000c0760405180604001604052806011815260200170020b93930b5b4b9902b30bab63a102b189607d1b81525083604051806040016040528060018152602001602f60f81b8152508462000e71565b95945050505050565b3362000c1b62000769565b6001600160a01b03161462000c445760405162461bcd60e51b8152600401620003a49062001be5565b6001546040517f0617fd31aa5ab95ec80eefc1eb61a2c477aa419d1d761b4e46f5f077e47852aa9162000c85916001600160a01b0390911690849062001abc565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b3362000cba62000769565b6001600160a01b03161462000ce35760405162461bcd60e51b8152600401620003a49062001be5565b6001600160a01b03811662000d4c5760405162461bcd60e51b815260206004820152602860248201527f4f776e61626c653a206e6577206d616e6167657220697320746865207a65726f604482015267206164647265737360c01b6064820152608401620003a4565b600080546040516001600160a01b0380851693921691600080516020620027ba83398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b0316633e47158c6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000dd257600080fd5b505afa15801562000de7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000763919062001757565b600062000e208888888888888862000ea5565b98975050505050505050565b600062000763825490565b6001600160a01b038216600090815260056020526040812062000e5b90836200100c565b9392505050565b6000620007636003836200100c565b60608484848460405160200162000e8c949392919062001a19565b6040516020818303038152906040529050949350505050565b600080606062000eb98a8a8a88886200101a565b60065492955090935091506001600160a01b0384169063e25e15e390839062000eef9062000ee990600162001ca1565b620012ac565b60405160200162000f01919062001a78565b604051602081830303815290604052858a8a8a8e6040518863ffffffff1660e01b815260040162000f39979695949392919062001b7a565b600060405180830381600087803b15801562000f5457600080fd5b505af115801562000f69573d6000803e3d6000fd5b5050505062000f838760036200140890919063ffffffff16565b506001600160a01b038716600090815260056020526040902062000fa8908462001408565b5060016006600082825462000fbe919062001ca1565b90915550506040516001600160a01b0380851691898216918516907f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b90600090a45050979650505050505050565b600062000e5b83836200141f565b60008060606000806200102e8a8a620014b6565b6001546040519294509092506001600160a01b0316903090620010519062001694565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f08015801562001094573d6000803e3d6000fd5b50604080518082018252601081526f417272616b6973205661756c7420563160801b6020820152905163bd30dfb960e01b81529196509350309063bd30dfb990620010e6908590859060040162001abc565b60006040518083038186803b158015620010ff57600080fd5b505afa9250505080156200113757506040513d6000823e601f3d908101601f191682016040526200113491908101906200195a565b60015b620011425762001145565b92505b604051630b4c774160e11b81526001600160a01b038381166004830152828116602483015262ffffff8a1660448301527f00000000000000000000000000000000000000000000000000000000000000001690631698ee829060640160206040518083038186803b158015620011ba57600080fd5b505afa158015620011cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011f5919062001757565b93506001600160a01b0384166200124d5760405162461bcd60e51b815260206004820152601b60248201527a1d5b9a5cddd85c081c1bdbdb08191bd95cc81b9bdd08195e1a5cdd602a1b6044820152606401620003a4565b6200125a84888862001585565b6200129f5760405162461bcd60e51b81526020600482015260146024820152730e8d2c6d6a6e0c2c6d2dcce40dad2e6dac2e8c6d60631b6044820152606401620003a4565b5050955095509592505050565b606081620012d15750506040805180820190915260018152600360fc1b602082015290565b8160005b8115620013015780620012e88162001d66565b9150620012f99050600a8362001ce4565b9150620012d5565b6000816001600160401b038111156200132a57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801562001355576020820181803683370190505b509050815b8515620013ff576200136e60018262001d1d565b905060006200137f600a8862001ce4565b6200138c90600a62001cfb565b62001398908862001d1d565b620013a590603062001cbc565b905060008160f81b905080848481518110620013d157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350620013f5600a8962001ce4565b975050506200135a565b50949350505050565b600062000e5b836001600160a01b03841662001642565b815460009082106200147f5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401620003a4565b826000018281548110620014a357634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b600080826001600160a01b0316846001600160a01b031614156200150a5760405162461bcd60e51b815260206004820152600a60248201526939b0b6b2903a37b5b2b760b11b6044820152606401620003a4565b826001600160a01b0316846001600160a01b0316106200152c5782846200152f565b83835b90925090506001600160a01b0382166200157e5760405162461bcd60e51b815260206004820152600f60248201526e6e6f2061646472657373207a65726f60881b6044820152606401620003a4565b9250929050565b600080846001600160a01b031663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015620015c257600080fd5b505afa158015620015d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015fd91906200193b565b90508260020b8460020b1280156200162157506200161c818562001d84565b60020b155b801562000c07575062001635818462001d84565b60020b1595945050505050565b60008181526001830160205260408120546200168b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000763565b50600062000763565b6109a58062001e1583390190565b600082601f830112620016b3578081fd5b813560206001600160401b03821115620016d157620016d162001dd5565b8160051b620016e282820162001c6e565b838152828101908684018388018501891015620016fd578687fd5b8693505b858410156200172c578035620017178162001deb565b83526001939093019291840191840162001701565b50979650505050505050565b6000602082840312156200174a578081fd5b813562000e5b8162001deb565b60006020828403121562001769578081fd5b815162000e5b8162001deb565b6000806040838503121562001789578081fd5b8235620017968162001deb565b91506020830135620017a88162001deb565b809150509250929050565b600080600080600080600060e0888a031215620017ce578283fd5b8735620017db8162001deb565b96506020880135620017ed8162001deb565b9550604088013562ffffff8116811462001805578384fd5b94506060880135620018178162001deb565b9350608088013561ffff811681146200182e578384fd5b925060a0880135620018408162001e04565b915060c0880135620018528162001e04565b8091505092959891949750929550565b60006020828403121562001874578081fd5b81356001600160401b038111156200188a578182fd5b6200189884828501620016a2565b949350505050565b600080600060408486031215620018b5578283fd5b83356001600160401b0380821115620018cc578485fd5b620018da87838801620016a2565b94506020860135915080821115620018f0578384fd5b818601915086601f83011262001904578384fd5b81358181111562001913578485fd5b8760208260051b850101111562001928578485fd5b6020830194508093505050509250925092565b6000602082840312156200194d578081fd5b815162000e5b8162001e04565b6000602082840312156200196c578081fd5b81516001600160401b038082111562001983578283fd5b818401915084601f83011262001997578283fd5b815181811115620019ac57620019ac62001dd5565b620019c1601f8201601f191660200162001c6e565b9150808252856020828501011115620019d8578384fd5b620013ff81602084016020860162001d37565b6000815180845262001a0581602086016020860162001d37565b601f01601f19169290920160200192915050565b6000855162001a2d818460208a0162001d37565b85519083019062001a43818360208a0162001d37565b855191019062001a5881836020890162001d37565b845191019062001a6d81836020880162001d37565b019695505050505050565b6552414b49532d60d01b81526000825162001a9b81600685016020870162001d37565b9190910160060192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b6020808252825182820181905260009190848201906040850190845b8181101562001b595783516001600160a01b03168352928401929184019160010162001b32565b50909695505050505050565b60208152600062000e5b6020830184620019eb565b60e08152600062001b8f60e083018a620019eb565b828103602084015262001ba3818a620019eb565b6001600160a01b03988916604085015261ffff9790971660608401525050600293840b60808201529190920b60a0820152921660c09092019190915292915050565b60208082526022908201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206d616e616760408201526132b960f11b606082015260800190565b6000808335601e1984360301811262001c3e578283fd5b8301803591506001600160401b0382111562001c58578283fd5b6020019150368190038213156200157e57600080fd5b604051601f8201601f191681016001600160401b038111828210171562001c995762001c9962001dd5565b604052919050565b6000821982111562001cb75762001cb762001da9565b500190565b600060ff821660ff84168060ff0382111562001cdc5762001cdc62001da9565b019392505050565b60008262001cf65762001cf662001dbf565b500490565b600081600019048311821515161562001d185762001d1862001da9565b500290565b60008282101562001d325762001d3262001da9565b500390565b60005b8381101562001d5457818101518382015260200162001d3a565b83811115620004f35750506000910152565b600060001982141562001d7d5762001d7d62001da9565b5060010190565b60008260020b8062001d9a5762001d9a62001dbf565b808360020b0791505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811462001e0157600080fd5b50565b8060020b811462001e0157600080fdfe60806040526040516109a53803806109a5833981016040819052610022916101a4565b61002c838261003d565b61003582610119565b5050506102ce565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610114576000836001600160a01b0316836040516100be9190610270565b600060405180830381855af49150503d80600081146100f9576040519150601f19603f3d011682016040523d82523d6000602084013e6100fe565b606091505b5050905080610112573d806000803e806000fd5b505b505050565b60006101316000805160206109858339815191525490565b90508160008051602061098583398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80516001600160a01b038116811461019f57600080fd5b919050565b6000806000606084860312156101b8578283fd5b6101c184610188565b92506101cf60208501610188565b60408501519092506001600160401b03808211156101eb578283fd5b818601915086601f8301126101fe578283fd5b815181811115610210576102106102b8565b604051601f8201601f19908116603f01168101908382118183101715610238576102386102b8565b81604052828152896020848701011115610250578586fd5b61026183602083016020880161028c565b80955050505050509250925092565b6000825161028281846020870161028c565b9190910192915050565b60005b838110156102a757818101518382015260200161028f565b838111156101125750506000910152565b634e487b7160e01b600052604160045260246000fd5b6106a8806102dd6000396000f3fe60806040526004361061004e5760003560e01c806301ffc9a71461009b5780633659cfe6146100d05780633e47158c146100f05780634f1ef2861461011d5780638356ca4f1461013057610091565b366100915760405162461bcd60e51b815260206004820152600e60248201526d115512115497d491529150d5115160921b60448201526064015b60405180910390fd5b610099610150565b005b3480156100a757600080fd5b506100bb6100b63660046105a9565b610189565b60405190151581526020015b60405180910390f35b3480156100dc57600080fd5b506100996100eb3660046104f2565b61027e565b3480156100fc57600080fd5b506101056102d2565b6040516001600160a01b0390911681526020016100c7565b61009961012b36600461050c565b6102e1565b34801561013c57600080fd5b5061009961014b3660046104f2565b61035e565b6000805160206106538339815191525460003681823780813683855af491503d8082833e82801561017f578183f35b8183fd5b50505050565b60006301ffc9a760e01b6001600160e01b0319831614806101ba57506307f5828d60e41b6001600160e01b03198316145b156101c757506001919050565b6001600160e01b031980831614156101e157506000919050565b600080516020610653833981519152546040516301ffc9a760e01b81526001600160e01b0319841660048201526001600160a01b038216906301ffc9a79060240160206040518083038186803b15801561023a57600080fd5b505afa92505050801561026a575060408051601f3d908101601f1916820190925261026791810190610589565b60015b6102775750600092915050565b9392505050565b61028661039f565b6001600160a01b0316336001600160a01b0316146102b65760405162461bcd60e51b81526004016100889061060a565b6102cf81604051806020016040528060008152506103b2565b50565b60006102dc61039f565b905090565b6102e961039f565b6001600160a01b0316336001600160a01b0316146103195760405162461bcd60e51b81526004016100889061060a565b6103598383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103b292505050565b505050565b61036661039f565b6001600160a01b0316336001600160a01b0316146103965760405162461bcd60e51b81526004016100889061060a565b6102cf81610475565b6000805160206106338339815191525490565b6000805160206106538339815191528054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610359576000836001600160a01b03168360405161042191906105d1565b600060405180830381855af49150503d806000811461045c576040519150601f19603f3d011682016040523d82523d6000602084013e610461565b606091505b5050905080610183573d806000803e806000fd5b600061047f61039f565b90508160008051602061063383398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80356001600160a01b03811681146104ed57600080fd5b919050565b600060208284031215610503578081fd5b610277826104d6565b600080600060408486031215610520578182fd5b610529846104d6565b925060208401356001600160401b0380821115610544578384fd5b818601915086601f830112610557578384fd5b813581811115610565578485fd5b876020828501011115610576578485fd5b6020830194508093505050509250925092565b60006020828403121561059a578081fd5b81518015158114610277578182fd5b6000602082840312156105ba578081fd5b81356001600160e01b031981168114610277578182fd5b60008251815b818110156105f157602081860181015185830152016105d7565b818111156105ff5782828501525b509190910192915050565b6020808252600e908201526d1393d517d055551213d49256915160921b60408201526060019056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220730effc08e7ae1c19f69ae08dd52de483b649ded49db9428e4ced9875431474364736f6c63430008040033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a264697066735822122032c0226340af0379cd7d43429d1502fc96d02b3e0f888c97b7ed277717483dc364736f6c63430008040033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620001365760003560e01c8063098eddb1146200013b5780630dfc574b1462000158578063260fc2b814620001715780632986c0e5146200018857806335c62bc2146200019257806340aee041146200019c57806342f5de9914620001b3578063481c6a7514620001ca578063485cc95514620001e357806354fd4d5014620001fa578063562b8103146200022e5780635c39f4671462000247578063607c12b5146200025e578063715018a6146200026857806386238765146200027257806395d807f11462000286578063bd30dfb914620002ae578063c45a015514620002c5578063cefa779914620002ed578063d6f748981462000301578063f2fde38b1462000318578063f3b7dead146200032f578063fef46b281462000346575b600080fd5b620001456200035d565b6040519081526020015b60405180910390f35b6200016f62000169366004620018a0565b62000370565b005b6200016f6200018236600462001862565b620004f9565b6200014560065481565b62000145620005df565b6200016f620001ad36600462001862565b62000656565b62000145620001c436600462001738565b62000740565b620001d462000769565b6040516200014f919062001aa8565b6200016f620001f436600462001776565b62000778565b6200021f604051806040016040528060058152602001640312e302e360dc1b81525081565b6040516200014f919062001b65565b6200023862000875565b6040516200014f919062001b16565b620002386200025836600462001738565b6200088a565b620002386200095f565b6200016f62000a31565b600254620001d4906001600160a01b031681565b6200029d6200029736600462001738565b62000a9e565b60405190151581526020016200014f565b6200021f620002bf36600462001776565b62000abb565b620001d47f000000000000000000000000000000000000000000000000000000000000000081565b600154620001d4906001600160a01b031681565b6200016f6200031236600462001738565b62000c10565b6200016f6200032936600462001738565b62000caf565b620001d46200034036600462001738565b62000d96565b620001d462000357366004620017b3565b62000e0d565b60006200036b600362000e2c565b905090565b336200037b62000769565b6001600160a01b031614620003ad5760405162461bcd60e51b8152600401620003a49062001be5565b60405180910390fd5b82518114620003fa5760405162461bcd60e51b81526020600482015260186024820152770dad2e6dac2e8c6d0d2dcce40c2e4e4c2f240d8cadccee8d60431b6044820152606401620003a4565b60005b8351811015620004f3578381815181106200042857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316634f1ef286600160009054906101000a90046001600160a01b03168585858181106200047557634e487b7160e01b600052603260045260246000fd5b905060200281019062000489919062001c27565b6040518463ffffffff1660e01b8152600401620004a99392919062001ad6565b600060405180830381600087803b158015620004c457600080fd5b505af1158015620004d9573d6000803e3d6000fd5b505050508080620004ea9062001d66565b915050620003fd565b50505050565b336200050462000769565b6001600160a01b0316146200052d5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db578181815181106200055b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316638356ca4f60006040518263ffffffff1660e01b815260040162000591919062001aa8565b600060405180830381600087803b158015620005ac57600080fd5b505af1158015620005c1573d6000803e3d6000fd5b505050508080620005d29062001d66565b91505062000530565b5050565b600080620005ec6200095f565b905060005b815181101562000651576200062e8282815181106200062057634e487b7160e01b600052603260045260246000fd5b602002602001015162000740565b6200063a908462001ca1565b925080620006488162001d66565b915050620005f1565b505090565b336200066162000769565b6001600160a01b0316146200068a5760405162461bcd60e51b8152600401620003a49062001be5565b60005b8151811015620005db57818181518110620006b857634e487b7160e01b600052603260045260246000fd5b6020908102919091010151600154604051631b2ce7f360e11b81526001600160a01b0392831692633659cfe692620006f69291169060040162001aa8565b600060405180830381600087803b1580156200071157600080fd5b505af115801562000726573d6000803e3d6000fd5b505050508080620007379062001d66565b9150506200068d565b6001600160a01b0381166000908152600560205260408120620007639062000e2c565b92915050565b6000546001600160a01b031690565b600054600160a81b900460ff16806200079b5750600054600160a01b900460ff16155b620008005760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620003a4565b600054600160a81b900460ff161580156200082b576000805461ffff60a01b191661010160a01b1790555b600180546001600160a01b038086166001600160a01b0319928316179092556000805492851692909116919091179055801562000870576000805460ff60a81b191690555b505050565b6002546060906200036b906001600160a01b03165b60606000620008998362000740565b90506000816001600160401b03811115620008c457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620008ee578160200160208202803683370190505b50905060005b82811015620009575762000909858262000e37565b8282815181106200092a57634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806200094e8162001d66565b915050620008f4565b509392505050565b606060006200096d6200035d565b90506000816001600160401b038111156200099857634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620009c2578160200160208202803683370190505b50905060005b8281101562000a2a57620009dc8162000e62565b828281518110620009fd57634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528062000a218162001d66565b915050620009c8565b5092915050565b3362000a3c62000769565b6001600160a01b03161462000a655760405162461bcd60e51b8152600401620003a49062001be5565b600080546040516001600160a01b0390911690600080516020620027ba833981519152908390a3600080546001600160a01b0319169055565b600062000aab8262000d96565b6001600160a01b03161592915050565b60606000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000af957600080fd5b505afa15801562000b0e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000b3891908101906200195a565b90506000836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801562000b7657600080fd5b505afa15801562000b8b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000bb591908101906200195a565b905062000c0760405180604001604052806011815260200170020b93930b5b4b9902b30bab63a102b189607d1b81525083604051806040016040528060018152602001602f60f81b8152508462000e71565b95945050505050565b3362000c1b62000769565b6001600160a01b03161462000c445760405162461bcd60e51b8152600401620003a49062001be5565b6001546040517f0617fd31aa5ab95ec80eefc1eb61a2c477aa419d1d761b4e46f5f077e47852aa9162000c85916001600160a01b0390911690849062001abc565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b3362000cba62000769565b6001600160a01b03161462000ce35760405162461bcd60e51b8152600401620003a49062001be5565b6001600160a01b03811662000d4c5760405162461bcd60e51b815260206004820152602860248201527f4f776e61626c653a206e6577206d616e6167657220697320746865207a65726f604482015267206164647265737360c01b6064820152608401620003a4565b600080546040516001600160a01b0380851693921691600080516020620027ba83398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b0316633e47158c6040518163ffffffff1660e01b815260040160206040518083038186803b15801562000dd257600080fd5b505afa15801562000de7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000763919062001757565b600062000e208888888888888862000ea5565b98975050505050505050565b600062000763825490565b6001600160a01b038216600090815260056020526040812062000e5b90836200100c565b9392505050565b6000620007636003836200100c565b60608484848460405160200162000e8c949392919062001a19565b6040516020818303038152906040529050949350505050565b600080606062000eb98a8a8a88886200101a565b60065492955090935091506001600160a01b0384169063e25e15e390839062000eef9062000ee990600162001ca1565b620012ac565b60405160200162000f01919062001a78565b604051602081830303815290604052858a8a8a8e6040518863ffffffff1660e01b815260040162000f39979695949392919062001b7a565b600060405180830381600087803b15801562000f5457600080fd5b505af115801562000f69573d6000803e3d6000fd5b5050505062000f838760036200140890919063ffffffff16565b506001600160a01b038716600090815260056020526040902062000fa8908462001408565b5060016006600082825462000fbe919062001ca1565b90915550506040516001600160a01b0380851691898216918516907f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b90600090a45050979650505050505050565b600062000e5b83836200141f565b60008060606000806200102e8a8a620014b6565b6001546040519294509092506001600160a01b0316903090620010519062001694565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f08015801562001094573d6000803e3d6000fd5b50604080518082018252601081526f417272616b6973205661756c7420563160801b6020820152905163bd30dfb960e01b81529196509350309063bd30dfb990620010e6908590859060040162001abc565b60006040518083038186803b158015620010ff57600080fd5b505afa9250505080156200113757506040513d6000823e601f3d908101601f191682016040526200113491908101906200195a565b60015b620011425762001145565b92505b604051630b4c774160e11b81526001600160a01b038381166004830152828116602483015262ffffff8a1660448301527f00000000000000000000000000000000000000000000000000000000000000001690631698ee829060640160206040518083038186803b158015620011ba57600080fd5b505afa158015620011cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011f5919062001757565b93506001600160a01b0384166200124d5760405162461bcd60e51b815260206004820152601b60248201527a1d5b9a5cddd85c081c1bdbdb08191bd95cc81b9bdd08195e1a5cdd602a1b6044820152606401620003a4565b6200125a84888862001585565b6200129f5760405162461bcd60e51b81526020600482015260146024820152730e8d2c6d6a6e0c2c6d2dcce40dad2e6dac2e8c6d60631b6044820152606401620003a4565b5050955095509592505050565b606081620012d15750506040805180820190915260018152600360fc1b602082015290565b8160005b8115620013015780620012e88162001d66565b9150620012f99050600a8362001ce4565b9150620012d5565b6000816001600160401b038111156200132a57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801562001355576020820181803683370190505b509050815b8515620013ff576200136e60018262001d1d565b905060006200137f600a8862001ce4565b6200138c90600a62001cfb565b62001398908862001d1d565b620013a590603062001cbc565b905060008160f81b905080848481518110620013d157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350620013f5600a8962001ce4565b975050506200135a565b50949350505050565b600062000e5b836001600160a01b03841662001642565b815460009082106200147f5760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b6064820152608401620003a4565b826000018281548110620014a357634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b600080826001600160a01b0316846001600160a01b031614156200150a5760405162461bcd60e51b815260206004820152600a60248201526939b0b6b2903a37b5b2b760b11b6044820152606401620003a4565b826001600160a01b0316846001600160a01b0316106200152c5782846200152f565b83835b90925090506001600160a01b0382166200157e5760405162461bcd60e51b815260206004820152600f60248201526e6e6f2061646472657373207a65726f60881b6044820152606401620003a4565b9250929050565b600080846001600160a01b031663d0c93a7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015620015c257600080fd5b505afa158015620015d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015fd91906200193b565b90508260020b8460020b1280156200162157506200161c818562001d84565b60020b155b801562000c07575062001635818462001d84565b60020b1595945050505050565b60008181526001830160205260408120546200168b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000763565b50600062000763565b6109a58062001e1583390190565b600082601f830112620016b3578081fd5b813560206001600160401b03821115620016d157620016d162001dd5565b8160051b620016e282820162001c6e565b838152828101908684018388018501891015620016fd578687fd5b8693505b858410156200172c578035620017178162001deb565b83526001939093019291840191840162001701565b50979650505050505050565b6000602082840312156200174a578081fd5b813562000e5b8162001deb565b60006020828403121562001769578081fd5b815162000e5b8162001deb565b6000806040838503121562001789578081fd5b8235620017968162001deb565b91506020830135620017a88162001deb565b809150509250929050565b600080600080600080600060e0888a031215620017ce578283fd5b8735620017db8162001deb565b96506020880135620017ed8162001deb565b9550604088013562ffffff8116811462001805578384fd5b94506060880135620018178162001deb565b9350608088013561ffff811681146200182e578384fd5b925060a0880135620018408162001e04565b915060c0880135620018528162001e04565b8091505092959891949750929550565b60006020828403121562001874578081fd5b81356001600160401b038111156200188a578182fd5b6200189884828501620016a2565b949350505050565b600080600060408486031215620018b5578283fd5b83356001600160401b0380821115620018cc578485fd5b620018da87838801620016a2565b94506020860135915080821115620018f0578384fd5b818601915086601f83011262001904578384fd5b81358181111562001913578485fd5b8760208260051b850101111562001928578485fd5b6020830194508093505050509250925092565b6000602082840312156200194d578081fd5b815162000e5b8162001e04565b6000602082840312156200196c578081fd5b81516001600160401b038082111562001983578283fd5b818401915084601f83011262001997578283fd5b815181811115620019ac57620019ac62001dd5565b620019c1601f8201601f191660200162001c6e565b9150808252856020828501011115620019d8578384fd5b620013ff81602084016020860162001d37565b6000815180845262001a0581602086016020860162001d37565b601f01601f19169290920160200192915050565b6000855162001a2d818460208a0162001d37565b85519083019062001a43818360208a0162001d37565b855191019062001a5881836020890162001d37565b845191019062001a6d81836020880162001d37565b019695505050505050565b6552414b49532d60d01b81526000825162001a9b81600685016020870162001d37565b9190910160060192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b6020808252825182820181905260009190848201906040850190845b8181101562001b595783516001600160a01b03168352928401929184019160010162001b32565b50909695505050505050565b60208152600062000e5b6020830184620019eb565b60e08152600062001b8f60e083018a620019eb565b828103602084015262001ba3818a620019eb565b6001600160a01b03988916604085015261ffff9790971660608401525050600293840b60808201529190920b60a0820152921660c09092019190915292915050565b60208082526022908201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206d616e616760408201526132b960f11b606082015260800190565b6000808335601e1984360301811262001c3e578283fd5b8301803591506001600160401b0382111562001c58578283fd5b6020019150368190038213156200157e57600080fd5b604051601f8201601f191681016001600160401b038111828210171562001c995762001c9962001dd5565b604052919050565b6000821982111562001cb75762001cb762001da9565b500190565b600060ff821660ff84168060ff0382111562001cdc5762001cdc62001da9565b019392505050565b60008262001cf65762001cf662001dbf565b500490565b600081600019048311821515161562001d185762001d1862001da9565b500290565b60008282101562001d325762001d3262001da9565b500390565b60005b8381101562001d5457818101518382015260200162001d3a565b83811115620004f35750506000910152565b600060001982141562001d7d5762001d7d62001da9565b5060010190565b60008260020b8062001d9a5762001d9a62001dbf565b808360020b0791505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811462001e0157600080fd5b50565b8060020b811462001e0157600080fdfe60806040526040516109a53803806109a5833981016040819052610022916101a4565b61002c838261003d565b61003582610119565b5050506102ce565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610114576000836001600160a01b0316836040516100be9190610270565b600060405180830381855af49150503d80600081146100f9576040519150601f19603f3d011682016040523d82523d6000602084013e6100fe565b606091505b5050905080610112573d806000803e806000fd5b505b505050565b60006101316000805160206109858339815191525490565b90508160008051602061098583398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80516001600160a01b038116811461019f57600080fd5b919050565b6000806000606084860312156101b8578283fd5b6101c184610188565b92506101cf60208501610188565b60408501519092506001600160401b03808211156101eb578283fd5b818601915086601f8301126101fe578283fd5b815181811115610210576102106102b8565b604051601f8201601f19908116603f01168101908382118183101715610238576102386102b8565b81604052828152896020848701011115610250578586fd5b61026183602083016020880161028c565b80955050505050509250925092565b6000825161028281846020870161028c565b9190910192915050565b60005b838110156102a757818101518382015260200161028f565b838111156101125750506000910152565b634e487b7160e01b600052604160045260246000fd5b6106a8806102dd6000396000f3fe60806040526004361061004e5760003560e01c806301ffc9a71461009b5780633659cfe6146100d05780633e47158c146100f05780634f1ef2861461011d5780638356ca4f1461013057610091565b366100915760405162461bcd60e51b815260206004820152600e60248201526d115512115497d491529150d5115160921b60448201526064015b60405180910390fd5b610099610150565b005b3480156100a757600080fd5b506100bb6100b63660046105a9565b610189565b60405190151581526020015b60405180910390f35b3480156100dc57600080fd5b506100996100eb3660046104f2565b61027e565b3480156100fc57600080fd5b506101056102d2565b6040516001600160a01b0390911681526020016100c7565b61009961012b36600461050c565b6102e1565b34801561013c57600080fd5b5061009961014b3660046104f2565b61035e565b6000805160206106538339815191525460003681823780813683855af491503d8082833e82801561017f578183f35b8183fd5b50505050565b60006301ffc9a760e01b6001600160e01b0319831614806101ba57506307f5828d60e41b6001600160e01b03198316145b156101c757506001919050565b6001600160e01b031980831614156101e157506000919050565b600080516020610653833981519152546040516301ffc9a760e01b81526001600160e01b0319841660048201526001600160a01b038216906301ffc9a79060240160206040518083038186803b15801561023a57600080fd5b505afa92505050801561026a575060408051601f3d908101601f1916820190925261026791810190610589565b60015b6102775750600092915050565b9392505050565b61028661039f565b6001600160a01b0316336001600160a01b0316146102b65760405162461bcd60e51b81526004016100889061060a565b6102cf81604051806020016040528060008152506103b2565b50565b60006102dc61039f565b905090565b6102e961039f565b6001600160a01b0316336001600160a01b0316146103195760405162461bcd60e51b81526004016100889061060a565b6103598383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103b292505050565b505050565b61036661039f565b6001600160a01b0316336001600160a01b0316146103965760405162461bcd60e51b81526004016100889061060a565b6102cf81610475565b6000805160206106338339815191525490565b6000805160206106538339815191528054908390556040516001600160a01b0380851691908316907f5570d70a002632a7b0b3c9304cc89efb62d8da9eca0dbd7752c83b737906829690600090a3815115610359576000836001600160a01b03168360405161042191906105d1565b600060405180830381855af49150503d806000811461045c576040519150601f19603f3d011682016040523d82523d6000602084013e610461565b606091505b5050905080610183573d806000803e806000fd5b600061047f61039f565b90508160008051602061063383398151915255816001600160a01b0316816001600160a01b03167fdf435d422321da6b195902d70fc417c06a32f88379c20dd8f2a8da07088cec2960405160405180910390a35050565b80356001600160a01b03811681146104ed57600080fd5b919050565b600060208284031215610503578081fd5b610277826104d6565b600080600060408486031215610520578182fd5b610529846104d6565b925060208401356001600160401b0380821115610544578384fd5b818601915086601f830112610557578384fd5b813581811115610565578485fd5b876020828501011115610576578485fd5b6020830194508093505050509250925092565b60006020828403121561059a578081fd5b81518015158114610277578182fd5b6000602082840312156105ba578081fd5b81356001600160e01b031981168114610277578182fd5b60008251815b818110156105f157602081860181015185830152016105d7565b818111156105ff5782828501525b509190910192915050565b6020808252600e908201526d1393d517d055551213d49256915160921b60408201526060019056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220730effc08e7ae1c19f69ae08dd52de483b649ded49db9428e4ced9875431474364736f6c63430008040033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0a264697066735822122032c0226340af0379cd7d43429d1502fc96d02b3e0f888c97b7ed277717483dc364736f6c63430008040033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/arrakis/ArrakisVaultV1.json b/external/abi/arrakis/ArrakisVaultV1.json new file mode 100644 index 000000000..14cdb737b --- /dev/null +++ b/external/abi/arrakis/ArrakisVaultV1.json @@ -0,0 +1,1136 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ArrakisVaultV1", + "sourceName": "contracts/ArrakisVaultV1.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address payable", + "name": "_gelato", + "type": "address" + }, + { + "internalType": "address", + "name": "_arrakisTreasury", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "burnAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "liquidityBurned", + "type": "uint128" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "feesEarned0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feesEarned1", + "type": "uint256" + } + ], + "name": "FeesEarned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "liquidityMinted", + "type": "uint128" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newManager", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int24", + "name": "lowerTick_", + "type": "int24" + }, + { + "indexed": false, + "internalType": "int24", + "name": "upperTick_", + "type": "int24" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "liquidityBefore", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "liquidityAfter", + "type": "uint128" + } + ], + "name": "Rebalance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "managerFeeBPS", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "address", + "name": "managerTreasury", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "gelatoRebalanceBPS", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "gelatoSlippageBPS", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gelatoSlippageInterval", + "type": "uint32" + } + ], + "name": "UpdateManagerParams", + "type": "event" + }, + { + "inputs": [], + "name": "GELATO", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESTRICTED_MINT_ENABLED", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "arrakisBalance0", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arrakisBalance1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arrakisFeeBPS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arrakisTreasury", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "burnAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "liquidityBurned", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int24", + "name": "newLowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "newUpperTick", + "type": "int24" + }, + { + "internalType": "uint160", + "name": "swapThresholdPrice", + "type": "uint160" + }, + { + "internalType": "uint256", + "name": "swapAmountBPS", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "zeroForOne", + "type": "bool" + } + ], + "name": "executiveRebalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gelatoRebalanceBPS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gelatoSlippageBPS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gelatoSlippageInterval", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount0Max", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Max", + "type": "uint256" + } + ], + "name": "getMintAmounts", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPositionID", + "outputs": [ + { + "internalType": "bytes32", + "name": "positionID", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderlyingBalances", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0Current", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Current", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint160", + "name": "sqrtRatioX96", + "type": "uint160" + } + ], + "name": "getUnderlyingBalancesAtPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0Current", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Current", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "_pool", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_managerFeeBPS", + "type": "uint16" + }, + { + "internalType": "int24", + "name": "_lowerTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "_upperTick", + "type": "int24" + }, + { + "internalType": "address", + "name": "_manager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lowerTick", + "outputs": [ + { + "internalType": "int24", + "name": "", + "type": "int24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managerBalance0", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managerBalance1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managerFeeBPS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managerTreasury", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "liquidityMinted", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pool", + "outputs": [ + { + "internalType": "contract IUniswapV3Pool", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint160", + "name": "swapThresholdPrice", + "type": "uint160" + }, + { + "internalType": "uint256", + "name": "swapAmountBPS", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "zeroForOne", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "paymentToken", + "type": "address" + } + ], + "name": "rebalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "restrictedMintToggle", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "toggleRestrictMint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token0", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token1", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount0Owed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Owed", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "uniswapV3MintCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int16", + "name": "newManagerFeeBPS", + "type": "int16" + }, + { + "internalType": "address", + "name": "newManagerTreasury", + "type": "address" + }, + { + "internalType": "int16", + "name": "newRebalanceBPS", + "type": "int16" + }, + { + "internalType": "int16", + "name": "newSlippageBPS", + "type": "int16" + }, + { + "internalType": "int32", + "name": "newSlippageInterval", + "type": "int32" + } + ], + "name": "updateManagerParams", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upperTick", + "outputs": [ + { + "internalType": "int24", + "name": "", + "type": "int24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawArrakisBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawManagerBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60c06040523480156200001157600080fd5b5060405162005f1838038062005f18833981016040819052620000349162000053565b6001600160601b0319606092831b8116608052911b1660a052620000aa565b6000806040838503121562000066578182fd5b8251620000738162000091565b6020840151909250620000868162000091565b809150509250929050565b6001600160a01b0381168114620000a757600080fd5b50565b60805160601c60a05160601c615e1f620000f9600039600081816104e5015281816119a401526119e101526000818161061d0152818161138c01528181611602015261163c0152615e1f6000f3fe608060405234801561001057600080fd5b506004361061023b5760003560e01c8063065756db1461024057806306fdde031461025c578063095ea7b3146102715780630dfe1681146102945780631322d954146102b457806316f0115b146102ca57806318160ddd146102dd57806323b872dd146102e557806324b8fd1b146102f8578063313ce5671461030d578063395093511461031c57806342fb9d441461032f578063481c6a751461033857806354fd4d50146103405780635f59dce514610364578063672152bd1461036c57806370a0823114610391578063715018a6146103ba578063727dd228146103c25780637ecd6717146103e357806394bf804d146103eb57806395d89b41146104225780639894f21a1461042a5780639b1344ac14610458578063a457c2d71461046c578063a50b1fe71461047f578063a9059cbb146104a7578063b135c99f146104ba578063b670ed7d146104cd578063b9f24cb2146104e0578063bbfe704e14610507578063c540e48314610510578063c707504114610523578063cc95353e1461052b578063ccdf7a0214610545578063d21220a71461055a578063d34879971461056d578063d6e7ff3914610580578063d839fb3f14610595578063d8953ca71461059e578063dc9ad4c1146105a7578063dd40e322146105af578063dd62ed3e146105c4578063df28408a146105fd578063e25e15e314610605578063eff557a714610618578063f2fde38b1461063f578063fa461e3314610652578063fcd3533c14610665575b600080fd5b61024960995481565b6040519081526020015b60405180910390f35b610264610678565b6040516102539190615826565b61028461027f36600461518c565b61070a565b6040519015158152602001610253565b609e546102a7906001600160a01b031681565b6040516102539190615713565b6102bc610720565b6040516102539291906159ed565b609d546102a7906001600160a01b031681565b603554610249565b6102846102f336600461514c565b6107c9565b61030b610306366004615305565b610881565b005b60405160128152602001610253565b61028461032a36600461518c565b610cbb565b610249609a5481565b6102a7610cf2565b610264604051806040016040528060058152602001640312e302e360dc1b81525081565b61030b610d01565b60985461037c9063ffffffff1681565b60405163ffffffff9091168152602001610253565b61024961039f3660046150dc565b6001600160a01b031660009081526033602052604090205490565b61030b610d6f565b6097546103d690600160b81b900460020b81565b60405161025391906157ea565b61030b610dc3565b6103fe6103f93660046156b2565b610e2f565b6040805193845260208401929092526001600160801b031690820152606001610253565b610264611176565b61043d6104383660046156d6565b611185565b60408051938452602084019290925290820152606001610253565b6097546103d690600160a01b900460020b81565b61028461047a36600461518c565b6112d7565b60975461049490600160d01b900461ffff1681565b60405161ffff9091168152602001610253565b6102846104b536600461518c565b611372565b61030b6104c836600461564a565b61137f565b6102bc6104db3660046150dc565b61166a565b6102a77f000000000000000000000000000000000000000000000000000000000000000081565b610249609c5481565b61030b61051e366004615296565b611711565b61049460fa81565b6098546102a790600160301b90046001600160a01b031681565b60985461049490600160201b900461ffff1681565b609f546102a7906001600160a01b031681565b61030b61057b366004615381565b611910565b60975461049490600160f01b900461ffff1681565b610494612b6781565b610249609b5481565b61030b61197a565b60975461049490600160e01b900461ffff1681565b6102496105d2366004615114565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b610249611a06565b61030b6106133660046153d1565b611a15565b6102a77f000000000000000000000000000000000000000000000000000000000000000081565b61030b61064d3660046150dc565b611cb6565b61030b610660366004615381565b611d96565b6103fe6106733660046156b2565b611e05565b60606036805461068790615c40565b80601f01602080910402602001604051908101604052809291908181526020018280546106b390615c40565b80156107005780601f106106d557610100808354040283529160200191610700565b820191906000526020600020905b8154815290600101906020018083116106e357829003601f168201915b5050505050905090565b600061071733848461213e565b50600192915050565b600080600080609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561077457600080fd5b505afa158015610788573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ac91906155ba565b5050505050915091506107bf8282612263565b9350935050509091565b60006107d6848484612514565b6001600160a01b0384166000908152603460209081526040808320338452909152902054828110156108605760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b610874853361086f8685615bfd565b61213e565b60019150505b9392505050565b3361088a610cf2565b6001600160a01b0316146108b05760405162461bcd60e51b815260040161085790615954565b60008060006108be60355490565b1115610c4257609d546001600160a01b031663514ea4bf6108dd6126da565b6040518263ffffffff1660e01b81526004016108fb91815260200190565b60a06040518083038186803b15801561091357600080fd5b505afa158015610927573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094b9190615564565b5092945050506001600160801b0383161590506109d457609754600090819061098a90600160a01b8104600290810b91600160b81b9004900b86612740565b93509350505061099a8282612acd565b6109a48282612ba6565b6040519193509150600080516020615dca833981519152906109c990849084906159ed565b60405180910390a150505b60978054600288810b62ffffff908116600160b81b0262ffffff60b81b19928c900b909116600160a01b029190911665ffffffffffff60a01b1990921691909117179055609b54609954609e546040516370a0823160e01b815260009392916001600160a01b0316906370a0823190610a51903090600401615713565b60206040518083038186803b158015610a6957600080fd5b505afa158015610a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa1919061569a565b610aab9190615bfd565b610ab59190615bfd565b609c54609a54609f546040516370a0823160e01b81529394506000936001600160a01b03909116906370a0823190610af1903090600401615713565b60206040518083038186803b158015610b0957600080fd5b505afa158015610b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b41919061569a565b610b4b9190615bfd565b610b559190615bfd565b9050610b66898984848b8b8b612c41565b609d546001600160a01b031663514ea4bf610b7f6126da565b6040518263ffffffff1660e01b8152600401610b9d91815260200190565b60a06040518083038186803b158015610bb557600080fd5b505afa158015610bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bed9190615564565b509295505050506001600160801b038316610c3b5760405162461bcd60e51b815260206004820152600e60248201526d06e657720706f736974696f6e20360941b6044820152606401610857565b5050610c87565b60978054600288810b62ffffff908116600160b81b0262ffffff60b81b19928c900b909116600160a01b029190911665ffffffffffff60a01b19909216919091171790555b600080516020615d6a83398151915287878484604051610caa94939291906157f8565b60405180910390a150505050505050565b3360008181526034602090815260408083206001600160a01b0387168452909152812054909161071791859061086f908690615a96565b6097546001600160a01b031690565b33610d0a610cf2565b6001600160a01b031614610d305760405162461bcd60e51b815260040161085790615954565b609754600160e01b900461ffff16612b671415610d57576097805461ffff60e01b19169055565b6097805461ffff60e01b1916612b6760e01b1790555b565b33610d78610cf2565b6001600160a01b031614610d9e5760405162461bcd60e51b815260040161085790615954565b60988054600160201b600160d01b031916905560006099819055609a55610d6d612e00565b60998054609a8054600093849055929055908115610e0057609854609e54610e00916001600160a01b0391821691600160301b9091041684612e67565b8015610e2b57609854609f54610e2b916001600160a01b0391821691600160301b9091041683612e67565b5050565b600080600060026065541415610e575760405162461bcd60e51b8152600401610857906159b6565b600260655584610e795760405162461bcd60e51b815260040161085790615996565b609754600160e01b900461ffff16612b67141580610ea157506097546001600160a01b031633145b610eda5760405162461bcd60e51b815260206004820152600a6024820152691c995cdd1c9a58dd195960b21b6044820152606401610857565b6000610ee560355490565b90506000609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f3757600080fd5b505afa158015610f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6f91906155ba565b50505050505090506000821115610fb057600080610f8b610720565b91509150610f9a828a86612ecf565b9650610fa7818a86612ecf565b95505050610ffd565b610ff781610fcf609760149054906101000a900460020b60020b612f26565b609754610fe990600160b81b9004600290810b900b612f26565b610ff28b613338565b6133a1565b90955093505b841561101b57609e5461101b906001600160a01b031633308861343d565b831561103957609f54611039906001600160a01b031633308761343d565b61107981611058609760149054906101000a900460020b60020b612f26565b60975461107290600160b81b9004600290810b900b612f26565b8888613475565b609d54609754604051633c8a7d8d60e01b81529295506001600160a01b0390911691633c8a7d8d916110c9913091600160a01b8104600290810b92600160b81b909204900b908990600401615727565b6040805180830381600087803b1580156110e257600080fd5b505af11580156110f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111a919061535e565b50506111268688613537565b7f55801cfe493000b734571da1694b21e7f66b11e8ce9fdaa0524ecb59105e73e7868887878760405161115d959493929190615769565b60405180910390a1505060016065819055509250925092565b60606037805461068790615c40565b60008060008061119460355490565b905080156111b3576111a7818787613604565b919550935091506112cf565b609d5460408051633850c7bd60e01b815290516000926001600160a01b031691633850c7bd9160048083019260e0929190829003018186803b1580156111f857600080fd5b505afa15801561120c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123091906155ba565b5050505050509050600061127a82611259609760149054906101000a900460020b60020b612f26565b60975461127390600160b81b9004600290810b900b612f26565b8b8b613475565b9050806001600160801b031693506112c7826112a7609760149054906101000a900460020b60020b612f26565b6097546112c190600160b81b9004600290810b900b612f26565b846133a1565b909650945050505b509250925092565b3360009081526034602090815260408083206001600160a01b0386168452909152812054828110156113595760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610857565b611368338561086f8685615bfd565b5060019392505050565b6000610717338484612514565b8181336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113f35760405162461bcd60e51b815260206004820152601760248201527647656c61746f666965643a204f6e6c792067656c61746f60481b6044820152606401610857565b8515611403576114038786613713565b609d546000906001600160a01b031663514ea4bf61141f6126da565b6040518263ffffffff1660e01b815260040161143d91815260200190565b60a06040518083038186803b15801561145557600080fd5b505afa158015611469573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148d9190615564565b5050505090506114a18189898989896139c1565b609d546000906001600160a01b031663514ea4bf6114bd6126da565b6040518263ffffffff1660e01b81526004016114db91815260200190565b60a06040518083038186803b1580156114f357600080fd5b505afa158015611507573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152b9190615564565b505050509050816001600160801b0316816001600160801b03161161158c5760405162461bcd60e51b81526020600482015260176024820152766c6971756964697479206d75737420696e63726561736560481b6044820152606401610857565b609754604051600080516020615d6a833981519152916115c691600160a01b8204600290810b92600160b81b9004900b90869086906157f8565b60405180910390a150506001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561162d576116286001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683613f19565b611661565b6116616001600160a01b0382167f000000000000000000000000000000000000000000000000000000000000000084612e67565b50505050505050565b6000806000609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b1580156116bd57600080fd5b505afa1580156116d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f591906155ba565b50505050509150506117078482612263565b9250925050915091565b3361171a610cf2565b6001600160a01b0316146117405760405162461bcd60e51b815260040161085790615954565b6127108360010b13156117655760405162461bcd60e51b815260040161085790615937565b6127108260010b131561178a5760405162461bcd60e51b815260040161085790615937565b61179760fa612710615b36565b60010b8560010b13156117bc5760405162461bcd60e51b815260040161085790615859565b60008560010b126117e2576098805461ffff60201b1916600160201b61ffff8816021790555b60008360010b12611808576097805461ffff60d01b1916600160d01b61ffff8616021790555b60008260010b1261182f57609780546001600160f01b0316600160f01b61ffff8516021790555b60008160030b12611850576098805463ffffffff191663ffffffff83161790555b6001600160a01b038416156118845760988054600160301b600160d01b031916600160301b6001600160a01b038716021790555b6098546097546040805161ffff600160201b8504811682526001600160a01b03600160301b8604166020830152600160d01b8404811692820192909252600160f01b90920416606082015263ffffffff90911660808201527ff459b381c988c676562c20a01f42f488c5560ed2e3957b0f27f26573418b61939060a00160405180910390a15050505050565b609d546001600160a01b0316331461193a5760405162461bcd60e51b815260040161085790615877565b831561195757609e54611957906001600160a01b03163386612e67565b821561197457609f54611974906001600160a01b03163385612e67565b50505050565b609b8054609c80546000938490559290559081156119c957609e546119c9906001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000084612e67565b8015610e2b57609f54610e2b906001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000083612e67565b6000611a106126da565b905090565b600054610100900460ff1680611a2e575060005460ff16155b611a4a5760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015611a6c576000805461ffff19166101011790555b611a7960fa612710615bba565b61ffff168561ffff161115611aa05760405162461bcd60e51b815260040161085790615859565b609d80546001600160a01b0319166001600160a01b03881690811790915560408051630dfe168160e01b81529051630dfe168191600480820192602092909190829003018186803b158015611af457600080fd5b505afa158015611b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2c91906150f8565b609e80546001600160a01b0319166001600160a01b03928316179055609d546040805163d21220a760e01b81529051919092169163d21220a7916004808301926020929190829003018186803b158015611b8557600080fd5b505afa158015611b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbd91906150f8565b609f80546001600160a01b0319166001600160a01b03928316179055609780546098805461012c600160201b600160d01b0319909116600160201b61ffff8c1602600160301b600160d01b03191617948716600160301b81029590951763ffffffff1916179055601960d31b600160a01b600160f01b03909116909217607d60f21b1767ffff000000ffffff60a01b1916600160a01b600288810b62ffffff90811692909202929092179390931762ffffff60b81b1916600160b81b9187900b9390931602919091179055611c92888861402f565b611c9a6140ae565b8015611cac576000805461ff00191690555b5050505050505050565b33611cbf610cf2565b6001600160a01b031614611ce55760405162461bcd60e51b815260040161085790615954565b6001600160a01b038116611d4c5760405162461bcd60e51b815260206004820152602860248201527f4f776e61626c653a206e6577206d616e6167657220697320746865207a65726f604482015267206164647265737360c01b6064820152608401610857565b6097546040516001600160a01b03808416921690600080516020615d8a83398151915290600090a3609780546001600160a01b0319166001600160a01b0392909216919091179055565b609d546001600160a01b03163314611dc05760405162461bcd60e51b815260040161085790615877565b6000841315611de557609e54611de0906001600160a01b03163386612e67565b611974565b600083131561197457609f54611974906001600160a01b03163385612e67565b600080600060026065541415611e2d5760405162461bcd60e51b8152600401610857906159b6565b600260655584611e685760405162461bcd60e51b815260206004820152600660248201526506275726e20360d41b6044820152606401610857565b6000611e7360355490565b609d549091506000906001600160a01b031663514ea4bf611e926126da565b6040518263ffffffff1660e01b8152600401611eb091815260200190565b60a06040518083038186803b158015611ec857600080fd5b505afa158015611edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f009190615564565b505050509050611f103388614122565b6000611f2688836001600160801b03168561425f565b9050611f3181613338565b609754909450600090819081908190611f6090600160a01b8104600290810b91600160b81b9004900b8a612740565b9350935093509350611f728282612acd565b611f7c8282612ba6565b6040519193509150600080516020615dca83398151915290611fa190849084906159ed565b60405180910390a1609b54609954609e546040516370a0823160e01b815261205c93929188916001600160a01b03909116906370a0823190611fe7903090600401615713565b60206040518083038186803b158015611fff57600080fd5b505afa158015612013573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612037919061569a565b6120419190615bfd565b61204b9190615bfd565b6120559190615bfd565b8d8961425f565b6120669085615a96565b609c54609a54609f546040516370a0823160e01b8152939d506120a39387916001600160a01b0316906370a0823190611fe7903090600401615713565b6120ad9084615a96565b985089156120cc57609e546120cc906001600160a01b03168c8c612e67565b88156120e957609f546120e9906001600160a01b03168c8b612e67565b7f7239dff1718b550db7f36cbf69c665cfeb56d0e96b4fb76a5cba712961b655098b8d8c8c8c604051612120959493929190615769565b60405180910390a15050505050505060016065819055509250925092565b6001600160a01b0383166121a05760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610857565b6001600160a01b0382166122015760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610857565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b609d546000908190819081908190819081906001600160a01b031663514ea4bf61228b6126da565b6040518263ffffffff1660e01b81526004016122a991815260200190565b60a06040518083038186803b1580156122c157600080fd5b505afa1580156122d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f99190615564565b9450945094509450945061234289612322609760149054906101000a900460020b60020b612f26565b60975461233c90600160b81b9004600290810b900b612f26565b886133a1565b909750955060006001600160801b0383166123606001878c8a61430e565b61236a9190615a96565b90506000826001600160801b03166123856000878d8b61430e565b61238f9190615a96565b905061239b8282612ba6565b609b54609954609e546040516370a0823160e01b8152949650929450909290916001600160a01b0316906370a08231906123d9903090600401615713565b60206040518083038186803b1580156123f157600080fd5b505afa158015612405573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612429919061569a565b6124339085615a96565b61243d9190615bfd565b6124479190615bfd565b612451908a615a96565b609c54609a54609f546040516370a0823160e01b8152939c50919290916001600160a01b0316906370a082319061248c903090600401615713565b60206040518083038186803b1580156124a457600080fd5b505afa1580156124b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124dc919061569a565b6124e69084615a96565b6124f09190615bfd565b6124fa9190615bfd565b6125049089615a96565b9750505050505050509250929050565b6001600160a01b0383166125785760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610857565b6001600160a01b0382166125da5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610857565b6001600160a01b038316600090815260336020526040902054818110156126525760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610857565b61265c8282615bfd565b6001600160a01b038086166000908152603360205260408082209390935590851681529081208054849290612692908490615a96565b92505081905550826001600160a01b0316846001600160a01b0316600080516020615daa833981519152846040516126cc91815260200190565b60405180910390a350505050565b6097546040516001600160601b03193060601b166020820152600160a01b8204600290810b810b60e890811b6034840152600160b81b909304810b900b90911b6037820152600090603a0160405160208183030381529060405280519060200120905090565b609e546040516370a0823160e01b815260009182918291829182916001600160a01b0316906370a0823190612779903090600401615713565b60206040518083038186803b15801561279157600080fd5b505afa1580156127a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c9919061569a565b609f546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906127ff903090600401615713565b60206040518083038186803b15801561281757600080fd5b505afa15801561282b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284f919061569a565b609d5460405163a34123a760e01b815260028c810b60048301528b900b60248201526001600160801b038a1660448201529192506001600160a01b03169063a34123a7906064016040805180830381600087803b1580156128af57600080fd5b505af11580156128c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e7919061535e565b609d546040516309e3d67b60e31b815230600482015260028d810b60248301528c900b60448201526001600160801b036064820181905260848201529298509096506001600160a01b031690634f1eb3d89060a4016040805180830381600087803b15801561295557600080fd5b505af1158015612969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298d9190615532565b5050609e546040516370a0823160e01b8152879184916001600160a01b03909116906370a08231906129c3903090600401615713565b60206040518083038186803b1580156129db57600080fd5b505afa1580156129ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a13919061569a565b612a1d9190615bfd565b612a279190615bfd565b609f546040516370a0823160e01b8152919550869183916001600160a01b0316906370a0823190612a5c903090600401615713565b60206040518083038186803b158015612a7457600080fd5b505afa158015612a88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aac919061569a565b612ab69190615bfd565b612ac09190615bfd565b9250505093509350935093565b612710612adb60fa84615b17565b612ae59190615ad4565b609b6000828254612af69190615a96565b909155506127109050612b0a60fa83615b17565b612b149190615ad4565b609c6000828254612b259190615a96565b909155505060985461271090612b4690600160201b900461ffff1684615b17565b612b509190615ad4565b60996000828254612b619190615a96565b909155505060985461271090612b8290600160201b900461ffff1683615b17565b612b8c9190615ad4565b609a6000828254612b9d9190615a96565b90915550505050565b6000806000612710609860049054906101000a900461ffff1660fa612bcb9190615a4e565b612bd99061ffff1687615b17565b612be39190615ad4565b60985490915060009061271090612c0690600160201b900461ffff1660fa615a4e565b612c149061ffff1687615b17565b612c1e9190615ad4565b9050612c2a8287615bfd565b9350612c368186615bfd565b925050509250929050565b609d5460408051633850c7bd60e01b815290516000926001600160a01b031691633850c7bd9160048083019260e0929190829003018186803b158015612c8657600080fd5b505afa158015612c9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cbe91906155ba565b50505050505090506000612ceb82612cd88b60020b612f26565b612ce48b60020b612f26565b8a8a613475565b90506001600160801b03811615612da857609d54604051633c8a7d8d60e01b815260009182916001600160a01b0390911690633c8a7d8d90612d379030908f908f908990600401615727565b6040805180830381600087803b158015612d5057600080fd5b505af1158015612d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d88919061535e565b9092509050612d97828a615bfd565b9850612da38189615bfd565b975050505b6000612dd76127108686612dbc5789612dbe565b8a5b612dc89190615b17565b612dd29190615ad4565b61471a565b90506000811315612df457612df18a8a8a8a858b8a614780565b50505b50505050505050505050565b33612e09610cf2565b6001600160a01b031614612e2f5760405162461bcd60e51b815260040161085790615954565b6097546040516000916001600160a01b031690600080516020615d8a833981519152908390a3609780546001600160a01b0319169055565b6040516001600160a01b038316602482015260448101829052612eca90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526149c9565b505050565b6000612edc84848461425f565b905060008280612efc57634e487b7160e01b600052601260045260246000fd5b848609111561087a576000198110612f1357600080fd5b80612f1d81615c7b565b95945050505050565b60008060008360020b12612f3d578260020b612f4a565b8260020b612f4a90615ccb565b9050612f59620d89e719615caa565b60020b811115612f8f5760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610857565b600060018216612fa357600160801b612fb5565b6ffffcb933bd6fad37aa2d162d1a5940015b6001600160881b031690506002821615612fea576080612fe5826ffff97272373d413259a46990580e213a615b17565b901c90505b600482161561301457608061300f826ffff2e50f5f656932ef12357cf3c7fdcc615b17565b901c90505b600882161561303e576080613039826fffe5caca7e10e4e61c3624eaa0941cd0615b17565b901c90505b6010821615613068576080613063826fffcb9843d60f6159c9db58835c926644615b17565b901c90505b602082161561309257608061308d826fff973b41fa98c081472e6896dfb254c0615b17565b901c90505b60408216156130bc5760806130b7826fff2ea16466c96a3843ec78b326b52861615b17565b901c90505b60808216156130e65760806130e1826ffe5dee046a99a2a811c461f1969c3053615b17565b901c90505b61010082161561311157608061310c826ffcbe86c7900a88aedcffc83b479aa3a4615b17565b901c90505b61020082161561313c576080613137826ff987a7253ac413176f2b074cf7815e54615b17565b901c90505b610400821615613167576080613162826ff3392b0822b70005940c7a398e4b70f3615b17565b901c90505b61080082161561319257608061318d826fe7159475a2c29b7443b29c7fa6e889d9615b17565b901c90505b6110008216156131bd5760806131b8826fd097f3bdfd2022b8845ad8f792aa5825615b17565b901c90505b6120008216156131e85760806131e3826fa9f746462d870fdf8a65dc1f90e061e5615b17565b901c90505b61400082161561321357608061320e826f70d869a156d2a1b890bb3df62baf32f7615b17565b901c90505b61800082161561323e576080613239826f31be135f97d08fd981231505542fcfa6615b17565b901c90505b6201000082161561326a576080613265826f09aa508b5b7a84e1c677de54f3e99bc9615b17565b901c90505b62020000821615613295576080613290826e5d6af8dedb81196699c329225ee604615b17565b901c90505b620400008216156132bf5760806132ba826d2216e584f5fa1ea926041bedfe98615b17565b901c90505b620800008216156132e75760806132e2826b048a170391f7dc42444e8fa2615b17565b901c90505b60008460020b1315613302576132ff81600019615ad4565b90505b613310600160201b82615c96565b1561331c57600161331f565b60005b6133309060ff16602083901c615a96565b949350505050565b6000600160801b821061339d5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401610857565b5090565b600080836001600160a01b0316856001600160a01b031611156133c2579293925b846001600160a01b0316866001600160a01b0316116133ed576133e6858585614a9b565b9150613434565b836001600160a01b0316866001600160a01b0316101561342657613412868585614a9b565b915061341f858785614b05565b9050613434565b613431858585614b05565b90505b94509492505050565b6040516001600160a01b03808516602483015283166044820152606481018290526119749085906323b872dd60e01b90608401612e93565b6000836001600160a01b0316856001600160a01b03161115613495579293925b846001600160a01b0316866001600160a01b0316116134c0576134b9858585614b4f565b9050612f1d565b836001600160a01b0316866001600160a01b031610156135225760006134e7878686614b4f565b905060006134f6878986614bb9565b9050806001600160801b0316826001600160801b0316106135175780613519565b815b92505050612f1d565b61352d858584614bb9565b9695505050505050565b6001600160a01b03821661358d5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610857565b806035600082825461359f9190615a96565b90915550506001600160a01b038216600090815260336020526040812080548392906135cc908490615a96565b90915550506040518181526001600160a01b03831690600090600080516020615daa8339815191529060200160405180910390a35050565b6000806000806000613614610720565b915091508160001480156136285750600081115b1561363f5761363886898361425f565b92506136ee565b8015801561364d5750600082115b1561365d5761363887898461425f565b81158015613669575080155b156136905760405162461bcd60e51b81526020600482015260006024820152604401610857565b600061369d888a8561425f565b905060006136ac888b8561425f565b90506000821180156136be5750600081115b6136da5760405162461bcd60e51b815260040161085790615996565b8082106136e757806136e9565b815b945050505b6136f983838a612ecf565b945061370683828a612ecf565b9350505093509350939050565b6040805160028082526060820183526000926020830190803683375050609854825192935063ffffffff169183915060009061375f57634e487b7160e01b600052603260045260246000fd5b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061379c57634e487b7160e01b600052603260045260246000fd5b63ffffffff90921660209283029190910190910152609d5460405163883bdbfd60e01b81526000916001600160a01b03169063883bdbfd906137e29085906004016157a0565b60006040518083038186803b1580156137fa57600080fd5b505afa15801561380e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261383691908101906151b7565b50905080516002146138765760405162461bcd60e51b815260206004820152600960248201526830b93930bc903632b760b91b6044820152606401610857565b6098548151600091829163ffffffff90911660060b90849083906138aa57634e487b7160e01b600052603260045260246000fd5b6020026020010151846001815181106138d357634e487b7160e01b600052603260045260246000fd5b60200260200101510360060b816138fa57634e487b7160e01b600052601260045260246000fd5b0590506139098160020b612f26565b609754909250600091506127109061392c90600160f01b900461ffff1684615ae8565b6139369190615aae565b9050841561397e576139488183615bdd565b6001600160a01b0316866001600160a01b031610156139795760405162461bcd60e51b815260040161085790615910565b6139b9565b6139888183615a74565b6001600160a01b0316866001600160a01b031611156139b95760405162461bcd60e51b815260040161085790615910565b505050505050565b609b54609954609e546040516370a0823160e01b815260009392916001600160a01b0316906370a08231906139fa903090600401615713565b60206040518083038186803b158015613a1257600080fd5b505afa158015613a26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4a919061569a565b613a549190615bfd565b613a5e9190615bfd565b609c54609a54609f546040516370a0823160e01b81529394506000936001600160a01b03909116906370a0823190613a9a903090600401615713565b60206040518083038186803b158015613ab257600080fd5b505afa158015613ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aea919061569a565b613af49190615bfd565b613afe9190615bfd565b6097549091506000908190613b2990600160a01b8104600290810b91600160b81b9004900b8c612740565b935093505050613b398282612acd565b613b438282612ba6565b6040519193509150600080516020615dca83398151915290613b6890849084906159ed565b60405180910390a1613b7a8483615a96565b9150613b868382615a96565b609e549091506001600160a01b0386811691161415613d3157609754869061271090613bbd90600160d01b900461ffff1685615b17565b613bc79190615ad4565b1015613be55760405162461bcd60e51b8152600401610857906158ee565b609b54609954609e546040516370a0823160e01b8152899392916001600160a01b0316906370a0823190613c1d903090600401615713565b60206040518083038186803b158015613c3557600080fd5b505afa158015613c49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c6d919061569a565b613c779190615bfd565b613c819190615bfd565b613c8b9190615bfd565b609c54609a54609f546040516370a0823160e01b8152939750919290916001600160a01b0316906370a0823190613cc6903090600401615713565b60206040518083038186803b158015613cde57600080fd5b505afa158015613cf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d16919061569a565b613d209190615bfd565b613d2a9190615bfd565b9250613ef2565b609f546001600160a01b0386811691161415613ebc57609754869061271090613d6590600160d01b900461ffff1684615b17565b613d6f9190615ad4565b1015613d8d5760405162461bcd60e51b8152600401610857906158ee565b609b54609954609e546040516370a0823160e01b81526001600160a01b03909116906370a0823190613dc3903090600401615713565b60206040518083038186803b158015613ddb57600080fd5b505afa158015613def573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e13919061569a565b613e1d9190615bfd565b613e279190615bfd565b609c54609a54609f546040516370a0823160e01b815293975089936001600160a01b03909116906370a0823190613e62903090600401615713565b60206040518083038186803b158015613e7a57600080fd5b505afa158015613e8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613eb2919061569a565b613d169190615bfd565b60405162461bcd60e51b815260206004820152600b60248201526a3bb937b733903a37b5b2b760a91b6044820152606401610857565b609754612df490600160a01b8104600290810b91600160b81b9004900b86868d8d8d612c41565b80471015613f695760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610857565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613fb6576040519150601f19603f3d011682016040523d82523d6000602084013e613fbb565b606091505b5050905080612eca5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c20726044820152791958da5c1a595b9d081b585e481a185d99481c995d995c9d195960321b6064820152608401610857565b600054610100900460ff1680614048575060005460ff16155b6140645760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614086576000805461ffff19166101011790555b61408e614bef565b6140988383614c59565b8015612eca576000805461ff0019169055505050565b600054610100900460ff16806140c7575060005460ff16155b6140e35760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614105576000805461ffff19166101011790555b61410d614cee565b801561411f576000805461ff00191690555b50565b6001600160a01b0382166141825760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610857565b6001600160a01b038216600090815260336020526040902054818110156141f65760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610857565b6142008282615bfd565b6001600160a01b0384166000908152603360205260408120919091556035805484929061422e908490615bfd565b90915550506040518281526000906001600160a01b03851690600080516020615daa83398151915290602001612256565b600080806000198587098587029250828110838203039150508060001415614299576000841161428e57600080fd5b50829004905061087a565b8084116142a557600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b60008060008087156144db57609d60009054906101000a90046001600160a01b03166001600160a01b031663f30583996040518163ffffffff1660e01b815260040160206040518083038186803b15801561436857600080fd5b505afa15801561437c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143a0919061569a565b609d5460975460405163f30dba9360e01b81529293506001600160a01b039091169163f30dba93916143e091600160a01b90910460020b906004016157ea565b6101006040518083038186803b1580156143f957600080fd5b505afa15801561440d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144319190615490565b5050609d5460975460405163f30dba9360e01b8152959a506001600160a01b03909116965063f30dba93955061447a94600160b81b90910460020b935060040191506157ea9050565b6101006040518083038186803b15801561449357600080fd5b505afa1580156144a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144cb9190615490565b5093975061469695505050505050565b609d60009054906101000a90046001600160a01b03166001600160a01b031663461413196040518163ffffffff1660e01b815260040160206040518083038186803b15801561452957600080fd5b505afa15801561453d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614561919061569a565b609d5460975460405163f30dba9360e01b81529293506001600160a01b039091169163f30dba93916145a191600160a01b90910460020b906004016157ea565b6101006040518083038186803b1580156145ba57600080fd5b505afa1580156145ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145f29190615490565b5050609d5460975460405163f30dba9360e01b8152949a506001600160a01b03909116965063f30dba93955061463a9450600160b81b900460020b9260040191506157ea9050565b6101006040518083038186803b15801561465357600080fd5b505afa158015614667573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061468b9190615490565b509297505050505050505b6000609760149054906101000a900460020b60020b8760020b126146bb5750826146c0565b508281035b6000609760179054906101000a900460020b60020b8860020b12156146e65750826146eb565b508282035b81830381900361470b6001600160801b0389168b8303600160801b61425f565b9b9a5050505050505050505050565b6000600160ff1b821061339d5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401610857565b609d54604051630251596160e31b81523060048201528215156024820152604481018590526001600160a01b03848116606483015260a06084830152600060a4830181905292839283928392169063128acb089060c4016040805180830381600087803b1580156147f057600080fd5b505af1158015614804573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614828919061535e565b91509150816148368a61471a565b6148409190615b7b565b93508061484c8961471a565b6148569190615b7b565b92506000609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b1580156148a857600080fd5b505afa1580156148bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148e091906155ba565b5050505050509050600061490d826148fa8f60020b612f26565b6149068f60020b612f26565b8989613475565b90506001600160801b038116156149b957609d60009054906101000a90046001600160a01b03166001600160a01b0316633c8a7d8d308f8f856040518563ffffffff1660e01b81526004016149659493929190615727565b6040805180830381600087803b15801561497e57600080fd5b505af1158015614992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149b6919061535e565b50505b5050505097509795505050505050565b6000614a1e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614d5e9092919063ffffffff16565b805190915015612eca5780806020019051810190614a3c919061527a565b612eca5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610857565b6000826001600160a01b0316846001600160a01b03161115614abb579192915b6001600160a01b038416614afb600160601b600160e01b03606085901b16614ae38787615bdd565b6001600160a01b0316866001600160a01b031661425f565b6133309190615ad4565b6000826001600160a01b0316846001600160a01b03161115614b25579192915b6133306001600160801b038316614b3c8686615bdd565b6001600160a01b0316600160601b61425f565b6000826001600160a01b0316846001600160a01b03161115614b6f579192915b6000614b92856001600160a01b0316856001600160a01b0316600160601b61425f565b9050612f1d614bb48483614ba68989615bdd565b6001600160a01b031661425f565b614d6d565b6000826001600160a01b0316846001600160a01b03161115614bd9579192915b613330614bb483600160601b614ba68888615bdd565b600054610100900460ff1680614c08575060005460ff16155b614c245760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff1615801561410d576000805461ffff1916610101179055801561411f576000805461ff001916905550565b600054610100900460ff1680614c72575060005460ff16155b614c8e5760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614cb0576000805461ffff19166101011790555b8251614cc3906036906020860190614ee9565b508151614cd7906037906020850190614ee9565b508015612eca576000805461ff0019169055505050565b600054610100900460ff1680614d07575060005460ff16155b614d235760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614d45576000805461ffff19166101011790555b6001606555801561411f576000805461ff001916905550565b60606133308484600085614d88565b806001600160801b0381168114614d8357600080fd5b919050565b606082471015614de95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610857565b843b614e375760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610857565b600080866001600160a01b03168587604051614e5391906156f7565b60006040518083038185875af1925050503d8060008114614e90576040519150601f19603f3d011682016040523d82523d6000602084013e614e95565b606091505b5091509150614ea5828286614eb0565b979650505050505050565b60608315614ebf57508161087a565b825115614ecf5782518084602001fd5b8160405162461bcd60e51b81526004016108579190615826565b828054614ef590615c40565b90600052602060002090601f016020900481019282614f175760008555614f5d565b82601f10614f3057805160ff1916838001178555614f5d565b82800160010185558215614f5d579182015b82811115614f5d578251825591602001919060010190614f42565b5061339d9291505b8082111561339d5760008155600101614f65565b600082601f830112614f89578081fd5b81516020614f9e614f9983615a2b565b6159fb565b80838252828201915082860187848660051b8901011115614fbd578586fd5b855b85811015614fe4578151614fd281615d27565b84529284019290840190600101614fbf565b5090979650505050505050565b60008083601f840112615002578182fd5b5081356001600160401b03811115615018578182fd5b60208301915083602082850101111561503057600080fd5b9250929050565b8035600181900b8114614d8357600080fd5b8051600681900b8114614d8357600080fd5b600082601f83011261506b578081fd5b81356001600160401b0381111561508457615084615d11565b615097601f8201601f19166020016159fb565b8181528460208386010111156150ab578283fd5b816020850160208301379081016020019190915292915050565b80516001600160801b0381168114614d8357600080fd5b6000602082840312156150ed578081fd5b813561087a81615d27565b600060208284031215615109578081fd5b815161087a81615d27565b60008060408385031215615126578081fd5b823561513181615d27565b9150602083013561514181615d27565b809150509250929050565b600080600060608486031215615160578081fd5b833561516b81615d27565b9250602084013561517b81615d27565b929592945050506040919091013590565b6000806040838503121561519e578182fd5b82356151a981615d27565b946020939093013593505050565b600080604083850312156151c9578182fd5b82516001600160401b03808211156151df578384fd5b818501915085601f8301126151f2578384fd5b81516020615202614f9983615a2b565b8083825282820191508286018a848660051b8901011115615221578889fd5b8896505b8487101561524a5761523681615049565b835260019690960195918301918301615225565b5091880151919650909350505080821115615263578283fd5b5061527085828601614f79565b9150509250929050565b60006020828403121561528b578081fd5b815161087a81615d3c565b600080600080600060a086880312156152ad578283fd5b6152b686615037565b945060208601356152c681615d27565b93506152d460408701615037565b92506152e260608701615037565b915060808601358060030b81146152f7578182fd5b809150509295509295909350565b600080600080600060a0868803121561531c578283fd5b853561532781615d4a565b9450602086013561533781615d4a565b9350604086013561534781615d27565b92506060860135915060808601356152f781615d3c565b60008060408385031215615370578182fd5b505080516020909101519092909150565b60008060008060608587031215615396578182fd5b843593506020850135925060408501356001600160401b038111156153b9578283fd5b6153c587828801614ff1565b95989497509550505050565b600080600080600080600060e0888a0312156153eb578485fd5b87356001600160401b0380821115615401578687fd5b61540d8b838c0161505b565b985060208a0135915080821115615422578687fd5b5061542f8a828b0161505b565b965050604088013561544081615d27565b9450606088013561545081615d59565b9350608088013561546081615d4a565b925060a088013561547081615d4a565b915060c088013561548081615d27565b8091505092959891949750929550565b600080600080600080600080610100898b0312156154ac578182fd5b6154b5896150c5565b9750602089015180600f0b81146154ca578283fd5b60408a015160608b0151919850965094506154e760808a01615049565b935060a08901516154f781615d27565b60c08a015190935063ffffffff81168114615510578283fd5b60e08a015190925061552181615d3c565b809150509295985092959890939650565b60008060408385031215615544578182fd5b61554d836150c5565b915061555b602084016150c5565b90509250929050565b600080600080600060a0868803121561557b578283fd5b615584866150c5565b945060208601519350604086015192506155a0606087016150c5565b91506155ae608087016150c5565b90509295509295909350565b600080600080600080600060e0888a0312156155d4578081fd5b87516155df81615d27565b60208901519097506155f081615d4a565b604089015190965061560181615d59565b606089015190955061561281615d59565b608089015190945061562381615d59565b60a089015190935060ff81168114615639578182fd5b60c089015190925061548081615d3c565b600080600080600060a08688031215615661578283fd5b853561566c81615d27565b945060208601359350604086013561568381615d3c565b92506060860135915060808601356152f781615d27565b6000602082840312156156ab578081fd5b5051919050565b600080604083850312156156c4578182fd5b82359150602083013561514181615d27565b600080604083850312156156e8578182fd5b50508035926020909101359150565b60008251615709818460208701615c14565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03949094168452600292830b6020850152910b60408301526001600160801b0316606082015260a06080820181905260009082015260c00190565b6001600160a01b039590951685526020850193909352604084019190915260608301526001600160801b0316608082015260a00190565b6020808252825182820181905260009190848201906040850190845b818110156157de57835163ffffffff16835292840192918401916001016157bc565b50909695505050505050565b60029190910b815260200190565b600294850b81529290930b60208301526001600160801b039081166040830152909116606082015260800190565b6020815260008251806020840152615845816040850160208701615c14565b601f01601f19169190910160400192915050565b6020808252600490820152636d42505360e01b604082015260600190565b6020808252600f908201526e31b0b6363130b1b59031b0b63632b960891b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b602080825260089082015267686967682066656560c01b604082015260600190565b6020808252600d908201526c6869676820736c69707061676560981b604082015260600190565b60208082526003908201526242505360e81b604082015260600190565b60208082526022908201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206d616e616760408201526132b960f11b606082015260800190565b60208082526006908201526506d696e7420360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b918252602082015260400190565b604051601f8201601f191681016001600160401b0381118282101715615a2357615a23615d11565b604052919050565b60006001600160401b03821115615a4457615a44615d11565b5060051b60200190565b600061ffff808316818516808303821115615a6b57615a6b615ce5565b01949350505050565b60006001600160a01b03828116848216808303821115615a6b57615a6b615ce5565b60008219821115615aa957615aa9615ce5565b500190565b60006001600160a01b0383811680615ac857615ac8615cfb565b92169190910492915050565b600082615ae357615ae3615cfb565b500490565b60006001600160a01b0382811684821681151582840482111615615b0e57615b0e615ce5565b02949350505050565b6000816000190483118215151615615b3157615b31615ce5565b500290565b60008160010b8360010b82811281617fff1901831281151615615b5b57615b5b615ce5565b81617fff018313811615615b7157615b71615ce5565b5090039392505050565b60008083128015600160ff1b850184121615615b9957615b99615ce5565b6001600160ff1b0384018313811615615bb457615bb4615ce5565b50500390565b600061ffff83811690831681811015615bd557615bd5615ce5565b039392505050565b60006001600160a01b0383811690831681811015615bd557615bd5615ce5565b600082821015615c0f57615c0f615ce5565b500390565b60005b83811015615c2f578181015183820152602001615c17565b838111156119745750506000910152565b600181811c90821680615c5457607f821691505b60208210811415615c7557634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615c8f57615c8f615ce5565b5060010190565b600082615ca557615ca5615cfb565b500690565b60008160020b627fffff19811415615cc457615cc4615ce5565b9003919050565b6000600160ff1b821415615ce157615ce1615ce5565b0390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461411f57600080fd5b801515811461411f57600080fd5b8060020b811461411f57600080fd5b61ffff8116811461411f57600080fdfec749f9ae947d4734cf1569606a8a347391ae94a063478aa853aeff48ac5f99e88be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc28ad1de9c0c32e5394ba60323e44d8d9536312236a47231772e448a3e49de42a26469706673582212207b33fb5362c9dc6a985db59388b6f1c39cf259872c1c74ed13a9b873a23d924364736f6c63430008040033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061023b5760003560e01c8063065756db1461024057806306fdde031461025c578063095ea7b3146102715780630dfe1681146102945780631322d954146102b457806316f0115b146102ca57806318160ddd146102dd57806323b872dd146102e557806324b8fd1b146102f8578063313ce5671461030d578063395093511461031c57806342fb9d441461032f578063481c6a751461033857806354fd4d50146103405780635f59dce514610364578063672152bd1461036c57806370a0823114610391578063715018a6146103ba578063727dd228146103c25780637ecd6717146103e357806394bf804d146103eb57806395d89b41146104225780639894f21a1461042a5780639b1344ac14610458578063a457c2d71461046c578063a50b1fe71461047f578063a9059cbb146104a7578063b135c99f146104ba578063b670ed7d146104cd578063b9f24cb2146104e0578063bbfe704e14610507578063c540e48314610510578063c707504114610523578063cc95353e1461052b578063ccdf7a0214610545578063d21220a71461055a578063d34879971461056d578063d6e7ff3914610580578063d839fb3f14610595578063d8953ca71461059e578063dc9ad4c1146105a7578063dd40e322146105af578063dd62ed3e146105c4578063df28408a146105fd578063e25e15e314610605578063eff557a714610618578063f2fde38b1461063f578063fa461e3314610652578063fcd3533c14610665575b600080fd5b61024960995481565b6040519081526020015b60405180910390f35b610264610678565b6040516102539190615826565b61028461027f36600461518c565b61070a565b6040519015158152602001610253565b609e546102a7906001600160a01b031681565b6040516102539190615713565b6102bc610720565b6040516102539291906159ed565b609d546102a7906001600160a01b031681565b603554610249565b6102846102f336600461514c565b6107c9565b61030b610306366004615305565b610881565b005b60405160128152602001610253565b61028461032a36600461518c565b610cbb565b610249609a5481565b6102a7610cf2565b610264604051806040016040528060058152602001640312e302e360dc1b81525081565b61030b610d01565b60985461037c9063ffffffff1681565b60405163ffffffff9091168152602001610253565b61024961039f3660046150dc565b6001600160a01b031660009081526033602052604090205490565b61030b610d6f565b6097546103d690600160b81b900460020b81565b60405161025391906157ea565b61030b610dc3565b6103fe6103f93660046156b2565b610e2f565b6040805193845260208401929092526001600160801b031690820152606001610253565b610264611176565b61043d6104383660046156d6565b611185565b60408051938452602084019290925290820152606001610253565b6097546103d690600160a01b900460020b81565b61028461047a36600461518c565b6112d7565b60975461049490600160d01b900461ffff1681565b60405161ffff9091168152602001610253565b6102846104b536600461518c565b611372565b61030b6104c836600461564a565b61137f565b6102bc6104db3660046150dc565b61166a565b6102a77f000000000000000000000000000000000000000000000000000000000000000081565b610249609c5481565b61030b61051e366004615296565b611711565b61049460fa81565b6098546102a790600160301b90046001600160a01b031681565b60985461049490600160201b900461ffff1681565b609f546102a7906001600160a01b031681565b61030b61057b366004615381565b611910565b60975461049490600160f01b900461ffff1681565b610494612b6781565b610249609b5481565b61030b61197a565b60975461049490600160e01b900461ffff1681565b6102496105d2366004615114565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b610249611a06565b61030b6106133660046153d1565b611a15565b6102a77f000000000000000000000000000000000000000000000000000000000000000081565b61030b61064d3660046150dc565b611cb6565b61030b610660366004615381565b611d96565b6103fe6106733660046156b2565b611e05565b60606036805461068790615c40565b80601f01602080910402602001604051908101604052809291908181526020018280546106b390615c40565b80156107005780601f106106d557610100808354040283529160200191610700565b820191906000526020600020905b8154815290600101906020018083116106e357829003601f168201915b5050505050905090565b600061071733848461213e565b50600192915050565b600080600080609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561077457600080fd5b505afa158015610788573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ac91906155ba565b5050505050915091506107bf8282612263565b9350935050509091565b60006107d6848484612514565b6001600160a01b0384166000908152603460209081526040808320338452909152902054828110156108605760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b610874853361086f8685615bfd565b61213e565b60019150505b9392505050565b3361088a610cf2565b6001600160a01b0316146108b05760405162461bcd60e51b815260040161085790615954565b60008060006108be60355490565b1115610c4257609d546001600160a01b031663514ea4bf6108dd6126da565b6040518263ffffffff1660e01b81526004016108fb91815260200190565b60a06040518083038186803b15801561091357600080fd5b505afa158015610927573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094b9190615564565b5092945050506001600160801b0383161590506109d457609754600090819061098a90600160a01b8104600290810b91600160b81b9004900b86612740565b93509350505061099a8282612acd565b6109a48282612ba6565b6040519193509150600080516020615dca833981519152906109c990849084906159ed565b60405180910390a150505b60978054600288810b62ffffff908116600160b81b0262ffffff60b81b19928c900b909116600160a01b029190911665ffffffffffff60a01b1990921691909117179055609b54609954609e546040516370a0823160e01b815260009392916001600160a01b0316906370a0823190610a51903090600401615713565b60206040518083038186803b158015610a6957600080fd5b505afa158015610a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa1919061569a565b610aab9190615bfd565b610ab59190615bfd565b609c54609a54609f546040516370a0823160e01b81529394506000936001600160a01b03909116906370a0823190610af1903090600401615713565b60206040518083038186803b158015610b0957600080fd5b505afa158015610b1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b41919061569a565b610b4b9190615bfd565b610b559190615bfd565b9050610b66898984848b8b8b612c41565b609d546001600160a01b031663514ea4bf610b7f6126da565b6040518263ffffffff1660e01b8152600401610b9d91815260200190565b60a06040518083038186803b158015610bb557600080fd5b505afa158015610bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bed9190615564565b509295505050506001600160801b038316610c3b5760405162461bcd60e51b815260206004820152600e60248201526d06e657720706f736974696f6e20360941b6044820152606401610857565b5050610c87565b60978054600288810b62ffffff908116600160b81b0262ffffff60b81b19928c900b909116600160a01b029190911665ffffffffffff60a01b19909216919091171790555b600080516020615d6a83398151915287878484604051610caa94939291906157f8565b60405180910390a150505050505050565b3360008181526034602090815260408083206001600160a01b0387168452909152812054909161071791859061086f908690615a96565b6097546001600160a01b031690565b33610d0a610cf2565b6001600160a01b031614610d305760405162461bcd60e51b815260040161085790615954565b609754600160e01b900461ffff16612b671415610d57576097805461ffff60e01b19169055565b6097805461ffff60e01b1916612b6760e01b1790555b565b33610d78610cf2565b6001600160a01b031614610d9e5760405162461bcd60e51b815260040161085790615954565b60988054600160201b600160d01b031916905560006099819055609a55610d6d612e00565b60998054609a8054600093849055929055908115610e0057609854609e54610e00916001600160a01b0391821691600160301b9091041684612e67565b8015610e2b57609854609f54610e2b916001600160a01b0391821691600160301b9091041683612e67565b5050565b600080600060026065541415610e575760405162461bcd60e51b8152600401610857906159b6565b600260655584610e795760405162461bcd60e51b815260040161085790615996565b609754600160e01b900461ffff16612b67141580610ea157506097546001600160a01b031633145b610eda5760405162461bcd60e51b815260206004820152600a6024820152691c995cdd1c9a58dd195960b21b6044820152606401610857565b6000610ee560355490565b90506000609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b158015610f3757600080fd5b505afa158015610f4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6f91906155ba565b50505050505090506000821115610fb057600080610f8b610720565b91509150610f9a828a86612ecf565b9650610fa7818a86612ecf565b95505050610ffd565b610ff781610fcf609760149054906101000a900460020b60020b612f26565b609754610fe990600160b81b9004600290810b900b612f26565b610ff28b613338565b6133a1565b90955093505b841561101b57609e5461101b906001600160a01b031633308861343d565b831561103957609f54611039906001600160a01b031633308761343d565b61107981611058609760149054906101000a900460020b60020b612f26565b60975461107290600160b81b9004600290810b900b612f26565b8888613475565b609d54609754604051633c8a7d8d60e01b81529295506001600160a01b0390911691633c8a7d8d916110c9913091600160a01b8104600290810b92600160b81b909204900b908990600401615727565b6040805180830381600087803b1580156110e257600080fd5b505af11580156110f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111a919061535e565b50506111268688613537565b7f55801cfe493000b734571da1694b21e7f66b11e8ce9fdaa0524ecb59105e73e7868887878760405161115d959493929190615769565b60405180910390a1505060016065819055509250925092565b60606037805461068790615c40565b60008060008061119460355490565b905080156111b3576111a7818787613604565b919550935091506112cf565b609d5460408051633850c7bd60e01b815290516000926001600160a01b031691633850c7bd9160048083019260e0929190829003018186803b1580156111f857600080fd5b505afa15801561120c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123091906155ba565b5050505050509050600061127a82611259609760149054906101000a900460020b60020b612f26565b60975461127390600160b81b9004600290810b900b612f26565b8b8b613475565b9050806001600160801b031693506112c7826112a7609760149054906101000a900460020b60020b612f26565b6097546112c190600160b81b9004600290810b900b612f26565b846133a1565b909650945050505b509250925092565b3360009081526034602090815260408083206001600160a01b0386168452909152812054828110156113595760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610857565b611368338561086f8685615bfd565b5060019392505050565b6000610717338484612514565b8181336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113f35760405162461bcd60e51b815260206004820152601760248201527647656c61746f666965643a204f6e6c792067656c61746f60481b6044820152606401610857565b8515611403576114038786613713565b609d546000906001600160a01b031663514ea4bf61141f6126da565b6040518263ffffffff1660e01b815260040161143d91815260200190565b60a06040518083038186803b15801561145557600080fd5b505afa158015611469573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148d9190615564565b5050505090506114a18189898989896139c1565b609d546000906001600160a01b031663514ea4bf6114bd6126da565b6040518263ffffffff1660e01b81526004016114db91815260200190565b60a06040518083038186803b1580156114f357600080fd5b505afa158015611507573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152b9190615564565b505050509050816001600160801b0316816001600160801b03161161158c5760405162461bcd60e51b81526020600482015260176024820152766c6971756964697479206d75737420696e63726561736560481b6044820152606401610857565b609754604051600080516020615d6a833981519152916115c691600160a01b8204600290810b92600160b81b9004900b90869086906157f8565b60405180910390a150506001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561162d576116286001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683613f19565b611661565b6116616001600160a01b0382167f000000000000000000000000000000000000000000000000000000000000000084612e67565b50505050505050565b6000806000609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b1580156116bd57600080fd5b505afa1580156116d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f591906155ba565b50505050509150506117078482612263565b9250925050915091565b3361171a610cf2565b6001600160a01b0316146117405760405162461bcd60e51b815260040161085790615954565b6127108360010b13156117655760405162461bcd60e51b815260040161085790615937565b6127108260010b131561178a5760405162461bcd60e51b815260040161085790615937565b61179760fa612710615b36565b60010b8560010b13156117bc5760405162461bcd60e51b815260040161085790615859565b60008560010b126117e2576098805461ffff60201b1916600160201b61ffff8816021790555b60008360010b12611808576097805461ffff60d01b1916600160d01b61ffff8616021790555b60008260010b1261182f57609780546001600160f01b0316600160f01b61ffff8516021790555b60008160030b12611850576098805463ffffffff191663ffffffff83161790555b6001600160a01b038416156118845760988054600160301b600160d01b031916600160301b6001600160a01b038716021790555b6098546097546040805161ffff600160201b8504811682526001600160a01b03600160301b8604166020830152600160d01b8404811692820192909252600160f01b90920416606082015263ffffffff90911660808201527ff459b381c988c676562c20a01f42f488c5560ed2e3957b0f27f26573418b61939060a00160405180910390a15050505050565b609d546001600160a01b0316331461193a5760405162461bcd60e51b815260040161085790615877565b831561195757609e54611957906001600160a01b03163386612e67565b821561197457609f54611974906001600160a01b03163385612e67565b50505050565b609b8054609c80546000938490559290559081156119c957609e546119c9906001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000084612e67565b8015610e2b57609f54610e2b906001600160a01b03167f000000000000000000000000000000000000000000000000000000000000000083612e67565b6000611a106126da565b905090565b600054610100900460ff1680611a2e575060005460ff16155b611a4a5760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015611a6c576000805461ffff19166101011790555b611a7960fa612710615bba565b61ffff168561ffff161115611aa05760405162461bcd60e51b815260040161085790615859565b609d80546001600160a01b0319166001600160a01b03881690811790915560408051630dfe168160e01b81529051630dfe168191600480820192602092909190829003018186803b158015611af457600080fd5b505afa158015611b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2c91906150f8565b609e80546001600160a01b0319166001600160a01b03928316179055609d546040805163d21220a760e01b81529051919092169163d21220a7916004808301926020929190829003018186803b158015611b8557600080fd5b505afa158015611b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbd91906150f8565b609f80546001600160a01b0319166001600160a01b03928316179055609780546098805461012c600160201b600160d01b0319909116600160201b61ffff8c1602600160301b600160d01b03191617948716600160301b81029590951763ffffffff1916179055601960d31b600160a01b600160f01b03909116909217607d60f21b1767ffff000000ffffff60a01b1916600160a01b600288810b62ffffff90811692909202929092179390931762ffffff60b81b1916600160b81b9187900b9390931602919091179055611c92888861402f565b611c9a6140ae565b8015611cac576000805461ff00191690555b5050505050505050565b33611cbf610cf2565b6001600160a01b031614611ce55760405162461bcd60e51b815260040161085790615954565b6001600160a01b038116611d4c5760405162461bcd60e51b815260206004820152602860248201527f4f776e61626c653a206e6577206d616e6167657220697320746865207a65726f604482015267206164647265737360c01b6064820152608401610857565b6097546040516001600160a01b03808416921690600080516020615d8a83398151915290600090a3609780546001600160a01b0319166001600160a01b0392909216919091179055565b609d546001600160a01b03163314611dc05760405162461bcd60e51b815260040161085790615877565b6000841315611de557609e54611de0906001600160a01b03163386612e67565b611974565b600083131561197457609f54611974906001600160a01b03163385612e67565b600080600060026065541415611e2d5760405162461bcd60e51b8152600401610857906159b6565b600260655584611e685760405162461bcd60e51b815260206004820152600660248201526506275726e20360d41b6044820152606401610857565b6000611e7360355490565b609d549091506000906001600160a01b031663514ea4bf611e926126da565b6040518263ffffffff1660e01b8152600401611eb091815260200190565b60a06040518083038186803b158015611ec857600080fd5b505afa158015611edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f009190615564565b505050509050611f103388614122565b6000611f2688836001600160801b03168561425f565b9050611f3181613338565b609754909450600090819081908190611f6090600160a01b8104600290810b91600160b81b9004900b8a612740565b9350935093509350611f728282612acd565b611f7c8282612ba6565b6040519193509150600080516020615dca83398151915290611fa190849084906159ed565b60405180910390a1609b54609954609e546040516370a0823160e01b815261205c93929188916001600160a01b03909116906370a0823190611fe7903090600401615713565b60206040518083038186803b158015611fff57600080fd5b505afa158015612013573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612037919061569a565b6120419190615bfd565b61204b9190615bfd565b6120559190615bfd565b8d8961425f565b6120669085615a96565b609c54609a54609f546040516370a0823160e01b8152939d506120a39387916001600160a01b0316906370a0823190611fe7903090600401615713565b6120ad9084615a96565b985089156120cc57609e546120cc906001600160a01b03168c8c612e67565b88156120e957609f546120e9906001600160a01b03168c8b612e67565b7f7239dff1718b550db7f36cbf69c665cfeb56d0e96b4fb76a5cba712961b655098b8d8c8c8c604051612120959493929190615769565b60405180910390a15050505050505060016065819055509250925092565b6001600160a01b0383166121a05760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610857565b6001600160a01b0382166122015760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610857565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b609d546000908190819081908190819081906001600160a01b031663514ea4bf61228b6126da565b6040518263ffffffff1660e01b81526004016122a991815260200190565b60a06040518083038186803b1580156122c157600080fd5b505afa1580156122d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f99190615564565b9450945094509450945061234289612322609760149054906101000a900460020b60020b612f26565b60975461233c90600160b81b9004600290810b900b612f26565b886133a1565b909750955060006001600160801b0383166123606001878c8a61430e565b61236a9190615a96565b90506000826001600160801b03166123856000878d8b61430e565b61238f9190615a96565b905061239b8282612ba6565b609b54609954609e546040516370a0823160e01b8152949650929450909290916001600160a01b0316906370a08231906123d9903090600401615713565b60206040518083038186803b1580156123f157600080fd5b505afa158015612405573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612429919061569a565b6124339085615a96565b61243d9190615bfd565b6124479190615bfd565b612451908a615a96565b609c54609a54609f546040516370a0823160e01b8152939c50919290916001600160a01b0316906370a082319061248c903090600401615713565b60206040518083038186803b1580156124a457600080fd5b505afa1580156124b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124dc919061569a565b6124e69084615a96565b6124f09190615bfd565b6124fa9190615bfd565b6125049089615a96565b9750505050505050509250929050565b6001600160a01b0383166125785760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610857565b6001600160a01b0382166125da5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610857565b6001600160a01b038316600090815260336020526040902054818110156126525760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610857565b61265c8282615bfd565b6001600160a01b038086166000908152603360205260408082209390935590851681529081208054849290612692908490615a96565b92505081905550826001600160a01b0316846001600160a01b0316600080516020615daa833981519152846040516126cc91815260200190565b60405180910390a350505050565b6097546040516001600160601b03193060601b166020820152600160a01b8204600290810b810b60e890811b6034840152600160b81b909304810b900b90911b6037820152600090603a0160405160208183030381529060405280519060200120905090565b609e546040516370a0823160e01b815260009182918291829182916001600160a01b0316906370a0823190612779903090600401615713565b60206040518083038186803b15801561279157600080fd5b505afa1580156127a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127c9919061569a565b609f546040516370a0823160e01b81529192506000916001600160a01b03909116906370a08231906127ff903090600401615713565b60206040518083038186803b15801561281757600080fd5b505afa15801561282b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284f919061569a565b609d5460405163a34123a760e01b815260028c810b60048301528b900b60248201526001600160801b038a1660448201529192506001600160a01b03169063a34123a7906064016040805180830381600087803b1580156128af57600080fd5b505af11580156128c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e7919061535e565b609d546040516309e3d67b60e31b815230600482015260028d810b60248301528c900b60448201526001600160801b036064820181905260848201529298509096506001600160a01b031690634f1eb3d89060a4016040805180830381600087803b15801561295557600080fd5b505af1158015612969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298d9190615532565b5050609e546040516370a0823160e01b8152879184916001600160a01b03909116906370a08231906129c3903090600401615713565b60206040518083038186803b1580156129db57600080fd5b505afa1580156129ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a13919061569a565b612a1d9190615bfd565b612a279190615bfd565b609f546040516370a0823160e01b8152919550869183916001600160a01b0316906370a0823190612a5c903090600401615713565b60206040518083038186803b158015612a7457600080fd5b505afa158015612a88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aac919061569a565b612ab69190615bfd565b612ac09190615bfd565b9250505093509350935093565b612710612adb60fa84615b17565b612ae59190615ad4565b609b6000828254612af69190615a96565b909155506127109050612b0a60fa83615b17565b612b149190615ad4565b609c6000828254612b259190615a96565b909155505060985461271090612b4690600160201b900461ffff1684615b17565b612b509190615ad4565b60996000828254612b619190615a96565b909155505060985461271090612b8290600160201b900461ffff1683615b17565b612b8c9190615ad4565b609a6000828254612b9d9190615a96565b90915550505050565b6000806000612710609860049054906101000a900461ffff1660fa612bcb9190615a4e565b612bd99061ffff1687615b17565b612be39190615ad4565b60985490915060009061271090612c0690600160201b900461ffff1660fa615a4e565b612c149061ffff1687615b17565b612c1e9190615ad4565b9050612c2a8287615bfd565b9350612c368186615bfd565b925050509250929050565b609d5460408051633850c7bd60e01b815290516000926001600160a01b031691633850c7bd9160048083019260e0929190829003018186803b158015612c8657600080fd5b505afa158015612c9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cbe91906155ba565b50505050505090506000612ceb82612cd88b60020b612f26565b612ce48b60020b612f26565b8a8a613475565b90506001600160801b03811615612da857609d54604051633c8a7d8d60e01b815260009182916001600160a01b0390911690633c8a7d8d90612d379030908f908f908990600401615727565b6040805180830381600087803b158015612d5057600080fd5b505af1158015612d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d88919061535e565b9092509050612d97828a615bfd565b9850612da38189615bfd565b975050505b6000612dd76127108686612dbc5789612dbe565b8a5b612dc89190615b17565b612dd29190615ad4565b61471a565b90506000811315612df457612df18a8a8a8a858b8a614780565b50505b50505050505050505050565b33612e09610cf2565b6001600160a01b031614612e2f5760405162461bcd60e51b815260040161085790615954565b6097546040516000916001600160a01b031690600080516020615d8a833981519152908390a3609780546001600160a01b0319169055565b6040516001600160a01b038316602482015260448101829052612eca90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526149c9565b505050565b6000612edc84848461425f565b905060008280612efc57634e487b7160e01b600052601260045260246000fd5b848609111561087a576000198110612f1357600080fd5b80612f1d81615c7b565b95945050505050565b60008060008360020b12612f3d578260020b612f4a565b8260020b612f4a90615ccb565b9050612f59620d89e719615caa565b60020b811115612f8f5760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610857565b600060018216612fa357600160801b612fb5565b6ffffcb933bd6fad37aa2d162d1a5940015b6001600160881b031690506002821615612fea576080612fe5826ffff97272373d413259a46990580e213a615b17565b901c90505b600482161561301457608061300f826ffff2e50f5f656932ef12357cf3c7fdcc615b17565b901c90505b600882161561303e576080613039826fffe5caca7e10e4e61c3624eaa0941cd0615b17565b901c90505b6010821615613068576080613063826fffcb9843d60f6159c9db58835c926644615b17565b901c90505b602082161561309257608061308d826fff973b41fa98c081472e6896dfb254c0615b17565b901c90505b60408216156130bc5760806130b7826fff2ea16466c96a3843ec78b326b52861615b17565b901c90505b60808216156130e65760806130e1826ffe5dee046a99a2a811c461f1969c3053615b17565b901c90505b61010082161561311157608061310c826ffcbe86c7900a88aedcffc83b479aa3a4615b17565b901c90505b61020082161561313c576080613137826ff987a7253ac413176f2b074cf7815e54615b17565b901c90505b610400821615613167576080613162826ff3392b0822b70005940c7a398e4b70f3615b17565b901c90505b61080082161561319257608061318d826fe7159475a2c29b7443b29c7fa6e889d9615b17565b901c90505b6110008216156131bd5760806131b8826fd097f3bdfd2022b8845ad8f792aa5825615b17565b901c90505b6120008216156131e85760806131e3826fa9f746462d870fdf8a65dc1f90e061e5615b17565b901c90505b61400082161561321357608061320e826f70d869a156d2a1b890bb3df62baf32f7615b17565b901c90505b61800082161561323e576080613239826f31be135f97d08fd981231505542fcfa6615b17565b901c90505b6201000082161561326a576080613265826f09aa508b5b7a84e1c677de54f3e99bc9615b17565b901c90505b62020000821615613295576080613290826e5d6af8dedb81196699c329225ee604615b17565b901c90505b620400008216156132bf5760806132ba826d2216e584f5fa1ea926041bedfe98615b17565b901c90505b620800008216156132e75760806132e2826b048a170391f7dc42444e8fa2615b17565b901c90505b60008460020b1315613302576132ff81600019615ad4565b90505b613310600160201b82615c96565b1561331c57600161331f565b60005b6133309060ff16602083901c615a96565b949350505050565b6000600160801b821061339d5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401610857565b5090565b600080836001600160a01b0316856001600160a01b031611156133c2579293925b846001600160a01b0316866001600160a01b0316116133ed576133e6858585614a9b565b9150613434565b836001600160a01b0316866001600160a01b0316101561342657613412868585614a9b565b915061341f858785614b05565b9050613434565b613431858585614b05565b90505b94509492505050565b6040516001600160a01b03808516602483015283166044820152606481018290526119749085906323b872dd60e01b90608401612e93565b6000836001600160a01b0316856001600160a01b03161115613495579293925b846001600160a01b0316866001600160a01b0316116134c0576134b9858585614b4f565b9050612f1d565b836001600160a01b0316866001600160a01b031610156135225760006134e7878686614b4f565b905060006134f6878986614bb9565b9050806001600160801b0316826001600160801b0316106135175780613519565b815b92505050612f1d565b61352d858584614bb9565b9695505050505050565b6001600160a01b03821661358d5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610857565b806035600082825461359f9190615a96565b90915550506001600160a01b038216600090815260336020526040812080548392906135cc908490615a96565b90915550506040518181526001600160a01b03831690600090600080516020615daa8339815191529060200160405180910390a35050565b6000806000806000613614610720565b915091508160001480156136285750600081115b1561363f5761363886898361425f565b92506136ee565b8015801561364d5750600082115b1561365d5761363887898461425f565b81158015613669575080155b156136905760405162461bcd60e51b81526020600482015260006024820152604401610857565b600061369d888a8561425f565b905060006136ac888b8561425f565b90506000821180156136be5750600081115b6136da5760405162461bcd60e51b815260040161085790615996565b8082106136e757806136e9565b815b945050505b6136f983838a612ecf565b945061370683828a612ecf565b9350505093509350939050565b6040805160028082526060820183526000926020830190803683375050609854825192935063ffffffff169183915060009061375f57634e487b7160e01b600052603260045260246000fd5b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061379c57634e487b7160e01b600052603260045260246000fd5b63ffffffff90921660209283029190910190910152609d5460405163883bdbfd60e01b81526000916001600160a01b03169063883bdbfd906137e29085906004016157a0565b60006040518083038186803b1580156137fa57600080fd5b505afa15801561380e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261383691908101906151b7565b50905080516002146138765760405162461bcd60e51b815260206004820152600960248201526830b93930bc903632b760b91b6044820152606401610857565b6098548151600091829163ffffffff90911660060b90849083906138aa57634e487b7160e01b600052603260045260246000fd5b6020026020010151846001815181106138d357634e487b7160e01b600052603260045260246000fd5b60200260200101510360060b816138fa57634e487b7160e01b600052601260045260246000fd5b0590506139098160020b612f26565b609754909250600091506127109061392c90600160f01b900461ffff1684615ae8565b6139369190615aae565b9050841561397e576139488183615bdd565b6001600160a01b0316866001600160a01b031610156139795760405162461bcd60e51b815260040161085790615910565b6139b9565b6139888183615a74565b6001600160a01b0316866001600160a01b031611156139b95760405162461bcd60e51b815260040161085790615910565b505050505050565b609b54609954609e546040516370a0823160e01b815260009392916001600160a01b0316906370a08231906139fa903090600401615713565b60206040518083038186803b158015613a1257600080fd5b505afa158015613a26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4a919061569a565b613a549190615bfd565b613a5e9190615bfd565b609c54609a54609f546040516370a0823160e01b81529394506000936001600160a01b03909116906370a0823190613a9a903090600401615713565b60206040518083038186803b158015613ab257600080fd5b505afa158015613ac6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613aea919061569a565b613af49190615bfd565b613afe9190615bfd565b6097549091506000908190613b2990600160a01b8104600290810b91600160b81b9004900b8c612740565b935093505050613b398282612acd565b613b438282612ba6565b6040519193509150600080516020615dca83398151915290613b6890849084906159ed565b60405180910390a1613b7a8483615a96565b9150613b868382615a96565b609e549091506001600160a01b0386811691161415613d3157609754869061271090613bbd90600160d01b900461ffff1685615b17565b613bc79190615ad4565b1015613be55760405162461bcd60e51b8152600401610857906158ee565b609b54609954609e546040516370a0823160e01b8152899392916001600160a01b0316906370a0823190613c1d903090600401615713565b60206040518083038186803b158015613c3557600080fd5b505afa158015613c49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c6d919061569a565b613c779190615bfd565b613c819190615bfd565b613c8b9190615bfd565b609c54609a54609f546040516370a0823160e01b8152939750919290916001600160a01b0316906370a0823190613cc6903090600401615713565b60206040518083038186803b158015613cde57600080fd5b505afa158015613cf2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d16919061569a565b613d209190615bfd565b613d2a9190615bfd565b9250613ef2565b609f546001600160a01b0386811691161415613ebc57609754869061271090613d6590600160d01b900461ffff1684615b17565b613d6f9190615ad4565b1015613d8d5760405162461bcd60e51b8152600401610857906158ee565b609b54609954609e546040516370a0823160e01b81526001600160a01b03909116906370a0823190613dc3903090600401615713565b60206040518083038186803b158015613ddb57600080fd5b505afa158015613def573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e13919061569a565b613e1d9190615bfd565b613e279190615bfd565b609c54609a54609f546040516370a0823160e01b815293975089936001600160a01b03909116906370a0823190613e62903090600401615713565b60206040518083038186803b158015613e7a57600080fd5b505afa158015613e8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613eb2919061569a565b613d169190615bfd565b60405162461bcd60e51b815260206004820152600b60248201526a3bb937b733903a37b5b2b760a91b6044820152606401610857565b609754612df490600160a01b8104600290810b91600160b81b9004900b86868d8d8d612c41565b80471015613f695760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610857565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613fb6576040519150601f19603f3d011682016040523d82523d6000602084013e613fbb565b606091505b5050905080612eca5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c20726044820152791958da5c1a595b9d081b585e481a185d99481c995d995c9d195960321b6064820152608401610857565b600054610100900460ff1680614048575060005460ff16155b6140645760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614086576000805461ffff19166101011790555b61408e614bef565b6140988383614c59565b8015612eca576000805461ff0019169055505050565b600054610100900460ff16806140c7575060005460ff16155b6140e35760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614105576000805461ffff19166101011790555b61410d614cee565b801561411f576000805461ff00191690555b50565b6001600160a01b0382166141825760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610857565b6001600160a01b038216600090815260336020526040902054818110156141f65760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610857565b6142008282615bfd565b6001600160a01b0384166000908152603360205260408120919091556035805484929061422e908490615bfd565b90915550506040518281526000906001600160a01b03851690600080516020615daa83398151915290602001612256565b600080806000198587098587029250828110838203039150508060001415614299576000841161428e57600080fd5b50829004905061087a565b8084116142a557600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b60008060008087156144db57609d60009054906101000a90046001600160a01b03166001600160a01b031663f30583996040518163ffffffff1660e01b815260040160206040518083038186803b15801561436857600080fd5b505afa15801561437c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143a0919061569a565b609d5460975460405163f30dba9360e01b81529293506001600160a01b039091169163f30dba93916143e091600160a01b90910460020b906004016157ea565b6101006040518083038186803b1580156143f957600080fd5b505afa15801561440d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144319190615490565b5050609d5460975460405163f30dba9360e01b8152959a506001600160a01b03909116965063f30dba93955061447a94600160b81b90910460020b935060040191506157ea9050565b6101006040518083038186803b15801561449357600080fd5b505afa1580156144a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144cb9190615490565b5093975061469695505050505050565b609d60009054906101000a90046001600160a01b03166001600160a01b031663461413196040518163ffffffff1660e01b815260040160206040518083038186803b15801561452957600080fd5b505afa15801561453d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614561919061569a565b609d5460975460405163f30dba9360e01b81529293506001600160a01b039091169163f30dba93916145a191600160a01b90910460020b906004016157ea565b6101006040518083038186803b1580156145ba57600080fd5b505afa1580156145ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145f29190615490565b5050609d5460975460405163f30dba9360e01b8152949a506001600160a01b03909116965063f30dba93955061463a9450600160b81b900460020b9260040191506157ea9050565b6101006040518083038186803b15801561465357600080fd5b505afa158015614667573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061468b9190615490565b509297505050505050505b6000609760149054906101000a900460020b60020b8760020b126146bb5750826146c0565b508281035b6000609760179054906101000a900460020b60020b8860020b12156146e65750826146eb565b508282035b81830381900361470b6001600160801b0389168b8303600160801b61425f565b9b9a5050505050505050505050565b6000600160ff1b821061339d5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401610857565b609d54604051630251596160e31b81523060048201528215156024820152604481018590526001600160a01b03848116606483015260a06084830152600060a4830181905292839283928392169063128acb089060c4016040805180830381600087803b1580156147f057600080fd5b505af1158015614804573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614828919061535e565b91509150816148368a61471a565b6148409190615b7b565b93508061484c8961471a565b6148569190615b7b565b92506000609d60009054906101000a90046001600160a01b03166001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b1580156148a857600080fd5b505afa1580156148bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148e091906155ba565b5050505050509050600061490d826148fa8f60020b612f26565b6149068f60020b612f26565b8989613475565b90506001600160801b038116156149b957609d60009054906101000a90046001600160a01b03166001600160a01b0316633c8a7d8d308f8f856040518563ffffffff1660e01b81526004016149659493929190615727565b6040805180830381600087803b15801561497e57600080fd5b505af1158015614992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149b6919061535e565b50505b5050505097509795505050505050565b6000614a1e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614d5e9092919063ffffffff16565b805190915015612eca5780806020019051810190614a3c919061527a565b612eca5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610857565b6000826001600160a01b0316846001600160a01b03161115614abb579192915b6001600160a01b038416614afb600160601b600160e01b03606085901b16614ae38787615bdd565b6001600160a01b0316866001600160a01b031661425f565b6133309190615ad4565b6000826001600160a01b0316846001600160a01b03161115614b25579192915b6133306001600160801b038316614b3c8686615bdd565b6001600160a01b0316600160601b61425f565b6000826001600160a01b0316846001600160a01b03161115614b6f579192915b6000614b92856001600160a01b0316856001600160a01b0316600160601b61425f565b9050612f1d614bb48483614ba68989615bdd565b6001600160a01b031661425f565b614d6d565b6000826001600160a01b0316846001600160a01b03161115614bd9579192915b613330614bb483600160601b614ba68888615bdd565b600054610100900460ff1680614c08575060005460ff16155b614c245760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff1615801561410d576000805461ffff1916610101179055801561411f576000805461ff001916905550565b600054610100900460ff1680614c72575060005460ff16155b614c8e5760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614cb0576000805461ffff19166101011790555b8251614cc3906036906020860190614ee9565b508151614cd7906037906020850190614ee9565b508015612eca576000805461ff0019169055505050565b600054610100900460ff1680614d07575060005460ff16155b614d235760405162461bcd60e51b8152600401610857906158a0565b600054610100900460ff16158015614d45576000805461ffff19166101011790555b6001606555801561411f576000805461ff001916905550565b60606133308484600085614d88565b806001600160801b0381168114614d8357600080fd5b919050565b606082471015614de95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610857565b843b614e375760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610857565b600080866001600160a01b03168587604051614e5391906156f7565b60006040518083038185875af1925050503d8060008114614e90576040519150601f19603f3d011682016040523d82523d6000602084013e614e95565b606091505b5091509150614ea5828286614eb0565b979650505050505050565b60608315614ebf57508161087a565b825115614ecf5782518084602001fd5b8160405162461bcd60e51b81526004016108579190615826565b828054614ef590615c40565b90600052602060002090601f016020900481019282614f175760008555614f5d565b82601f10614f3057805160ff1916838001178555614f5d565b82800160010185558215614f5d579182015b82811115614f5d578251825591602001919060010190614f42565b5061339d9291505b8082111561339d5760008155600101614f65565b600082601f830112614f89578081fd5b81516020614f9e614f9983615a2b565b6159fb565b80838252828201915082860187848660051b8901011115614fbd578586fd5b855b85811015614fe4578151614fd281615d27565b84529284019290840190600101614fbf565b5090979650505050505050565b60008083601f840112615002578182fd5b5081356001600160401b03811115615018578182fd5b60208301915083602082850101111561503057600080fd5b9250929050565b8035600181900b8114614d8357600080fd5b8051600681900b8114614d8357600080fd5b600082601f83011261506b578081fd5b81356001600160401b0381111561508457615084615d11565b615097601f8201601f19166020016159fb565b8181528460208386010111156150ab578283fd5b816020850160208301379081016020019190915292915050565b80516001600160801b0381168114614d8357600080fd5b6000602082840312156150ed578081fd5b813561087a81615d27565b600060208284031215615109578081fd5b815161087a81615d27565b60008060408385031215615126578081fd5b823561513181615d27565b9150602083013561514181615d27565b809150509250929050565b600080600060608486031215615160578081fd5b833561516b81615d27565b9250602084013561517b81615d27565b929592945050506040919091013590565b6000806040838503121561519e578182fd5b82356151a981615d27565b946020939093013593505050565b600080604083850312156151c9578182fd5b82516001600160401b03808211156151df578384fd5b818501915085601f8301126151f2578384fd5b81516020615202614f9983615a2b565b8083825282820191508286018a848660051b8901011115615221578889fd5b8896505b8487101561524a5761523681615049565b835260019690960195918301918301615225565b5091880151919650909350505080821115615263578283fd5b5061527085828601614f79565b9150509250929050565b60006020828403121561528b578081fd5b815161087a81615d3c565b600080600080600060a086880312156152ad578283fd5b6152b686615037565b945060208601356152c681615d27565b93506152d460408701615037565b92506152e260608701615037565b915060808601358060030b81146152f7578182fd5b809150509295509295909350565b600080600080600060a0868803121561531c578283fd5b853561532781615d4a565b9450602086013561533781615d4a565b9350604086013561534781615d27565b92506060860135915060808601356152f781615d3c565b60008060408385031215615370578182fd5b505080516020909101519092909150565b60008060008060608587031215615396578182fd5b843593506020850135925060408501356001600160401b038111156153b9578283fd5b6153c587828801614ff1565b95989497509550505050565b600080600080600080600060e0888a0312156153eb578485fd5b87356001600160401b0380821115615401578687fd5b61540d8b838c0161505b565b985060208a0135915080821115615422578687fd5b5061542f8a828b0161505b565b965050604088013561544081615d27565b9450606088013561545081615d59565b9350608088013561546081615d4a565b925060a088013561547081615d4a565b915060c088013561548081615d27565b8091505092959891949750929550565b600080600080600080600080610100898b0312156154ac578182fd5b6154b5896150c5565b9750602089015180600f0b81146154ca578283fd5b60408a015160608b0151919850965094506154e760808a01615049565b935060a08901516154f781615d27565b60c08a015190935063ffffffff81168114615510578283fd5b60e08a015190925061552181615d3c565b809150509295985092959890939650565b60008060408385031215615544578182fd5b61554d836150c5565b915061555b602084016150c5565b90509250929050565b600080600080600060a0868803121561557b578283fd5b615584866150c5565b945060208601519350604086015192506155a0606087016150c5565b91506155ae608087016150c5565b90509295509295909350565b600080600080600080600060e0888a0312156155d4578081fd5b87516155df81615d27565b60208901519097506155f081615d4a565b604089015190965061560181615d59565b606089015190955061561281615d59565b608089015190945061562381615d59565b60a089015190935060ff81168114615639578182fd5b60c089015190925061548081615d3c565b600080600080600060a08688031215615661578283fd5b853561566c81615d27565b945060208601359350604086013561568381615d3c565b92506060860135915060808601356152f781615d27565b6000602082840312156156ab578081fd5b5051919050565b600080604083850312156156c4578182fd5b82359150602083013561514181615d27565b600080604083850312156156e8578182fd5b50508035926020909101359150565b60008251615709818460208701615c14565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03949094168452600292830b6020850152910b60408301526001600160801b0316606082015260a06080820181905260009082015260c00190565b6001600160a01b039590951685526020850193909352604084019190915260608301526001600160801b0316608082015260a00190565b6020808252825182820181905260009190848201906040850190845b818110156157de57835163ffffffff16835292840192918401916001016157bc565b50909695505050505050565b60029190910b815260200190565b600294850b81529290930b60208301526001600160801b039081166040830152909116606082015260800190565b6020815260008251806020840152615845816040850160208701615c14565b601f01601f19169190910160400192915050565b6020808252600490820152636d42505360e01b604082015260600190565b6020808252600f908201526e31b0b6363130b1b59031b0b63632b960891b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b602080825260089082015267686967682066656560c01b604082015260600190565b6020808252600d908201526c6869676820736c69707061676560981b604082015260600190565b60208082526003908201526242505360e81b604082015260600190565b60208082526022908201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206d616e616760408201526132b960f11b606082015260800190565b60208082526006908201526506d696e7420360d41b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b918252602082015260400190565b604051601f8201601f191681016001600160401b0381118282101715615a2357615a23615d11565b604052919050565b60006001600160401b03821115615a4457615a44615d11565b5060051b60200190565b600061ffff808316818516808303821115615a6b57615a6b615ce5565b01949350505050565b60006001600160a01b03828116848216808303821115615a6b57615a6b615ce5565b60008219821115615aa957615aa9615ce5565b500190565b60006001600160a01b0383811680615ac857615ac8615cfb565b92169190910492915050565b600082615ae357615ae3615cfb565b500490565b60006001600160a01b0382811684821681151582840482111615615b0e57615b0e615ce5565b02949350505050565b6000816000190483118215151615615b3157615b31615ce5565b500290565b60008160010b8360010b82811281617fff1901831281151615615b5b57615b5b615ce5565b81617fff018313811615615b7157615b71615ce5565b5090039392505050565b60008083128015600160ff1b850184121615615b9957615b99615ce5565b6001600160ff1b0384018313811615615bb457615bb4615ce5565b50500390565b600061ffff83811690831681811015615bd557615bd5615ce5565b039392505050565b60006001600160a01b0383811690831681811015615bd557615bd5615ce5565b600082821015615c0f57615c0f615ce5565b500390565b60005b83811015615c2f578181015183820152602001615c17565b838111156119745750506000910152565b600181811c90821680615c5457607f821691505b60208210811415615c7557634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415615c8f57615c8f615ce5565b5060010190565b600082615ca557615ca5615cfb565b500690565b60008160020b627fffff19811415615cc457615cc4615ce5565b9003919050565b6000600160ff1b821415615ce157615ce1615ce5565b0390565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461411f57600080fd5b801515811461411f57600080fd5b8060020b811461411f57600080fd5b61ffff8116811461411f57600080fdfec749f9ae947d4734cf1569606a8a347391ae94a063478aa853aeff48ac5f99e88be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc28ad1de9c0c32e5394ba60323e44d8d9536312236a47231772e448a3e49de42a26469706673582212207b33fb5362c9dc6a985db59388b6f1c39cf259872c1c74ed13a9b873a23d924364736f6c63430008040033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/external/abi/arrakis/GUniRouter.json b/external/abi/arrakis/GUniRouter.json new file mode 100644 index 000000000..a5fafd324 --- /dev/null +++ b/external/abi/arrakis/GUniRouter.json @@ -0,0 +1,448 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GUniRouter", + "sourceName": "contracts/GUniRouter.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IUniswapV3Factory", + "name": "_factory", + "type": "address" + }, + { + "internalType": "contract IWETH", + "name": "_weth", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "contract IGUniPool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount0Max", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Max", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "addLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGUniPool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount0Max", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Max", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "addLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "contract IUniswapV3Factory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "internalType": "address", + "name": "token1", + "type": "address" + } + ], + "name": "isToken0Weth", + "outputs": [ + { + "internalType": "bool", + "name": "wethToken0", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGUniPool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount0In", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1In", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "zeroForOne", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "swapThreshold", + "type": "uint160" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "rebalanceAndAddLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGUniPool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount0In", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1In", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "zeroForOne", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "swapAmount", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "swapThreshold", + "type": "uint160" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "rebalanceAndAddLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGUniPool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "burnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "removeLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "liquidityBurned", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IGUniPool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "burnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount0Min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Min", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "receiver", + "type": "address" + } + ], + "name": "removeLiquidityETH", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "liquidityBurned", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200293e3803806200293e833981016040819052620000349162000054565b6001600160601b0319606091821b811660805291901b1660a052620000ab565b6000806040838503121562000067578182fd5b8251620000748162000092565b6020840151909250620000878162000092565b809150509250929050565b6001600160a01b0381168114620000a857600080fd5b50565b60805160601c60a05160601c61281a62000124600039600081816101b80152610b580152600081816101130152818161024601528181610288015281816106350152818161075a0152818161089a0152818161093d01528181610fc6015281816110aa015281816118e80152611a0f015261281a6000f3fe6080604052600436106100855760003560e01c8063207e88f71461009157806333f9ab55146100c65780633fc8cef31461010157806359f842b2146101425780636587e4ce14610186578063c45a0155146101a6578063dcdf7202146101da578063fa461e33146101ed578063fb9f47891461020f578063fbec41a81461022f57600080fd5b3661008c57005b600080fd5b34801561009d57600080fd5b506100b16100ac36600461233f565b610242565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100e66100e1366004612393565b610319565b604080519384526020840192909252908201526060016100bd565b34801561010d57600080fd5b506101357f000000000000000000000000000000000000000000000000000000000000000081565b6040516100bd9190612638565b34801561014e57600080fd5b5061016261015d366004612421565b610387565b6040805193845260208401929092526001600160801b0316908201526060016100bd565b34801561019257600080fd5b506101626101a1366004612421565b61045e565b3480156101b257600080fd5b506101357f000000000000000000000000000000000000000000000000000000000000000081565b6100e66101e8366004612393565b610822565b3480156101f957600080fd5b5061020d6102083660046124f6565b6109c1565b005b34801561021b57600080fd5b506100e661022a366004612476565b610c74565b6100e661023d366004612476565b610e2b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316141561028657506001610313565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614156102c857506000610313565b60405162461bcd60e51b815260206004820152601b60248201527a0dedcca40e0deded840e8ded6cadc40daeae6e840c4ca40ae8aa89602b1b60448201526064015b60405180910390fd5b92915050565b6000806000806000806103308f8f8f8f8f8f611201565b9250925092508883101580156103465750878210155b6103625760405162461bcd60e51b815260040161030a906126c8565b61036f8f8484848b61149a565b95509550955050505099509950999650505050505050565b600080806103a06001600160a01b03891633308a61165b565b604051633f34d4cf60e21b81526001600160a01b0389169063fcd3533c906103ce908a908890600401612736565b606060405180830381600087803b1580156103e857600080fd5b505af11580156103fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042091906125ab565b919450925090508583108015906104375750848210155b6104535760405162461bcd60e51b815260040161030a90612698565b955095509592505050565b600080600080610549896001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156104a057600080fd5b505afa1580156104b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d89190612323565b8a6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561051157600080fd5b505afa158015610525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ac9190612323565b90506105606001600160a01b038a1633308b61165b565b604051633f34d4cf60e21b81526001600160a01b038a169063fcd3533c9061058e908b903090600401612736565b606060405180830381600087803b1580156105a857600080fd5b505af11580156105bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e091906125ab565b919550935091508684108015906105f75750858310155b6106135760405162461bcd60e51b815260040161030a90612698565b801561073e5783156106ad57604051632e1a7d4d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561068157600080fd5b505af1158015610695573d6000803e3d6000fd5b506106ad925050506001600160a01b038616856116cc565b82156107395761073985848b6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b505afa158015610705573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107299190612323565b6001600160a01b031691906117e7565b610816565b82156107d257604051632e1a7d4d60e01b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b506107d2925050506001600160a01b038616846116cc565b83156108165761081685858b6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b50955095509592505050565b6000806000806000806108398f8f8f8f8f8f611806565b92509250925088831015801561084f5750878210155b61086b5760405162461bcd60e51b815260040161030a906126c8565b6108788f8484848b61149a565b6040516370a0823160e01b815292985090965094506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a08231906108cf903090600401612638565b60206040518083038186803b1580156108e757600080fd5b505afa1580156108fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190612593565b905080156109ae57604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561098957600080fd5b505af115801561099d573d6000803e3d6000fd5b506109ae92503391508390506116cc565b5050505099509950999650505050505050565b60003390506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610a0157600080fd5b505afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a399190612323565b90506000826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610a7657600080fd5b505afa158015610a8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aae9190612323565b90506000836001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610aeb57600080fd5b505afa158015610aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b239190612570565b604051630b4c774160e11b81526001600160a01b038581166004830152848116602483015262ffffff831660448301529192507f000000000000000000000000000000000000000000000000000000000000000090911690631698ee829060640160206040518083038186803b158015610b9c57600080fd5b505afa158015610bb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd49190612323565b6001600160a01b0316336001600160a01b031614610c2b5760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a59081d5b9a5cddd85c081c1bdbdb60621b604482015260640161030a565b6000881315610c4d57610c486001600160a01b038416338a6117e7565b610c6a565b6000871315610c6a57610c6a6001600160a01b03831633896117e7565b5050505050505050565b6000806000806000808b6001600160a01b0316639894f21a8c8c6040518363ffffffff1660e01b8152600401610cb4929190918252602082015260400190565b60606040518083038186803b158015610ccc57600080fd5b505afa158015610ce0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0491906125ef565b925092509250888310158015610d1a5750878210155b610d365760405162461bcd60e51b815260040161030a906126c8565b8215610dc457610dc43330858f6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b505afa158015610d8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db39190612323565b6001600160a01b031692919061165b565b8115610e0957610e093330848f6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b610e168c8484848b61149a565b95509550955050505096509650969350505050565b6000806000806000808b6001600160a01b0316639894f21a8c8c6040518363ffffffff1660e01b8152600401610e6b929190918252602082015260400190565b60606040518083038186803b158015610e8357600080fd5b505afa158015610e97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebb91906125ef565b925092509250888310158015610ed15750878210155b610eed5760405162461bcd60e51b815260040161030a906126c8565b610f9a8c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2957600080fd5b505afa158015610f3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f619190612323565b8d6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561051157600080fd5b1561108357348b14610fbe5760405162461bcd60e51b815260040161030a906126f3565b8215611039577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561101f57600080fd5b505af1158015611033573d6000803e3d6000fd5b50505050505b811561107e5761107e3330848f6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b611162565b348a146110a25760405162461bcd60e51b815260040161030a906126f3565b811561111d577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561110357600080fd5b505af1158015611117573d6000803e3d6000fd5b50505050505b8215611162576111623330858f6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b61116f8c8484848b61149a565b8096508197508298505050506111b78c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2957600080fd5b156111dd57828b11156111d8576111d86111d1848d612765565b33906116cc565b6111f2565b818a11156111f2576111f26111d1838c612765565b50505096509650969350505050565b60008080871561124a5761124a33308a8c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b861561128f5761128f3330898c6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b61129b89878787611c8f565b6000896001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016113399190612638565b60206040518083038186803b15801561135157600080fd5b505afa158015611365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113899190612593565b905060008a6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c657600080fd5b505afa1580156113da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fe9190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016114299190612638565b60206040518083038186803b15801561144157600080fd5b505afa158015611455573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114799190612593565b90506114868b8383611da7565b919d909c50909a5098505050505050505050565b60008080861561152a5761152a88888a6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156114e257600080fd5b505afa1580156114f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151a9190612323565b6001600160a01b03169190611edb565b851561156e5761156e88878a6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156114e257600080fd5b6040516394bf804d60e01b81526001600160a01b038916906394bf804d9061159c9088908890600401612736565b606060405180830381600087803b1580156115b657600080fd5b505af11580156115ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ee91906125ab565b509093509150868314801561160257508582145b61164d5760405162461bcd60e51b815260206004820152601c60248201527b1d5b995e1c1958dd195908185b5bdd5b9d1cc819195c1bdcda5d195960221b604482015260640161030a565b849050955095509592505050565b6040516001600160a01b03808516602483015283166044820152606481018290526116c69085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611f8a565b50505050565b8047101561171c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161030a565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611769576040519150601f19603f3d011682016040523d82523d6000602084013e61176e565b606091505b50509050806117e25760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c20726044820152791958da5c1a595b9d081b585e481a185d99481c995d995c9d195960321b606482015260840161030a565b505050565b6117e28363a9059cbb60e01b848460405160240161168f92919061264c565b6000806000806118b98a6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561184857600080fd5b505afa15801561185c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118809190612323565b8b6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561051157600080fd5b9050881561199e57801561195f573489146118e65760405162461bcd60e51b815260040161030a906126f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db08a6040518263ffffffff1660e01b81526004016000604051808303818588803b15801561194157600080fd5b505af1158015611955573d6000803e3d6000fd5b505050505061199e565b61199e33308b8d6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b8715611a825780156119ee576119e933308a8d6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b611a82565b348814611a0d5760405162461bcd60e51b815260040161030a906126f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0896040518263ffffffff1660e01b81526004016000604051808303818588803b158015611a6857600080fd5b505af1158015611a7c573d6000803e3d6000fd5b50505050505b611a8e8a888888611c8f565b60008a6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611ac957600080fd5b505afa158015611add573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b019190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611b2c9190612638565b60206040518083038186803b158015611b4457600080fd5b505afa158015611b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7c9190612593565b905060008b6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015611bb957600080fd5b505afa158015611bcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf19190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611c1c9190612638565b60206040518083038186803b158015611c3457600080fd5b505afa158015611c48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6c9190612593565b9050611c7a8c83838661205c565b919e909d50909b509950505050505050505050565b836001600160a01b03166316f0115b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cc857600080fd5b505afa158015611cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d009190612323565b604051630251596160e31b81523060048201528415156024820152604481018490526001600160a01b03838116606483015260a06084830152600060a4830152919091169063128acb089060c4016040805180830381600087803b158015611d6757600080fd5b505af1158015611d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9f91906124d3565b505050505050565b604051634c4a790d60e11b81526004810183905260248101829052600090819081906001600160a01b03871690639894f21a9060440160606040518083038186803b158015611df557600080fd5b505afa158015611e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2d91906125ef565b9194509250905082851115611e8357611e8333611e4a8588612765565b886001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b81841115611ed257611ed233611e998487612765565b886001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b93509350939050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015611f2757600080fd5b505afa158015611f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5f9190612593565b611f69919061274d565b90506116c68463095ea7b360e01b858460405160240161168f92919061264c565b6000611fdf826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121a99092919063ffffffff16565b8051909150156117e25780806020019051810190611ffd9190612377565b6117e25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161030a565b604051634c4a790d60e11b81526004810184905260248101839052600090819081906001600160a01b03881690639894f21a9060440160606040518083038186803b1580156120aa57600080fd5b505afa1580156120be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e291906125ef565b9194509250905082861180156120f6575083155b1561214757612142336121098589612765565b896001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b61219f565b81851180156121535750835b1561219f5761219f336121668488612765565b896001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b9450945094915050565b60606121b884846000856121c2565b90505b9392505050565b6060824710156122235760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161030a565b843b6122715760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161030a565b600080866001600160a01b0316858760405161228d919061261c565b60006040518083038185875af1925050503d80600081146122ca576040519150601f19603f3d011682016040523d82523d6000602084013e6122cf565b606091505b50915091506122df8282866122ea565b979650505050505050565b606083156122f95750816121bb565b8251156123095782518084602001fd5b8160405162461bcd60e51b815260040161030a9190612665565b600060208284031215612334578081fd5b81516121bb816127be565b60008060408385031215612351578081fd5b823561235c816127be565b9150602083013561236c816127be565b809150509250929050565b600060208284031215612388578081fd5b81516121bb816127d6565b60008060008060008060008060006101208a8c0312156123b1578485fd5b89356123bc816127be565b985060208a0135975060408a0135965060608a01356123da816127d6565b955060808a0135945060a08a01356123f1816127be565b935060c08a0135925060e08a013591506101008a0135612410816127be565b809150509295985092959850929598565b600080600080600060a08688031215612438578081fd5b8535612443816127be565b94506020860135935060408601359250606086013591506080860135612468816127be565b809150509295509295909350565b60008060008060008060c0878903121561248e578384fd5b8635612499816127be565b95506020870135945060408701359350606087013592506080870135915060a08701356124c5816127be565b809150509295509295509295565b600080604083850312156124e5578182fd5b505080516020909101519092909150565b6000806000806060858703121561250b578182fd5b843593506020850135925060408501356001600160401b038082111561252f578384fd5b818701915087601f830112612542578384fd5b813581811115612550578485fd5b886020828501011115612561578485fd5b95989497505060200194505050565b600060208284031215612581578081fd5b815162ffffff811681146121bb578182fd5b6000602082840312156125a4578081fd5b5051919050565b6000806000606084860312156125bf578081fd5b83516020850151604086015191945092506001600160801b03811681146125e4578182fd5b809150509250925092565b600080600060608486031215612603578081fd5b8351925060208401519150604084015190509250925092565b6000825161262e81846020870161277c565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b602081526000825180602084015261268481604085016020870161277c565b601f01601f19169190910160400192915050565b60208082526016908201527572656365697665642062656c6f77206d696e696d756d60501b604082015260600190565b60208082526011908201527062656c6f77206d696e20616d6f756e747360781b604082015260600190565b60208082526023908201527f6d69736d61746368696e6720616d6f756e74206f662045544820666f7277617260408201526219195960ea1b606082015260800190565b9182526001600160a01b0316602082015260400190565b60008219821115612760576127606127a8565b500190565b600082821015612777576127776127a8565b500390565b60005b8381101561279757818101518382015260200161277f565b838111156116c65750506000910152565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146127d357600080fd5b50565b80151581146127d357600080fdfea2646970667358221220987d503d23c5aa32673995d22b43a1c3936e75b7b4f6aee1b22686840194c48064736f6c63430008040033", + "deployedBytecode": "0x6080604052600436106100855760003560e01c8063207e88f71461009157806333f9ab55146100c65780633fc8cef31461010157806359f842b2146101425780636587e4ce14610186578063c45a0155146101a6578063dcdf7202146101da578063fa461e33146101ed578063fb9f47891461020f578063fbec41a81461022f57600080fd5b3661008c57005b600080fd5b34801561009d57600080fd5b506100b16100ac36600461233f565b610242565b60405190151581526020015b60405180910390f35b3480156100d257600080fd5b506100e66100e1366004612393565b610319565b604080519384526020840192909252908201526060016100bd565b34801561010d57600080fd5b506101357f000000000000000000000000000000000000000000000000000000000000000081565b6040516100bd9190612638565b34801561014e57600080fd5b5061016261015d366004612421565b610387565b6040805193845260208401929092526001600160801b0316908201526060016100bd565b34801561019257600080fd5b506101626101a1366004612421565b61045e565b3480156101b257600080fd5b506101357f000000000000000000000000000000000000000000000000000000000000000081565b6100e66101e8366004612393565b610822565b3480156101f957600080fd5b5061020d6102083660046124f6565b6109c1565b005b34801561021b57600080fd5b506100e661022a366004612476565b610c74565b6100e661023d366004612476565b610e2b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316141561028657506001610313565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614156102c857506000610313565b60405162461bcd60e51b815260206004820152601b60248201527a0dedcca40e0deded840e8ded6cadc40daeae6e840c4ca40ae8aa89602b1b60448201526064015b60405180910390fd5b92915050565b6000806000806000806103308f8f8f8f8f8f611201565b9250925092508883101580156103465750878210155b6103625760405162461bcd60e51b815260040161030a906126c8565b61036f8f8484848b61149a565b95509550955050505099509950999650505050505050565b600080806103a06001600160a01b03891633308a61165b565b604051633f34d4cf60e21b81526001600160a01b0389169063fcd3533c906103ce908a908890600401612736565b606060405180830381600087803b1580156103e857600080fd5b505af11580156103fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061042091906125ab565b919450925090508583108015906104375750848210155b6104535760405162461bcd60e51b815260040161030a90612698565b955095509592505050565b600080600080610549896001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156104a057600080fd5b505afa1580156104b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d89190612323565b8a6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561051157600080fd5b505afa158015610525573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ac9190612323565b90506105606001600160a01b038a1633308b61165b565b604051633f34d4cf60e21b81526001600160a01b038a169063fcd3533c9061058e908b903090600401612736565b606060405180830381600087803b1580156105a857600080fd5b505af11580156105bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e091906125ab565b919550935091508684108015906105f75750858310155b6106135760405162461bcd60e51b815260040161030a90612698565b801561073e5783156106ad57604051632e1a7d4d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561068157600080fd5b505af1158015610695573d6000803e3d6000fd5b506106ad925050506001600160a01b038616856116cc565b82156107395761073985848b6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b505afa158015610705573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107299190612323565b6001600160a01b031691906117e7565b610816565b82156107d257604051632e1a7d4d60e01b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b506107d2925050506001600160a01b038616846116cc565b83156108165761081685858b6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b50955095509592505050565b6000806000806000806108398f8f8f8f8f8f611806565b92509250925088831015801561084f5750878210155b61086b5760405162461bcd60e51b815260040161030a906126c8565b6108788f8484848b61149a565b6040516370a0823160e01b815292985090965094506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a08231906108cf903090600401612638565b60206040518083038186803b1580156108e757600080fd5b505afa1580156108fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091f9190612593565b905080156109ae57604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561098957600080fd5b505af115801561099d573d6000803e3d6000fd5b506109ae92503391508390506116cc565b5050505099509950999650505050505050565b60003390506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610a0157600080fd5b505afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a399190612323565b90506000826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610a7657600080fd5b505afa158015610a8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aae9190612323565b90506000836001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b158015610aeb57600080fd5b505afa158015610aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b239190612570565b604051630b4c774160e11b81526001600160a01b038581166004830152848116602483015262ffffff831660448301529192507f000000000000000000000000000000000000000000000000000000000000000090911690631698ee829060640160206040518083038186803b158015610b9c57600080fd5b505afa158015610bb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd49190612323565b6001600160a01b0316336001600160a01b031614610c2b5760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a59081d5b9a5cddd85c081c1bdbdb60621b604482015260640161030a565b6000881315610c4d57610c486001600160a01b038416338a6117e7565b610c6a565b6000871315610c6a57610c6a6001600160a01b03831633896117e7565b5050505050505050565b6000806000806000808b6001600160a01b0316639894f21a8c8c6040518363ffffffff1660e01b8152600401610cb4929190918252602082015260400190565b60606040518083038186803b158015610ccc57600080fd5b505afa158015610ce0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0491906125ef565b925092509250888310158015610d1a5750878210155b610d365760405162461bcd60e51b815260040161030a906126c8565b8215610dc457610dc43330858f6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b505afa158015610d8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db39190612323565b6001600160a01b031692919061165b565b8115610e0957610e093330848f6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b610e168c8484848b61149a565b95509550955050505096509650969350505050565b6000806000806000808b6001600160a01b0316639894f21a8c8c6040518363ffffffff1660e01b8152600401610e6b929190918252602082015260400190565b60606040518083038186803b158015610e8357600080fd5b505afa158015610e97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebb91906125ef565b925092509250888310158015610ed15750878210155b610eed5760405162461bcd60e51b815260040161030a906126c8565b610f9a8c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2957600080fd5b505afa158015610f3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f619190612323565b8d6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561051157600080fd5b1561108357348b14610fbe5760405162461bcd60e51b815260040161030a906126f3565b8215611039577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0846040518263ffffffff1660e01b81526004016000604051808303818588803b15801561101f57600080fd5b505af1158015611033573d6000803e3d6000fd5b50505050505b811561107e5761107e3330848f6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b611162565b348a146110a25760405162461bcd60e51b815260040161030a906126f3565b811561111d577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561110357600080fd5b505af1158015611117573d6000803e3d6000fd5b50505050505b8215611162576111623330858f6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b61116f8c8484848b61149a565b8096508197508298505050506111b78c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2957600080fd5b156111dd57828b11156111d8576111d86111d1848d612765565b33906116cc565b6111f2565b818a11156111f2576111f26111d1838c612765565b50505096509650969350505050565b60008080871561124a5761124a33308a8c6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b861561128f5761128f3330898c6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b61129b89878787611c8f565b6000896001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156112d657600080fd5b505afa1580156112ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130e9190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016113399190612638565b60206040518083038186803b15801561135157600080fd5b505afa158015611365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113899190612593565b905060008a6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c657600080fd5b505afa1580156113da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fe9190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016114299190612638565b60206040518083038186803b15801561144157600080fd5b505afa158015611455573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114799190612593565b90506114868b8383611da7565b919d909c50909a5098505050505050505050565b60008080861561152a5761152a88888a6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156114e257600080fd5b505afa1580156114f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151a9190612323565b6001600160a01b03169190611edb565b851561156e5761156e88878a6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156114e257600080fd5b6040516394bf804d60e01b81526001600160a01b038916906394bf804d9061159c9088908890600401612736565b606060405180830381600087803b1580156115b657600080fd5b505af11580156115ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ee91906125ab565b509093509150868314801561160257508582145b61164d5760405162461bcd60e51b815260206004820152601c60248201527b1d5b995e1c1958dd195908185b5bdd5b9d1cc819195c1bdcda5d195960221b604482015260640161030a565b849050955095509592505050565b6040516001600160a01b03808516602483015283166044820152606481018290526116c69085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611f8a565b50505050565b8047101561171c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161030a565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611769576040519150601f19603f3d011682016040523d82523d6000602084013e61176e565b606091505b50509050806117e25760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c20726044820152791958da5c1a595b9d081b585e481a185d99481c995d995c9d195960321b606482015260840161030a565b505050565b6117e28363a9059cbb60e01b848460405160240161168f92919061264c565b6000806000806118b98a6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561184857600080fd5b505afa15801561185c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118809190612323565b8b6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561051157600080fd5b9050881561199e57801561195f573489146118e65760405162461bcd60e51b815260040161030a906126f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db08a6040518263ffffffff1660e01b81526004016000604051808303818588803b15801561194157600080fd5b505af1158015611955573d6000803e3d6000fd5b505050505061199e565b61199e33308b8d6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b8715611a825780156119ee576119e933308a8d6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7b57600080fd5b611a82565b348814611a0d5760405162461bcd60e51b815260040161030a906126f3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0896040518263ffffffff1660e01b81526004016000604051808303818588803b158015611a6857600080fd5b505af1158015611a7c573d6000803e3d6000fd5b50505050505b611a8e8a888888611c8f565b60008a6001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015611ac957600080fd5b505afa158015611add573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b019190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611b2c9190612638565b60206040518083038186803b158015611b4457600080fd5b505afa158015611b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7c9190612593565b905060008b6001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015611bb957600080fd5b505afa158015611bcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf19190612323565b6001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611c1c9190612638565b60206040518083038186803b158015611c3457600080fd5b505afa158015611c48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6c9190612593565b9050611c7a8c83838661205c565b919e909d50909b509950505050505050505050565b836001600160a01b03166316f0115b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cc857600080fd5b505afa158015611cdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d009190612323565b604051630251596160e31b81523060048201528415156024820152604481018490526001600160a01b03838116606483015260a06084830152600060a4830152919091169063128acb089060c4016040805180830381600087803b158015611d6757600080fd5b505af1158015611d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9f91906124d3565b505050505050565b604051634c4a790d60e11b81526004810183905260248101829052600090819081906001600160a01b03871690639894f21a9060440160606040518083038186803b158015611df557600080fd5b505afa158015611e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2d91906125ef565b9194509250905082851115611e8357611e8333611e4a8588612765565b886001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b81841115611ed257611ed233611e998487612765565b886001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b93509350939050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015611f2757600080fd5b505afa158015611f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5f9190612593565b611f69919061274d565b90506116c68463095ea7b360e01b858460405160240161168f92919061264c565b6000611fdf826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121a99092919063ffffffff16565b8051909150156117e25780806020019051810190611ffd9190612377565b6117e25760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161030a565b604051634c4a790d60e11b81526004810184905260248101839052600090819081906001600160a01b03881690639894f21a9060440160606040518083038186803b1580156120aa57600080fd5b505afa1580156120be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e291906125ef565b9194509250905082861180156120f6575083155b1561214757612142336121098589612765565b896001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b61219f565b81851180156121535750835b1561219f5761219f336121668488612765565b896001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156106f157600080fd5b9450945094915050565b60606121b884846000856121c2565b90505b9392505050565b6060824710156122235760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161030a565b843b6122715760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161030a565b600080866001600160a01b0316858760405161228d919061261c565b60006040518083038185875af1925050503d80600081146122ca576040519150601f19603f3d011682016040523d82523d6000602084013e6122cf565b606091505b50915091506122df8282866122ea565b979650505050505050565b606083156122f95750816121bb565b8251156123095782518084602001fd5b8160405162461bcd60e51b815260040161030a9190612665565b600060208284031215612334578081fd5b81516121bb816127be565b60008060408385031215612351578081fd5b823561235c816127be565b9150602083013561236c816127be565b809150509250929050565b600060208284031215612388578081fd5b81516121bb816127d6565b60008060008060008060008060006101208a8c0312156123b1578485fd5b89356123bc816127be565b985060208a0135975060408a0135965060608a01356123da816127d6565b955060808a0135945060a08a01356123f1816127be565b935060c08a0135925060e08a013591506101008a0135612410816127be565b809150509295985092959850929598565b600080600080600060a08688031215612438578081fd5b8535612443816127be565b94506020860135935060408601359250606086013591506080860135612468816127be565b809150509295509295909350565b60008060008060008060c0878903121561248e578384fd5b8635612499816127be565b95506020870135945060408701359350606087013592506080870135915060a08701356124c5816127be565b809150509295509295509295565b600080604083850312156124e5578182fd5b505080516020909101519092909150565b6000806000806060858703121561250b578182fd5b843593506020850135925060408501356001600160401b038082111561252f578384fd5b818701915087601f830112612542578384fd5b813581811115612550578485fd5b886020828501011115612561578485fd5b95989497505060200194505050565b600060208284031215612581578081fd5b815162ffffff811681146121bb578182fd5b6000602082840312156125a4578081fd5b5051919050565b6000806000606084860312156125bf578081fd5b83516020850151604086015191945092506001600160801b03811681146125e4578182fd5b809150509250925092565b600080600060608486031215612603578081fd5b8351925060208401519150604084015190509250925092565b6000825161262e81846020870161277c565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b602081526000825180602084015261268481604085016020870161277c565b601f01601f19169190910160400192915050565b60208082526016908201527572656365697665642062656c6f77206d696e696d756d60501b604082015260600190565b60208082526011908201527062656c6f77206d696e20616d6f756e747360781b604082015260600190565b60208082526023908201527f6d69736d61746368696e6720616d6f756e74206f662045544820666f7277617260408201526219195960ea1b606082015260800190565b9182526001600160a01b0316602082015260400190565b60008219821115612760576127606127a8565b500190565b600082821015612777576127776127a8565b500390565b60005b8381101561279757818101518382015260200161277f565b838111156116c65750506000910152565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03811681146127d357600080fd5b50565b80151581146127d357600080fdfea2646970667358221220987d503d23c5aa32673995d22b43a1c3936e75b7b4f6aee1b22686840194c48064736f6c63430008040033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/test/integration/arrakisUniswapV3AmmAdapter.spec.ts b/test/integration/arrakisUniswapV3AmmAdapter.spec.ts new file mode 100644 index 000000000..8323926e9 --- /dev/null +++ b/test/integration/arrakisUniswapV3AmmAdapter.spec.ts @@ -0,0 +1,506 @@ +import "module-alias/register"; + +import { network } from "hardhat"; +import { BigNumber } from "ethers"; +import { ether } from "@utils/index"; +import { Account } from "@utils/test/types"; +import { Address } from "@utils/types"; +import { + MAX_UINT_256, + ADDRESS_ZERO, + ZERO, +} from "@utils/constants"; +import { SetToken, AmmModule, ArrakisUniswapV3AmmAdapter } from "@utils/contracts"; +import DeployHelper from "@utils/deploys"; +import { + addSnapshotBeforeRestoreAfterEach, + getAccounts, + getSystemFixture, + getUniswapV3Fixture, + getArrakisV1Fixture, + getWaffleExpect +} from "@utils/test/index"; +import { SystemFixture, UniswapV3Fixture, ArrakisV1Fixture } from "@utils/fixtures"; + +const expect = getWaffleExpect(); + +describe("ArrakisUniswapV3AmmAdapter Integration [ @forked-mainnet ]", () => { + let owner: Account; + let deployer: DeployHelper; + let setup: SystemFixture; + let uniswapV3Setup: UniswapV3Fixture; + let arrakisV1Setup: ArrakisV1Fixture; + let ammModule: AmmModule; + let arrakisUniswapV3AmmAdapter: ArrakisUniswapV3AmmAdapter; + let arrakisUniswapV3AmmAdapterName: string; + + before(async () => { + await network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_TOKEN}`, + blockNumber: 15180700, + }, + }, + ], + }); + + [ + owner, + ] = await getAccounts(); + + deployer = new DeployHelper(owner.wallet); + setup = getSystemFixture(owner.address); + await setup.initialize(); + + uniswapV3Setup = getUniswapV3Fixture(owner.address); + await uniswapV3Setup.initialize( + owner, + setup.weth, + 2500, + setup.wbtc, + 35000, + setup.dai + ); + + arrakisV1Setup = getArrakisV1Fixture(owner.address); + await arrakisV1Setup.initialize(owner, uniswapV3Setup, setup.weth, 2500, setup.wbtc, 35000, setup.dai); + + ammModule = await deployer.modules.deployAmmModule(setup.controller.address); + await setup.controller.addModule(ammModule.address); + + arrakisUniswapV3AmmAdapter = await deployer.adapters.deployArrakisUniswapV3AmmAdapter( + arrakisV1Setup.router.address, + uniswapV3Setup.factory.address + ); + arrakisUniswapV3AmmAdapterName = "ARRAKISUNISWAPV3AMM"; + + await setup.integrationRegistry.addIntegration( + ammModule.address, + arrakisUniswapV3AmmAdapterName, + arrakisUniswapV3AmmAdapter.address + ); + }); + + addSnapshotBeforeRestoreAfterEach(); + + context("Add and Remove Liquidity Tests", async () => { + let subjectCaller: Account; + let subjectSetToken: Address; + let subjectIntegrationName: string; + let subjectAmmPool: Address; + + let setToken: SetToken; + + context("when there is a deployed SetToken with enabled AmmModule", async () => { + beforeEach(async () => { + // Deploy a standard SetToken with the AMM Module + setToken = await setup.createSetToken( + [setup.weth.address, setup.dai.address], + [ether(1), ether(2500)], + [setup.issuanceModule.address, ammModule.address] + ); + + await setup.issuanceModule.initialize(setToken.address, ADDRESS_ZERO); + await ammModule.initialize(setToken.address); + + // Mint some instances of the SetToken + await setup.approveAndIssueSetToken(setToken, ether(1)); + }); + + describe("#addLiquidity", async () => { + let subjectComponentsToInput: Address[]; + let subjectMaxComponentQuantities: BigNumber[]; + let subjectMinPoolTokensToMint: BigNumber; + + beforeEach(async () => { + subjectSetToken = setToken.address; + subjectIntegrationName = arrakisUniswapV3AmmAdapterName; + subjectAmmPool = arrakisV1Setup.wethDaiPool.address; + subjectComponentsToInput = [setup.weth.address, setup.dai.address]; + subjectMaxComponentQuantities = [ether(1), ether(2500)]; + subjectCaller = owner; + const orderedAmount = arrakisV1Setup.getOrderedAmount( + setup.weth.address, + setup.dai.address, + subjectMaxComponentQuantities[0], + subjectMaxComponentQuantities[1] + ); + const mintAmounts = await arrakisV1Setup.wethDaiPool.getMintAmounts( + orderedAmount[0], + orderedAmount[1] + ); + subjectMinPoolTokensToMint = mintAmounts[2]; + }); + + async function subject(): Promise { + return await ammModule.connect(subjectCaller.wallet).addLiquidity( + subjectSetToken, + subjectIntegrationName, + subjectAmmPool, + subjectMinPoolTokensToMint, + subjectComponentsToInput, + subjectMaxComponentQuantities, + ); + } + + it("should mint the liquidity token to the caller", async () => { + await subject(); + const liquidityTokenBalance = await arrakisV1Setup.wethDaiPool.balanceOf(subjectSetToken); + expect(liquidityTokenBalance).to.eq(subjectMinPoolTokensToMint); + }); + + it("should update the positions properly", async () => { + await subject(); + const positions = await setToken.getPositions(); + expect(positions.length).to.eq(3); + expect(positions[2].component).to.eq(subjectAmmPool); + expect(positions[2].unit).to.eq(subjectMinPoolTokensToMint); + }); + + describe("when insufficient liquidity tokens are received", async () => { + beforeEach(async () => { + subjectMinPoolTokensToMint = subjectMinPoolTokensToMint.mul(2); + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("_minLiquidity is too high for input token limit"); + }); + }); + + describe("when extra dai tokens are supplied", async () => { + let wethRemaining: BigNumber; + let daiRemaining: BigNumber; + beforeEach(async () => { + subjectMaxComponentQuantities = [ether(0.5), ether(1300)]; + + const orderedAmount = arrakisV1Setup.getOrderedAmount( + setup.weth.address, + setup.dai.address, + subjectMaxComponentQuantities[0], + subjectMaxComponentQuantities[1] + ); + const mintAmounts = await arrakisV1Setup.wethDaiPool.getMintAmounts( + orderedAmount[0], + orderedAmount[1] + ); + if (orderedAmount[2]) { + wethRemaining = ether(1).sub(mintAmounts[1]); + daiRemaining = ether(2500).sub(mintAmounts[0]); + } else { + wethRemaining = ether(1).sub(mintAmounts[0]); + daiRemaining = ether(2500).sub(mintAmounts[1]); + } + subjectMinPoolTokensToMint = mintAmounts[2]; + }); + + it("should mint the correct amount of liquidity tokens to the caller", async () => { + await subject(); + const liquidityTokenBalance = await arrakisV1Setup.wethDaiPool.balanceOf(subjectSetToken); + expect(liquidityTokenBalance).to.eq(subjectMinPoolTokensToMint); + }); + + it("should have the expected weth, dai, and lp tokens", async () => { + await subject(); + const positions = await setToken.getPositions(); + expect(positions.length).to.eq(3); + expect(positions[0].component).to.eq(setup.weth.address); + expect(positions[0].unit).to.eq(wethRemaining); + expect(positions[1].component).to.eq(setup.dai.address); + expect(positions[1].unit).to.eq(daiRemaining); + expect(positions[2].component).to.eq(subjectAmmPool); + expect(positions[2].unit).to.eq(subjectMinPoolTokensToMint); + }); + }); + + describe("when extra weth tokens are supplied", async () => { + let wethRemaining: BigNumber; + let daiRemaining: BigNumber; + beforeEach(async () => { + subjectMaxComponentQuantities = [ether(0.6), ether(1250)]; + + const orderedAmount = arrakisV1Setup.getOrderedAmount( + setup.weth.address, + setup.dai.address, + subjectMaxComponentQuantities[0], + subjectMaxComponentQuantities[1] + ); + const mintAmounts = await arrakisV1Setup.wethDaiPool.getMintAmounts( + orderedAmount[0], + orderedAmount[1] + ); + if (orderedAmount[2]) { + wethRemaining = ether(1).sub(mintAmounts[1]); + daiRemaining = ether(2500).sub(mintAmounts[0]); + } else { + wethRemaining = ether(1).sub(mintAmounts[0]); + daiRemaining = ether(2500).sub(mintAmounts[1]); + } + subjectMinPoolTokensToMint = mintAmounts[2]; + }); + + it("should mint the correct amount of liquidity tokens to the caller", async () => { + await subject(); + const liquidityTokenBalance = await arrakisV1Setup.wethDaiPool.balanceOf(subjectSetToken); + expect(liquidityTokenBalance).to.eq(subjectMinPoolTokensToMint); + }); + + it("should have the expected weth, dai, and lp tokens", async () => { + await subject(); + const positions = await setToken.getPositions(); + expect(positions.length).to.eq(3); + expect(positions[0].component).to.eq(setup.weth.address); + expect(positions[0].unit).to.eq(wethRemaining); + expect(positions[1].component).to.eq(setup.dai.address); + expect(positions[1].unit).to.eq(daiRemaining); + expect(positions[2].component).to.eq(subjectAmmPool); + expect(positions[2].unit).to.eq(subjectMinPoolTokensToMint); + }); + }); + + describe("when the pool token is not enabled on Adapter", async () => { + beforeEach(async () => { + subjectAmmPool = arrakisV1Setup.wethWbtcPool.address; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Pool token must be enabled on the Adapter"); + }); + }); + + describe("when the _components length is invalid", async () => { + beforeEach(async () => { + subjectComponentsToInput = [setup.weth.address]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Components and units must be equal length"); + }); + }); + + describe("when the _maxTokensIn length is invalid", async () => { + beforeEach(async () => { + subjectMaxComponentQuantities = [ether(1)]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Components and units must be equal length"); + }); + }); + + describe("when the _pool doesn't match the _components", async () => { + beforeEach(async () => { + subjectComponentsToInput = [setup.weth.address, setup.wbtc.address]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Pool token must be enabled on the Adapter"); + }); + }); + + describe("when the _maxTokensIn[0] is 0", async () => { + beforeEach(async () => { + subjectMaxComponentQuantities = [ether(0), ether(2500)]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Component quantity must be nonzero"); + }); + }); + + describe("when the _maxTokensIn[1] is 0", async () => { + beforeEach(async () => { + subjectMaxComponentQuantities = [ether(1), ether(0)]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Component quantity must be nonzero"); + }); + }); + + describe("when the _minLiquidity is 0", async () => { + beforeEach(async () => { + subjectMinPoolTokensToMint = ZERO; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Token quantity must be nonzero"); + }); + }); + + }); + + }); + + context("when there is a deployed SetToken with enabled AmmModule", async () => { + before(async () => { + // Mint some liquidity token + await setup.weth.connect(owner.wallet) + .approve(arrakisV1Setup.router.address, MAX_UINT_256); + await setup.dai.connect(owner.wallet) + .approve(arrakisV1Setup.router.address, MAX_UINT_256); + const amountOrdered = arrakisV1Setup.getOrderedAmount( + setup.weth.address, + setup.dai.address, + ether(200), + ether(500000) + ); + await arrakisV1Setup.router.connect(owner.wallet).addLiquidity( + arrakisV1Setup.wethDaiPool.address, + amountOrdered[0], + amountOrdered[1], + ether(0), + ether(0), + owner.address + ); + + // Deploy a standard SetToken with the AMM Module + setToken = await setup.createSetToken( + [arrakisV1Setup.wethDaiPool.address], + [ether(50)], + [setup.issuanceModule.address, ammModule.address] + ); + + await setup.issuanceModule.initialize(setToken.address, ADDRESS_ZERO); + await ammModule.initialize(setToken.address); + + // Mint some instances of the SetToken + await setup.approveAndIssueSetToken(setToken, ether(1)); + }); + + describe("#removeLiquidity", async () => { + let subjectComponentsToOutput: Address[]; + let subjectMinComponentQuantities: BigNumber[]; + let subjectPoolTokens: BigNumber; + + beforeEach(async () => { + subjectSetToken = setToken.address; + subjectIntegrationName = arrakisUniswapV3AmmAdapterName; + subjectAmmPool = arrakisV1Setup.wethDaiPool.address; + subjectComponentsToOutput = [setup.weth.address, setup.dai.address]; + subjectPoolTokens = ether(50); + subjectMinComponentQuantities = [ether(0.99), ether(2499)]; // slippage check + subjectCaller = owner; + }); + + async function subject(): Promise { + return await ammModule.connect(subjectCaller.wallet).removeLiquidity( + subjectSetToken, + subjectIntegrationName, + subjectAmmPool, + subjectPoolTokens, + subjectComponentsToOutput, + subjectMinComponentQuantities, + ); + } + + it("should reduce the liquidity token of the caller", async () => { + const previousLiquidityTokenBalance = await arrakisV1Setup.wethDaiPool.balanceOf(subjectSetToken); + + await subject(); + const liquidityTokenBalance = await arrakisV1Setup.wethDaiPool.balanceOf(subjectSetToken); + const expectedLiquidityBalance = previousLiquidityTokenBalance.sub(subjectPoolTokens); + expect(liquidityTokenBalance).to.eq(expectedLiquidityBalance); + }); + + it("should update the positions properly", async () => { + await subject(); + const positions = await setToken.getPositions(); + + expect(positions.length).to.eq(2); + expect(positions[0].component).to.eq(setup.weth.address); + expect(positions[0].unit).to.be.gt(subjectMinComponentQuantities[0]); + expect(positions[1].component).to.eq(setup.dai.address); + expect(positions[1].unit).to.be.gt(subjectMinComponentQuantities[1]); + + }); + + describe("when more underlying tokens are requested than owned", async () => { + beforeEach(async () => { + subjectMinComponentQuantities = [subjectMinComponentQuantities[0].mul(2), + subjectMinComponentQuantities[1]]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("received below minimum"); + }); + }); + + describe("when the pool address is invalid", async () => { + beforeEach(async () => { + subjectAmmPool = arrakisV1Setup.wethWbtcPool.address; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Pool token must be enabled on the Adapter"); + }); + }); + + describe("when the _components length is invalid", async () => { + beforeEach(async () => { + subjectComponentsToOutput = [setup.weth.address]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Components and units must be equal length"); + }); + }); + + describe("when the _minTokensOut length is invalid", async () => { + beforeEach(async () => { + subjectMinComponentQuantities = [ether(1)]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Components and units must be equal length"); + }); + }); + + describe("when the _pool doesn't match the _components", async () => { + beforeEach(async () => { + subjectComponentsToOutput = [setup.weth.address, setup.wbtc.address]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Pool token must be enabled on the Adapter"); + }); + }); + + describe("when the _minTokensOut[0] is 0", async () => { + beforeEach(async () => { + subjectMinComponentQuantities = [ether(0), ether(2499)]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Component quantity must be nonzero"); + }); + }); + + describe("when the _minTokensOut[1] is 0", async () => { + beforeEach(async () => { + subjectMinComponentQuantities = [ether(0.99), ether(0)]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Component quantity must be nonzero"); + }); + }); + + describe("when the _liquidity is 0", async () => { + beforeEach(async () => { + subjectPoolTokens = ZERO; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Token quantity must be nonzero"); + }); + }); + + }); + + }); + }); + +}); diff --git a/test/protocol/integration/amm/ArrakisUniswapV3AmmAdapter.spec.ts b/test/protocol/integration/amm/ArrakisUniswapV3AmmAdapter.spec.ts new file mode 100644 index 000000000..8f3a53b2b --- /dev/null +++ b/test/protocol/integration/amm/ArrakisUniswapV3AmmAdapter.spec.ts @@ -0,0 +1,346 @@ +import "module-alias/register"; +import { BigNumber } from "ethers"; +import { ether } from "@utils/index"; +import { Account } from "@utils/test/types"; +import { Address } from "@utils/types"; +import { + ZERO, +} from "@utils/constants"; +import { ArrakisUniswapV3AmmAdapter } from "@utils/contracts"; +import DeployHelper from "@utils/deploys"; +import { + addSnapshotBeforeRestoreAfterEach, + getAccounts, + getSystemFixture, + getUniswapV3Fixture, + getArrakisV1Fixture, + getWaffleExpect +} from "@utils/test/index"; + +import { SystemFixture, UniswapV3Fixture, ArrakisV1Fixture } from "@utils/fixtures"; + +const expect = getWaffleExpect(); + +describe("ArrakisUniswapV3AmmAdapter", () => { + let owner: Account; + let deployer: DeployHelper; + let setup: SystemFixture; + let uniswapV3Setup: UniswapV3Fixture; + let arrakisV1Setup: ArrakisV1Fixture; + let arrakisUniswapV3AmmAdapter: ArrakisUniswapV3AmmAdapter; + + before(async () => { + [ + owner, + ] = await getAccounts(); + + deployer = new DeployHelper(owner.wallet); + setup = getSystemFixture(owner.address); + await setup.initialize(); + + uniswapV3Setup = getUniswapV3Fixture(owner.address); + await uniswapV3Setup.initialize( + owner, + setup.weth, + 2500, + setup.wbtc, + 35000, + setup.dai + ); + + arrakisV1Setup = getArrakisV1Fixture(owner.address); + await arrakisV1Setup.initialize(owner, uniswapV3Setup, setup.weth, 2500, setup.wbtc, 35000, setup.dai); + + arrakisUniswapV3AmmAdapter = await deployer.adapters.deployArrakisUniswapV3AmmAdapter( + arrakisV1Setup.router.address, + uniswapV3Setup.factory.address + ); + }); + + addSnapshotBeforeRestoreAfterEach(); + + describe("constructor", async () => { + async function subject(): Promise { + return await deployer.adapters.deployArrakisUniswapV3AmmAdapter( + arrakisV1Setup.router.address, + uniswapV3Setup.factory.address + ); + } + + it("should have the correct router address", async () => { + const deployedArrakisUniswapV3AmmAdapter = await subject(); + + const actualRouterAddress = await deployedArrakisUniswapV3AmmAdapter.router(); + expect(actualRouterAddress).to.eq(arrakisV1Setup.router.address); + }); + + it("should have the correct uniswapV3 factory address", async () => { + const deployedArrakisUniswapV3AmmAdapter = await subject(); + + const actualUniV3FactoryAddress = await deployedArrakisUniswapV3AmmAdapter.uniV3Factory(); + expect(actualUniV3FactoryAddress).to.eq(uniswapV3Setup.factory.address); + }); + }); + + describe("getSpenderAddress", async () => { + let poolAddress: Address; + + before(async () => { + poolAddress = arrakisV1Setup.wethDaiPool.address; + }); + + async function subject(): Promise { + return await arrakisUniswapV3AmmAdapter.getSpenderAddress(poolAddress); + } + + it("should return the correct spender address", async () => { + const spender = await subject(); + expect(spender).to.eq(arrakisV1Setup.router.address); + }); + }); + + describe("isValidPool", async () => { + let subjectAmmPool: Address; + let subjectComponents: Address[]; + + beforeEach(async () => { + subjectAmmPool = arrakisV1Setup.wethDaiPool.address; + subjectComponents = [setup.weth.address, setup.dai.address]; + }); + + async function subject(): Promise { + return await arrakisUniswapV3AmmAdapter.isValidPool(subjectAmmPool, subjectComponents); + } + + it("should be a valid pool", async () => { + const status = await subject(); + expect(status).to.be.true; + }); + + describe("when the pool address is invalid", async () => { + beforeEach(async () => { + subjectAmmPool = setup.weth.address; + }); + + it("should be an invalid pool", async () => { + const status = await subject(); + expect(status).to.be.false; + }); + }); + + describe("when the components don't match", async () => { + beforeEach(async () => { + subjectComponents = [setup.weth.address, setup.wbtc.address]; + }); + + it("should be an invalid pool", async () => { + const status = await subject(); + expect(status).to.be.false; + }); + }); + + describe("when the number of components is incorrect", async () => { + beforeEach(async () => { + subjectComponents = [setup.weth.address]; + }); + + it("should be an invalid pool", async () => { + const status = await subject(); + expect(status).to.be.false; + }); + }); + + describe("when the pool address is not an ERC20", async () => { + beforeEach(async () => { + subjectAmmPool = uniswapV3Setup.wethDaiPool.address; + }); + + it("should be an invalid pool", async () => { + const status = await subject(); + expect(status).to.be.false; + }); + }); + + }); + + describe("getProvideLiquiditySingleAssetCalldata", async () => { + let subjectAmmPool: Address; + let subjectComponent: Address; + let subjectMaxTokenIn: BigNumber; + let subjectMinLiquidity: BigNumber; + + before(async () => { + subjectAmmPool = arrakisV1Setup.wethDaiPool.address; + subjectComponent = setup.weth.address; + subjectMaxTokenIn = ether(1); + subjectMinLiquidity = ether(1); + }); + + async function subject(): Promise { + return await arrakisUniswapV3AmmAdapter.getProvideLiquiditySingleAssetCalldata( + owner.address, + subjectAmmPool, + subjectComponent, + subjectMaxTokenIn, + subjectMinLiquidity); + } + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Arrakis single asset addition is not supported"); + }); + }); + + describe("getRemoveLiquiditySingleAssetCalldata", async () => { + let subjectAmmPool: Address; + let subjectComponent: Address; + let subjectMinTokenOut: BigNumber; + let subjectLiquidity: BigNumber; + + before(async () => { + subjectAmmPool = uniswapV3Setup.wethDaiPool.address; + subjectComponent = setup.weth.address; + subjectMinTokenOut = ether(1); + subjectLiquidity = ether(1); + }); + + async function subject(): Promise { + return await arrakisUniswapV3AmmAdapter.getRemoveLiquiditySingleAssetCalldata( + owner.address, + subjectAmmPool, + subjectComponent, + subjectMinTokenOut, + subjectLiquidity); + } + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Arrakis single asset removal is not supported"); + }); + }); + + describe("getProvideLiquidityCalldata", async () => { + let subjectAmmPool: Address; + let subjectComponents: Address[]; + let subjectMaxTokensIn: BigNumber[]; + let subjectMinLiquidity: BigNumber; + + beforeEach(async () => { + subjectAmmPool = arrakisV1Setup.wethDaiPool.address; + subjectComponents = [setup.weth.address, setup.dai.address]; + subjectMaxTokensIn = [ether(1), ether(3000)]; + const orderedMaxTokensIn = arrakisV1Setup.getOrderedAmount( + setup.weth.address, + setup.dai.address, + subjectMaxTokensIn[0], + subjectMaxTokensIn[1] + ); + const mintAmount = await arrakisV1Setup.wethDaiPool.getMintAmounts(orderedMaxTokensIn[0], orderedMaxTokensIn[1]); + subjectMinLiquidity = mintAmount[2]; + }); + + async function subject(): Promise { + return await arrakisUniswapV3AmmAdapter.getProvideLiquidityCalldata( + owner.address, + subjectAmmPool, + subjectComponents, + subjectMaxTokensIn, + subjectMinLiquidity); + } + + it("should return the correct provide liquidity calldata", async () => { + const calldata = await subject(); + + // Determine how much of each token the _minLiquidity would return + const orderedMaxTokensIn = arrakisV1Setup.getOrderedAmount( + setup.weth.address, + setup.dai.address, + subjectMaxTokensIn[0], + subjectMaxTokensIn[1] + ); + const mintAmount = await arrakisV1Setup.wethDaiPool.getMintAmounts(orderedMaxTokensIn[0], orderedMaxTokensIn[1]); + const amountAMin = mintAmount[0]; + const amountBMin = mintAmount[1]; + + const expectedCallData = arrakisV1Setup.router.interface.encodeFunctionData("addLiquidity", [ + subjectAmmPool, + orderedMaxTokensIn[0], + orderedMaxTokensIn[1], + amountAMin, + amountBMin, + owner.address + ]); + expect(JSON.stringify(calldata)).to.eq(JSON.stringify([arrakisV1Setup.router.address, ZERO, expectedCallData])); + }); + + describe("when the either of the _maxTokensIn is zero", async () => { + beforeEach(async () => { + subjectMaxTokensIn = [ZERO, ether(3000)]; + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Component quantity must be nonzero"); + }); + }); + + describe("when the _minLiquidity is too high", async () => { + beforeEach(async () => { + subjectMinLiquidity = subjectMinLiquidity.mul(2); + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("_minLiquidity is too high for input token limit"); + }); + }); + }); + + describe("getRemoveLiquidityCalldata", async () => { + let subjectAmmPool: Address; + let subjectComponents: Address[]; + let subjectMinTokensOut: BigNumber[]; + let subjectLiquidity: BigNumber; + + beforeEach(async () => { + subjectAmmPool = arrakisV1Setup.wethDaiPool.address; + subjectComponents = [setup.weth.address, setup.dai.address]; + subjectLiquidity = await arrakisV1Setup.wethDaiPool.balanceOf(owner.address); + subjectMinTokensOut = [ether(1), ether(3000)]; + }); + + async function subject(): Promise { + return await arrakisUniswapV3AmmAdapter.getRemoveLiquidityCalldata( + owner.address, + subjectAmmPool, + subjectComponents, + subjectMinTokensOut, + subjectLiquidity); + } + + it("should return the correct remove liquidity calldata", async () => { + const calldata = await subject(); + const orderedMinTokensOut = arrakisV1Setup.getOrderedAmount( + setup.weth.address, + setup.dai.address, + subjectMinTokensOut[0], + subjectMinTokensOut[1] + ); + const expectedCallData = arrakisV1Setup.router.interface.encodeFunctionData("removeLiquidity", [ + subjectAmmPool, + subjectLiquidity, + orderedMinTokensOut[0], + orderedMinTokensOut[1], + owner.address + ]); + expect(JSON.stringify(calldata)).to.eq(JSON.stringify([arrakisV1Setup.router.address, ZERO, expectedCallData])); + }); + + describe("when the _liquidity is more than available", async () => { + beforeEach(async () => { + subjectLiquidity = (await arrakisV1Setup.wethDaiPool.balanceOf(owner.address)).add(ether(1)); + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("_liquidity must be <= to current balance"); + }); + }); + }); + +}); diff --git a/utils/contracts/arrakis.ts b/utils/contracts/arrakis.ts new file mode 100644 index 000000000..7c1315f92 --- /dev/null +++ b/utils/contracts/arrakis.ts @@ -0,0 +1,4 @@ +// External Arrakis/Gelato contracts +export { ArrakisFactoryV1 } from "../../typechain/ArrakisFactoryV1"; +export { ArrakisVaultV1 } from "../../typechain/ArrakisVaultV1"; +export { GUniRouter } from "../../typechain/GUniRouter"; \ No newline at end of file diff --git a/utils/contracts/index.ts b/utils/contracts/index.ts index 593889b16..915e92668 100644 --- a/utils/contracts/index.ts +++ b/utils/contracts/index.ts @@ -9,6 +9,7 @@ export { AddressArrayUtilsMock } from "../../typechain/AddressArrayUtilsMock"; export { AirdropModule } from "../../typechain/AirdropModule"; export { AmmAdapterMock } from "../../typechain/AmmAdapterMock"; export { AmmModule } from "../../typechain/AmmModule"; +export { ArrakisUniswapV3AmmAdapter } from "../../typechain/ArrakisUniswapV3AmmAdapter"; export { AssetLimitHook } from "../../typechain/AssetLimitHook"; export { BalancerV1IndexExchangeAdapter } from "../../typechain/BalancerV1IndexExchangeAdapter"; export { BasicIssuanceModule } from "../../typechain/BasicIssuanceModule"; diff --git a/utils/deploys/deployAdapters.ts b/utils/deploys/deployAdapters.ts index 72af8e9d1..70e3d98f0 100644 --- a/utils/deploys/deployAdapters.ts +++ b/utils/deploys/deployAdapters.ts @@ -3,6 +3,7 @@ import { BigNumber, Signer } from "ethers"; import { AaveGovernanceV2Adapter, AaveV2WrapV2Adapter, + ArrakisUniswapV3AmmAdapter, BalancerV1IndexExchangeAdapter, CompoundLikeGovernanceAdapter, CurveExchangeAdapter, @@ -33,6 +34,7 @@ import { Address, Bytes } from "./../types"; import { AaveGovernanceV2Adapter__factory } from "../../typechain/factories/AaveGovernanceV2Adapter__factory"; import { AaveV2WrapV2Adapter__factory } from "../../typechain/factories/AaveV2WrapV2Adapter__factory"; +import { ArrakisUniswapV3AmmAdapter__factory } from "../../typechain/factories/ArrakisUniswapV3AmmAdapter__factory"; import { BalancerV1IndexExchangeAdapter__factory } from "../../typechain/factories/BalancerV1IndexExchangeAdapter__factory"; import { CompoundLikeGovernanceAdapter__factory } from "../../typechain/factories/CompoundLikeGovernanceAdapter__factory"; import { CurveExchangeAdapter__factory } from "../../typechain/factories/CurveExchangeAdapter__factory"; @@ -88,6 +90,13 @@ export default class DeployAdapters { return await new UniswapV2AmmAdapter__factory(this._deployerSigner).deploy(uniswapV2Router); } + public async deployArrakisUniswapV3AmmAdapter( + arrakisRouter: Address, + uniswapV3Factory: Address + ): Promise { + return await new ArrakisUniswapV3AmmAdapter__factory(this._deployerSigner).deploy(arrakisRouter, uniswapV3Factory); + } + public async deployUniswapV2ExchangeAdapter( uniswapV2Router: Address, ): Promise { diff --git a/utils/deploys/deployExternal.ts b/utils/deploys/deployExternal.ts index 0ef99cfbd..b2693ac49 100644 --- a/utils/deploys/deployExternal.ts +++ b/utils/deploys/deployExternal.ts @@ -203,6 +203,15 @@ import { PerpV2InsuranceFund__factory } from "../../typechain/factories/PerpV2In import { PerpV2AccountBalance__factory } from "../../typechain/factories/PerpV2AccountBalance__factory"; import { PerpV2Exchange__factory } from "../../typechain/factories/PerpV2Exchange__factory"; +import { + GUniRouter, + ArrakisFactoryV1, + ArrakisVaultV1 +} from "../contracts/arrakis"; +import { ArrakisFactoryV1__factory } from "../../typechain/factories/ArrakisFactoryV1__factory"; +import { ArrakisVaultV1__factory } from "../../typechain/factories/ArrakisVaultV1__factory"; +import { GUniRouter__factory } from "../../typechain/factories/GUniRouter__factory"; + export default class DeployExternalContracts { private _deployerSigner: Signer; @@ -740,4 +749,21 @@ export default class DeployExternalContracts { public async getVToken(token: Address): Promise { return await new PerpV2BaseToken__factory(this._deployerSigner).attach(token); } + + // Arrakis/Gelato + public async deployArrakisFactoryV1(uniswapV3factory: Address): Promise { + return await new ArrakisFactoryV1__factory(this._deployerSigner).deploy(uniswapV3factory); + } + + public async deployGUniRouter(uniswapV3factory: Address, weth: Address): Promise { + return await new GUniRouter__factory(this._deployerSigner).deploy(uniswapV3factory, weth); + } + + public async deployArrakisVaultV1(_gelato: Address, _arrakisTreasury: Address): Promise { + return await new ArrakisVaultV1__factory(this._deployerSigner).deploy(_gelato, _arrakisTreasury); + } + + public async getArrakisVaultV1Instance(pool: Address): Promise { + return await new ArrakisVaultV1__factory(this._deployerSigner).attach(pool); + } } diff --git a/utils/fixtures/arrakisV1Fixture.ts b/utils/fixtures/arrakisV1Fixture.ts new file mode 100644 index 000000000..dbd22cf80 --- /dev/null +++ b/utils/fixtures/arrakisV1Fixture.ts @@ -0,0 +1,137 @@ +import DeployHelper from "../deploys"; +import { Signer, providers, BigNumber } from "ethers"; +import { Address } from "../types"; +import { Account } from "../test/types"; + +import { + ArrakisFactoryV1, + GUniRouter, + ArrakisVaultV1 +} from "../contracts/arrakis"; + +import { UniswapV3Fixture } from "@utils/fixtures"; +import { StandardTokenMock } from "../../typechain/StandardTokenMock"; +import { WETH9 } from "../../typechain/WETH9"; + +type Token = StandardTokenMock | WETH9; + +export class ArrakisV1Fixture { + + private _deployer: DeployHelper; + private _ownerSigner: Signer; + + public factory: ArrakisFactoryV1; + public router: GUniRouter; + + public wethDaiPool: ArrakisVaultV1; + public wethWbtcPool: ArrakisVaultV1; + + /** + * Instantiates a new ArrakisFixture + * + * @param provider the ethers web3 provider to use + * @param ownerAddress the address of the owner + */ + constructor(provider: providers.Web3Provider | providers.JsonRpcProvider, ownerAddress: Address) { + this._ownerSigner = provider.getSigner(ownerAddress); + this._deployer = new DeployHelper(this._ownerSigner); + } + + /** + * Deploys contracts and creates weth-dai and weth-wbtc arrakis pools + * + * @param _owner the owner of the deployed Arrakis system + * @param _uniswapV3Factory uniswapV3 factory address + * @param _weth weth address + * @param _wethPrice weth price + * @param _wbtc wbtc address + * @param _wbtcPrice wbtc price + * @param _dai dai address + */ + public async initialize( + _owner: Account, + _uniswapV3Setup: UniswapV3Fixture, + _weth: Token, + _wethPrice: number, + _wbtc: Token, + _wbtcPrice: number, + _dai: Token + ): Promise { + await this.deployVaultAndFactoryAndinitialize(_owner, _uniswapV3Setup); + this.router = await this._deployer.external.deployGUniRouter(_uniswapV3Setup.factory.address, _weth.address); + + this.wethDaiPool = await this.createNewPair(_owner, _uniswapV3Setup, _weth, _dai, 3000, _wethPrice); + this.wethWbtcPool = await this.createNewPair(_owner, _uniswapV3Setup, _weth, _wbtc, 3000, _wethPrice / _wbtcPrice); + } + + /** + * Creates and initializes a new arrakis factory + * + * @param _owner the owner of the deployed Arrakis system + * @param _uniswapV3Setup uniswapV3Fixture + * @returns void promise + */ + public async deployVaultAndFactoryAndinitialize( + _owner: Account, + _uniswapV3Setup: UniswapV3Fixture + ): Promise { + const vaultImplementation = await this._deployer.external.deployArrakisVaultV1(_owner.address, _owner.address); + this.factory = await this._deployer.external.deployArrakisFactoryV1(_uniswapV3Setup.factory.address); + await this.factory.initialize(vaultImplementation.address, _owner.address); + } + + /** + * Creates and initializes a new arrakis vault pool + * + * @param _owner the owner of the deployed Arrakis system + * @param _uniswapV3Setup uniswapV3Fixture + * @param _token0 first token + * @param _token1 second token + * @param _fee fee tier of either 500, 3000, or 10000 + * @param _ratio the initial price ratio of the pool equal to priceToken0 / priceToken1 + * @returns a new Arrakis Vault holding UniswapV3 position on given tokens + */ + public async createNewPair( + _owner: Account, + _uniswapV3Setup: UniswapV3Fixture, + _token0: Token, + _token1: Token, + _fee: number, + _ratio: number, + ): Promise { + await _uniswapV3Setup.createNewPair(_token0, _token1, _fee, _ratio); + + const tickSpacing = _fee / 50; // ticks can only be initialized if they are a multiple of fee / 50 + const maxTick = 887272; // the maximum tick index that Uniswap V3 allows + const maxValidTick = Math.floor(maxTick / tickSpacing) * tickSpacing; // valid ticks must be a multiple of tickSpacing + const minValidTick = Math.ceil(-maxTick / tickSpacing) * tickSpacing; + + const txReceipt = await ( + await this.factory.deployVault( + _token0.address, + _token1.address, + _fee, + _owner.address, + 0, + minValidTick, + maxValidTick + ) + ).wait(); + + const poolAddress = txReceipt.events![2].args!.pool; + return this._deployer.external.getArrakisVaultV1Instance(poolAddress); + } + + /** + * Sorts token amounts in order of token address + * + * @param _tokenOne first token address + * @param _tokenTwo second token address + * @param _amountOne first token amount + * @param _amountTwo second token amount + * @returns amounts sorted in order of token address + */ + public getOrderedAmount(_tokenOne: Address, _tokenTwo: Address, _amountOne: BigNumber, _amountTwo: BigNumber): [BigNumber, BigNumber, boolean] { + return _tokenOne.toLowerCase() < _tokenTwo.toLowerCase() ? [_amountOne, _amountTwo, false] : [_amountTwo, _amountOne, true]; + } +} diff --git a/utils/fixtures/index.ts b/utils/fixtures/index.ts index e390db2c4..8eca9ae0d 100644 --- a/utils/fixtures/index.ts +++ b/utils/fixtures/index.ts @@ -8,3 +8,4 @@ export { UniswapFixture } from "./uniswapFixture"; export { UniswapV3Fixture } from "./uniswapV3Fixture"; export { YearnFixture } from "./yearnFixture"; export { PerpV2Fixture } from "./perpV2Fixture"; +export { ArrakisV1Fixture } from "./arrakisV1Fixture"; diff --git a/utils/test/index.ts b/utils/test/index.ts index 3cb59708d..eabd42661 100644 --- a/utils/test/index.ts +++ b/utils/test/index.ts @@ -12,7 +12,8 @@ import { UniswapFixture, YearnFixture, UniswapV3Fixture, - PerpV2Fixture + PerpV2Fixture, + ArrakisV1Fixture } from "../fixtures"; import { Blockchain, ProtocolUtils } from "../common"; @@ -30,6 +31,7 @@ export const getUniswapFixture = (ownerAddress: Address) => new UniswapFixture(p export const getYearnFixture = (ownerAddress: Address) => new YearnFixture(provider, ownerAddress); export const getUniswapV3Fixture = (ownerAddress: Address) => new UniswapV3Fixture(provider, ownerAddress); export const getPerpV2Fixture = (ownerAddress: Address) => new PerpV2Fixture(provider, ownerAddress); +export const getArrakisV1Fixture = (ownerAddress: Address) => new ArrakisV1Fixture(provider, ownerAddress); export { ForkedTokens } from "./types";