From 102be3a91c8bc428b58d966ff87e6a004dfb38bb Mon Sep 17 00:00:00 2001 From: cryptoDev222 Date: Fri, 8 Oct 2021 14:21:02 -0500 Subject: [PATCH 01/31] implement sushi connector --- .../mainnet/connectors/sushiswap/events.sol | 41 ++++ .../mainnet/connectors/sushiswap/helpers.sol | 184 +++++++++++++++ .../connectors/sushiswap/interface.sol | 57 +++++ .../mainnet/connectors/sushiswap/main.sol | 196 ++++++++++++++++ test/sushiswap/sushiswap.test.js | 217 ++++++++++++++++++ 5 files changed, 695 insertions(+) create mode 100644 contracts/mainnet/connectors/sushiswap/events.sol create mode 100644 contracts/mainnet/connectors/sushiswap/helpers.sol create mode 100644 contracts/mainnet/connectors/sushiswap/interface.sol create mode 100644 contracts/mainnet/connectors/sushiswap/main.sol create mode 100644 test/sushiswap/sushiswap.test.js diff --git a/contracts/mainnet/connectors/sushiswap/events.sol b/contracts/mainnet/connectors/sushiswap/events.sol new file mode 100644 index 00000000..2717b0a3 --- /dev/null +++ b/contracts/mainnet/connectors/sushiswap/events.sol @@ -0,0 +1,41 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDepositLiquidity( + address indexed tokenA, + address indexed tokenB, + uint256 amtA, + uint256 amtB, + uint256 uniAmount, + uint256 getId, + uint256 setId + ); + + event LogWithdrawLiquidity( + address indexed tokenA, + address indexed tokenB, + uint256 amountA, + uint256 amountB, + uint256 uniAmount, + uint256 getId, + uint256[] setId + ); + + event LogBuy( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/sushiswap/helpers.sol b/contracts/mainnet/connectors/sushiswap/helpers.sol new file mode 100644 index 00000000..a1baa4c5 --- /dev/null +++ b/contracts/mainnet/connectors/sushiswap/helpers.sol @@ -0,0 +1,184 @@ +pragma solidity ^0.7.0; + +import {TokenInterface} from "../../common/interfaces.sol"; +import {DSMath} from "../../common/math.sol"; +import {Basic} from "../../common/basic.sol"; +import {ISushiSwapRouter, ISushiSwapFactory} from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev ISushiSwapRouter + */ + ISushiSwapRouter internal constant router = + ISushiSwapRouter(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); + + function getExpectedBuyAmt(address[] memory paths, uint256 sellAmt) + internal + view + returns (uint256 buyAmt) + { + uint256[] memory amts = router.getAmountsOut(sellAmt, paths); + buyAmt = amts[1]; + } + + function getExpectedSellAmt(address[] memory paths, uint256 buyAmt) + internal + view + returns (uint256 sellAmt) + { + uint256[] memory amts = router.getAmountsIn(buyAmt, paths); + sellAmt = amts[0]; + } + + function checkPair(address[] memory paths) internal view { + address pair = ISushiSwapFactory(router.factory()).getPair( + paths[0], + paths[1] + ); + require(pair != address(0), "No-exchange-address"); + } + + function getPaths(address buyAddr, address sellAddr) + internal + pure + returns (address[] memory paths) + { + paths = new address[](2); + paths[0] = address(sellAddr); + paths[1] = address(buyAddr); + } + + function getMinAmount( + TokenInterface token, + uint256 amt, + uint256 slippage + ) internal view returns (uint256 minAmt) { + uint256 _amt18 = convertTo18(token.decimals(), amt); + minAmt = wmul(_amt18, sub(WAD, slippage)); + minAmt = convert18ToDec(token.decimals(), minAmt); + } + + function _addLiquidity( + address tokenA, + address tokenB, + uint256 _amt, + uint256 unitAmt, + uint256 slippage + ) + internal + returns ( + uint256 _amtA, + uint256 _amtB, + uint256 _liquidity + ) + { + (TokenInterface _tokenA, TokenInterface _tokenB) = changeEthAddress( + tokenA, + tokenB + ); + + _amtA = _amt == uint256(-1) + ? getTokenBal(TokenInterface(tokenA)) + : _amt; + _amtB = convert18ToDec( + _tokenB.decimals(), + wmul(unitAmt, convertTo18(_tokenA.decimals(), _amtA)) + ); + + bool isEth = address(_tokenA) == wethAddr; + convertEthToWeth(isEth, _tokenA, _amtA); + + isEth = address(_tokenB) == wethAddr; + convertEthToWeth(isEth, _tokenB, _amtB); + + approve(_tokenA, address(router), _amtA); + approve(_tokenB, address(router), _amtB); + + uint256 minAmtA = getMinAmount(_tokenA, _amtA, slippage); + uint256 minAmtB = getMinAmount(_tokenB, _amtB, slippage); + (_amtA, _amtB, _liquidity) = router.addLiquidity( + address(_tokenA), + address(_tokenB), + _amtA, + _amtB, + minAmtA, + minAmtA, + address(this), + block.timestamp + 1 + ); + } + + function _removeLiquidity( + address tokenA, + address tokenB, + uint256 _amt, + uint256 unitAmtA, + uint256 unitAmtB + ) + internal + returns ( + uint256 _amtA, + uint256 _amtB, + uint256 _uniAmt + ) + { + TokenInterface _tokenA; + TokenInterface _tokenB; + (_tokenA, _tokenB, _uniAmt) = _getRemoveLiquidityData( + tokenA, + tokenB, + _amt + ); + { + uint256 minAmtA = convert18ToDec( + _tokenA.decimals(), + wmul(unitAmtA, _uniAmt) + ); + uint256 minAmtB = convert18ToDec( + _tokenB.decimals(), + wmul(unitAmtB, _uniAmt) + ); + (_amtA, _amtB) = router.removeLiquidity( + address(_tokenA), + address(_tokenB), + _uniAmt, + minAmtA, + minAmtB, + address(this), + block.timestamp + 1 + ); + } + + bool isEth = address(_tokenA) == wethAddr; + convertWethToEth(isEth, _tokenA, _amtA); + + isEth = address(_tokenB) == wethAddr; + convertWethToEth(isEth, _tokenB, _amtB); + } + + function _getRemoveLiquidityData( + address tokenA, + address tokenB, + uint256 _amt + ) + internal + returns ( + TokenInterface _tokenA, + TokenInterface _tokenB, + uint256 _uniAmt + ) + { + (_tokenA, _tokenB) = changeEthAddress(tokenA, tokenB); + address exchangeAddr = ISushiSwapFactory(router.factory()).getPair( + address(_tokenA), + address(_tokenB) + ); + require(exchangeAddr != address(0), "pair-not-found."); + + TokenInterface uniToken = TokenInterface(exchangeAddr); + _uniAmt = _amt == uint256(-1) + ? uniToken.balanceOf(address(this)) + : _amt; + approve(uniToken, address(router), _uniAmt); + } +} diff --git a/contracts/mainnet/connectors/sushiswap/interface.sol b/contracts/mainnet/connectors/sushiswap/interface.sol new file mode 100644 index 00000000..bd3be483 --- /dev/null +++ b/contracts/mainnet/connectors/sushiswap/interface.sol @@ -0,0 +1,57 @@ +pragma solidity ^0.7.0; + +interface ISushiSwapRouter { + function factory() external pure returns (address); + function WETH() external pure returns (address); + + function addLiquidity( + address tokenA, + address tokenB, + uint amountADesired, + uint amountBDesired, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB, uint liquidity); + function removeLiquidity( + address tokenA, + address tokenB, + uint liquidity, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB); + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + function swapTokensForExactTokens( + uint amountOut, + uint amountInMax, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + + function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); + function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); + function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); + function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); + function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); +} + +interface ISushiSwapFactory { + function getPair(address tokenA, address tokenB) external view returns (address pair); + function allPairs(uint) external view returns (address pair); + function allPairsLength() external view returns (uint); + + function feeTo() external view returns (address); + function feeToSetter() external view returns (address); + + function createPair(address tokenA, address tokenB) external returns (address pair); +} diff --git a/contracts/mainnet/connectors/sushiswap/main.sol b/contracts/mainnet/connectors/sushiswap/main.sol new file mode 100644 index 00000000..bd0078bc --- /dev/null +++ b/contracts/mainnet/connectors/sushiswap/main.sol @@ -0,0 +1,196 @@ +pragma solidity ^0.7.0; + +/** + * @title SushiSwap. + * @dev Decentralized Exchange. + */ + +import { TokenInterface } from "../../common/interfaces.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract SushipswapResolver is Helpers, Events { + /** + * @dev Deposit Liquidity. + * @notice Deposit Liquidity to a SushiSwap pool. + * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amtA The amount of A tokens to deposit. + * @param unitAmt The unit amount of of amtB/amtA with slippage. + * @param slippage Slippage amount. + * @param getId ID to retrieve amtA. + * @param setId ID stores the amount of pools tokens received. + */ + function deposit( + address tokenA, + address tokenB, + uint256 amtA, + uint256 unitAmt, + uint256 slippage, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amtA); + + (uint _amtA, uint _amtB, uint _uniAmt) = _addLiquidity( + tokenA, + tokenB, + _amt, + unitAmt, + slippage + ); + setUint(setId, _uniAmt); + + _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setId); + } + + /** + * @dev Withdraw Liquidity. + * @notice Withdraw Liquidity from a SushiSwap pool. + * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param uniAmt The amount of pool tokens to withdraw. + * @param unitAmtA The unit amount of amtA/uniAmt with slippage. + * @param unitAmtB The unit amount of amtB/uniAmt with slippage. + * @param getId ID to retrieve uniAmt. + * @param setIds Array of IDs to store the amount tokens received. + */ + function withdraw( + address tokenA, + address tokenB, + uint256 uniAmt, + uint256 unitAmtA, + uint256 unitAmtB, + uint256 getId, + uint256[] calldata setIds + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, uniAmt); + + (uint _amtA, uint _amtB, uint _uniAmt) = _removeLiquidity( + tokenA, + tokenB, + _amt, + unitAmtA, + unitAmtB + ); + + setUint(setIds[0], _amtA); + setUint(setIds[1], _amtB); + + _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; + _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setIds); + } + + /** + * @dev Buy ETH/ERC20_Token. + * @notice Buy a token using a SushiSwap + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param buyAmt The amount of tokens to buy. + * @param unitAmt The unit amount of sellAmt/buyAmt with slippage. + * @param getId ID to retrieve buyAmt. + * @param setId ID to store the amount of tokens sold. + */ + function buy( + address buyAddr, + address sellAddr, + uint256 buyAmt, + uint256 unitAmt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _buyAmt = getUint(getId, buyAmt); + (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeEthAddress(buyAddr, sellAddr); + address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + + uint _slippageAmt = convert18ToDec(_sellAddr.decimals(), + wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt)) + ); + + checkPair(paths); + uint _expectedAmt = getExpectedSellAmt(paths, _buyAmt); + require(_slippageAmt >= _expectedAmt, "Too much slippage"); + + bool isEth = address(_sellAddr) == wethAddr; + convertEthToWeth(isEth, _sellAddr, _expectedAmt); + approve(_sellAddr, address(router), _expectedAmt); + + uint _sellAmt = router.swapTokensForExactTokens( + _buyAmt, + _expectedAmt, + paths, + address(this), + block.timestamp + 1 + )[0]; + + isEth = address(_buyAddr) == wethAddr; + convertWethToEth(isEth, _buyAddr, _buyAmt); + + setUint(setId, _sellAmt); + + _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + } + + /** + * @dev Sell ETH/ERC20_Token. + * @notice Sell a token using a SushiSwap + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmt The unit amount of buyAmt/sellAmt with slippage. + * @param getId ID to retrieve sellAmt. + * @param setId ID stores the amount of token brought. + */ + function sell( + address buyAddr, + address sellAddr, + uint256 sellAmt, + uint256 unitAmt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _sellAmt = getUint(getId, sellAmt); + (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeEthAddress(buyAddr, sellAddr); + address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + + if (_sellAmt == uint(-1)) { + _sellAmt = sellAddr == ethAddr ? + address(this).balance : + _sellAddr.balanceOf(address(this)); + } + + uint _slippageAmt = convert18ToDec(_buyAddr.decimals(), + wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt)) + ); + + checkPair(paths); + uint _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); + require(_slippageAmt <= _expectedAmt, "Too much slippage"); + + bool isEth = address(_sellAddr) == wethAddr; + convertEthToWeth(isEth, _sellAddr, _sellAmt); + approve(_sellAddr, address(router), _sellAmt); + + uint _buyAmt = router.swapExactTokensForTokens( + _sellAmt, + _expectedAmt, + paths, + address(this), + block.timestamp + 1 + )[1]; + + isEth = address(_buyAddr) == wethAddr; + convertWethToEth(isEth, _buyAddr, _buyAmt); + + setUint(setId, _buyAmt); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + } +} + +contract ConnectV2Sushiswap is SushipswapResolver { + string public constant name = "Sushipswap-v1.1"; +} diff --git a/test/sushiswap/sushiswap.test.js b/test/sushiswap/sushiswap.test.js new file mode 100644 index 00000000..ead9dfd3 --- /dev/null +++ b/test/sushiswap/sushiswap.test.js @@ -0,0 +1,217 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { web3, deployments, waffle, ethers } = hre; +const { provider, deployContract } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const encodeFlashcastData = require("../../scripts/encodeFlashcastData.js") +const getMasterSigner = require("../../scripts/getMasterSigner") +const addLiquidity = require("../../scripts/addLiquidity"); + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); +const constants = require("../../scripts/constant/constant"); +const tokens = require("../../scripts/constant/tokens"); +const { abi: nftManagerAbi } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json") + +const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); +const { eth } = require("../../scripts/constant/tokens"); +const { BigNumber } = require("ethers"); + +const FeeAmount = { + LOW: 500, + MEDIUM: 3000, + HIGH: 10000, +} + +const TICK_SPACINGS = { + 500: 10, + 3000: 60, + 10000: 200 +} + +const USDT_ADDR = "0xdac17f958d2ee523a2206206994597c13d831ec7" +const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" + +let tokenIds = [] +let liquidities = [] +const abiCoder = ethers.utils.defaultAbiCoder + +describe("Sushiswap", function () { + const connectorName = "Sushiswap-v1" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785, + }, + }, + ], + }); + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2SushiswapArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + // let castEvent = new Promise((resolve, reject) => { + // dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => { + // const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[0]); + // const params1 = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[2]); + // tokenIds.push(params[0]); + // tokenIds.push(params1[0]); + // liquidities.push(params[1]); + // event.removeListener(); + + // resolve({ + // eventNames, + // }); + // }); + + // setTimeout(() => { + // reject(new Error('timeout')); + // }, 60000) + // }); + + // let event = await castEvent + + // const data = await nftManager.positions(tokenIds[0]) + + // expect(data.liquidity).to.be.equals(liquidities[0]); + }).timeout(10000000000); + + it("Should withdraw successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setIds = ["0", "0"] + + const spells = [ + { + connector: connectorName, + method: "withdraw", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + 0, + 0, + getId, + setIds + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) \ No newline at end of file From 650009f45e5882b6eed3d3ef37f9a3f90addb2c8 Mon Sep 17 00:00:00 2001 From: cryptoDev222 Date: Fri, 22 Oct 2021 09:29:32 -0500 Subject: [PATCH 02/31] feat/implement sushiswap double incentive --- contracts/mainnet/common/interfaces.sol | 1 + .../connectors/sushi-incentive/events.sol | 36 +++ .../connectors/sushi-incentive/helpers.sol | 88 +++++++ .../connectors/sushi-incentive/interface.sol | 94 +++++++ .../connectors/sushi-incentive/main.sol | 146 +++++++++++ hardhat.config.js | 90 +++++++ test/sushiswap/sushiswap.test.js | 51 +--- .../sushiswapIncentive/sushiIncentive.test.js | 237 ++++++++++++++++++ 8 files changed, 694 insertions(+), 49 deletions(-) create mode 100644 contracts/mainnet/connectors/sushi-incentive/events.sol create mode 100644 contracts/mainnet/connectors/sushi-incentive/helpers.sol create mode 100644 contracts/mainnet/connectors/sushi-incentive/interface.sol create mode 100644 contracts/mainnet/connectors/sushi-incentive/main.sol create mode 100644 hardhat.config.js create mode 100644 test/sushiswapIncentive/sushiIncentive.test.js diff --git a/contracts/mainnet/common/interfaces.sol b/contracts/mainnet/common/interfaces.sol index 24a4eb47..53e848d3 100644 --- a/contracts/mainnet/common/interfaces.sol +++ b/contracts/mainnet/common/interfaces.sol @@ -8,6 +8,7 @@ interface TokenInterface { function withdraw(uint) external; function balanceOf(address) external view returns (uint); function decimals() external view returns (uint); + function totalSupply() external view returns (uint); } interface MemoryInterface { diff --git a/contracts/mainnet/connectors/sushi-incentive/events.sol b/contracts/mainnet/connectors/sushi-incentive/events.sol new file mode 100644 index 00000000..ebf68ebd --- /dev/null +++ b/contracts/mainnet/connectors/sushi-incentive/events.sol @@ -0,0 +1,36 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit( + address indexed user, + uint256 indexed pid, + uint256 indexed version, + uint256 amount + ); + event LogWithdraw( + address indexed user, + uint256 indexed pid, + uint256 indexed version, + uint256 amount + ); + event LogEmergencyWithdraw( + address indexed user, + uint256 indexed pid, + uint256 indexed version, + uint256 lpAmount, + uint256 rewardsAmount + ); + event LogHarvest( + address indexed user, + uint256 indexed pid, + uint256 indexed version, + uint256 amount + ); + event LogWithdrawAndHarvest( + address indexed user, + uint256 indexed pid, + uint256 indexed version, + uint256 widrawAmount, + uint256 harvestAmount + ); +} diff --git a/contracts/mainnet/connectors/sushi-incentive/helpers.sol b/contracts/mainnet/connectors/sushi-incentive/helpers.sol new file mode 100644 index 00000000..97522f22 --- /dev/null +++ b/contracts/mainnet/connectors/sushi-incentive/helpers.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +import {DSMath} from "../../common/math.sol"; +import {Basic} from "../../common/basic.sol"; +import "./interface.sol"; + +contract Helpers is DSMath, Basic { + IMasterChefV2 immutable masterChefV2 = + IMasterChefV2(0xEF0881eC094552b2e128Cf945EF17a6752B4Ec5d); + IMasterChef immutable masterChef = + IMasterChef(0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd); + ISushiSwapFactory immutable factory = + ISushiSwapFactory(0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac); + + function _deposit(uint256 _pid, uint256 _amount, uint256 _version) internal { + if(_version == 2) + masterChefV2.deposit(_pid, _amount, address(this)); + else + masterChef.deposit(_pid, _amount); + } + + function _withdraw(uint256 _pid, uint256 _amount, uint256 _version) internal { + if(_version == 2) + masterChefV2.withdraw(_pid, _amount, address(this)); + else + masterChef.withdraw(_pid, _amount); + } + + function _harvest(uint256 _pid) internal { + masterChefV2.harvest(_pid, address(this)); + } + + function _withdrawAndHarvest(uint256 _pid, uint256 _amount, uint256 _version) internal { + if(_version == 2) + masterChefV2.withdrawAndHarvest(_pid, _amount, address(this)); + else _withdraw(_pid, _amount, _version); + } + + function _emergencyWithdraw(uint256 _pid, uint256 _version) internal { + if(_version == 2) + masterChefV2.emergencyWithdraw(_pid, address(this)); + else + masterChef.emergencyWithdraw(_pid, address(this)); + } + + function _getPoolId(address tokenA, address tokenB) + internal + view + returns (uint256 poolId, uint256 version, address lpToken) + { + address pair = factory.getPair(tokenA, tokenB); + uint256 length = masterChefV2.poolLength(); + version = 2; + poolId = uint256(-1); + + for (uint256 i = 0; i < length; i++) { + lpToken = masterChefV2.lpToken(i); + if (pair == lpToken) { + poolId = i; + break; + } + } + + uint256 lengthV1 = masterChef.poolLength(); + for (uint256 i = 0; i < lengthV1; i++) { + (lpToken, , , ) = masterChef.poolInfo(i); + if (pair == lpToken) { + poolId = i; + version = 1; + break; + } + } + } + + function _getUserInfo(uint256 _pid, uint256 _version) + internal + view + returns (uint256 lpAmount, uint256 rewardsAmount) + { + if(_version == 2) + (lpAmount, rewardsAmount) = masterChefV2.userInfo(_pid, address(this)); + else + (lpAmount, rewardsAmount) = masterChef.userInfo(_pid, address(this)); + } +} diff --git a/contracts/mainnet/connectors/sushi-incentive/interface.sol b/contracts/mainnet/connectors/sushi-incentive/interface.sol new file mode 100644 index 00000000..865ec361 --- /dev/null +++ b/contracts/mainnet/connectors/sushi-incentive/interface.sol @@ -0,0 +1,94 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; +import "./libraries/IERC20.sol"; + +struct UserInfo { + uint256 amount; + uint256 rewardDebt; +} + +struct PoolInfo { + IERC20 lpToken; // Address of LP token contract. + uint256 allocPoint; // How many allocation points assigned to this pool. SUSHIs to distribute per block. + uint256 lastRewardBlock; // Last block number that SUSHIs distribution occurs. + uint256 accSushiPerShare; // Accumulated SUSHIs per share, times 1e12. See below. +} + +interface IMasterChef { + function poolLength() external view returns (uint256); + + function updatePool(uint256 pid) external returns (PoolInfo memory); + + function poolInfo(uint256 pid) external view returns (address, uint256, uint256, uint256); + + function userInfo(uint256 _pid, address _user) + external + view + returns (uint256, uint256); + + function deposit( + uint256 pid, + uint256 amount + ) external; + + function withdraw( + uint256 pid, + uint256 amount + ) external; + + function emergencyWithdraw(uint256 pid, address to) external; +} + +interface IMasterChefV2 { + function poolLength() external view returns (uint256); + + function updatePool(uint256 pid) external returns (PoolInfo memory); + + function lpToken(uint256 pid) external view returns (address); + + function userInfo(uint256 _pid, address _user) + external + view + returns (uint256, uint256); + + function deposit( + uint256 pid, + uint256 amount, + address to + ) external; + + function withdraw( + uint256 pid, + uint256 amount, + address to + ) external; + + function emergencyWithdraw(uint256 pid, address to) external; + + function harvest(uint256 pid, address to) external; + + function withdrawAndHarvest( + uint256 pid, + uint256 amount, + address to + ) external; +} + +interface ISushiSwapFactory { + function getPair(address tokenA, address tokenB) + external + view + returns (address pair); + + function allPairs(uint256) external view returns (address pair); + + function allPairsLength() external view returns (uint256); + + function feeTo() external view returns (address); + + function feeToSetter() external view returns (address); + + function createPair(address tokenA, address tokenB) + external + returns (address pair); +} diff --git a/contracts/mainnet/connectors/sushi-incentive/main.sol b/contracts/mainnet/connectors/sushi-incentive/main.sol new file mode 100644 index 00000000..a60e6940 --- /dev/null +++ b/contracts/mainnet/connectors/sushi-incentive/main.sol @@ -0,0 +1,146 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title SushiSwap Double Incentive. + * @dev Decentralized Exchange. + */ + +import {TokenInterface} from "../../common/interfaces.sol"; +import {Helpers} from "./helpers.sol"; +import {Events} from "./events.sol"; + +abstract contract SushipswapIncentiveResolver is Helpers, Events { + /** + * @dev deposit LP token to masterChef + * @param token1 token1 of LP token + * @param token2 token2 of LP token + * @param amount amount of LP token + * @param getId ID to retrieve amount + * @param setId ID stores Pool ID + */ + function deposit( + address token1, + address token2, + uint256 amount, + uint256 getId, + uint256 setId + ) external { + amount = getUint(getId, amount); + (uint256 _pid, uint256 _version, address lpTokenAddr) = _getPoolId( + token1, + token2 + ); + setUint(setId, _pid); + require(_pid != uint256(-1), "pool-does-not-exist"); + TokenInterface lpToken = TokenInterface(lpTokenAddr); + lpToken.approve(address(masterChef), amount); + _deposit(_pid, amount, _version); + emit LogDeposit(address(this), _pid, _version, amount); + } + + /** + * @dev withdraw LP token from masterChef + * @param token1 token1 of LP token + * @param token2 token2 of LP token + * @param amount amount of LP token + * @param getId ID to retrieve amount + * @param setId ID stores Pool ID + */ + function withdraw( + address token1, + address token2, + uint256 amount, + uint256 getId, + uint256 setId + ) external { + amount = getUint(getId, amount); + (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); + setUint(setId, _pid); + require(_pid != uint256(-1), "pool-does-not-exist"); + _withdraw(_pid, amount, _version); + emit LogWithdraw(address(this), _pid, _version, amount); + } + + /** + * @dev harvest from masterChef + * @param token1 token1 deposited of LP token + * @param token2 token2 deposited LP token + * @param setId ID stores Pool ID + */ + function harvest( + address token1, + address token2, + uint256 setId + ) external { + (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); + setUint(setId, _pid); + require(_pid != uint256(-1), "pool-does-not-exist"); + (, uint256 rewardsAmount) = _getUserInfo(_pid, _version); + if (_version == 2) _harvest(_pid); + else _withdraw(_pid, 0, _version); + emit LogHarvest(address(this), _pid, _version, rewardsAmount); + } + + /** + * @dev withdraw LP token and harvest from masterChef + * @param token1 token1 of LP token + * @param token2 token2 of LP token + * @param amount amount of LP token + * @param getId ID to retrieve amount + * @param setId ID stores Pool ID + */ + function withdrawAndHarvest( + address token1, + address token2, + uint256 amount, + uint256 getId, + uint256 setId + ) external { + amount = getUint(getId, amount); + (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); + setUint(setId, _pid); + require(_pid != uint256(-1), "pool-does-not-exist"); + (, uint256 rewardsAmount) = _getUserInfo(_pid, _version); + _withdrawAndHarvest(_pid, amount, _version); + emit LogWithdrawAndHarvest( + address(this), + _pid, + _version, + amount, + rewardsAmount + ); + } + + /** + * @dev emergency withdraw from masterChef + * @param token1 token1 deposited of LP token + * @param token2 token2 deposited LP token + * @param setId ID stores Pool ID + */ + function emergencyWithdraw( + address token1, + address token2, + uint256 setId + ) external { + (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); + setUint(setId, _pid); + require(_pid != uint256(-1), "pool-does-not-exist"); + (uint256 lpAmount, uint256 rewardsAmount) = _getUserInfo( + _pid, + _version + ); + _emergencyWithdraw(_pid, _version); + emit LogEmergencyWithdraw( + address(this), + _pid, + _version, + lpAmount, + rewardsAmount + ); + } +} + +contract ConnectV2SushiswapIncentive is SushipswapIncentiveResolver { + string public constant name = "SushipswapIncentive-v1.1"; +} diff --git a/hardhat.config.js b/hardhat.config.js new file mode 100644 index 00000000..7d88c978 --- /dev/null +++ b/hardhat.config.js @@ -0,0 +1,90 @@ +require("@nomiclabs/hardhat-waffle"); +require("@nomiclabs/hardhat-ethers"); +require("@tenderly/hardhat-tenderly"); +require("@nomiclabs/hardhat-etherscan"); +require("@nomiclabs/hardhat-web3"); +require("hardhat-deploy"); +require("hardhat-deploy-ethers"); +require("dotenv").config(); + +const { utils } = require("ethers"); + +const PRIVATE_KEY = process.env.PRIVATE_KEY; +const ALCHEMY_ID = process.env.ALCHEMY_ID; +const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY; + +if (!process.env.ALCHEMY_ID) { + throw new Error("ENV Variable ALCHEMY_ID not set!"); +} + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +module.exports = { + solidity: { + compilers: [ + { + version: "0.7.6", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + { + version: "0.6.0", + }, + { + version: "0.6.2", + }, + { + version: "0.6.12", + }, + { + version: "0.6.5", + }, + ], + }, + networks: { + // defaultNetwork: "hardhat", + kovan: { + url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_ID}`, + accounts: [`0x${PRIVATE_KEY}`], + }, + mainnet: { + url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, + accounts: [`0x${PRIVATE_KEY}`], + timeout: 150000, + gasPrice: parseInt(utils.parseUnits("30", "gwei")), + }, + rinkeby: { + url: `https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_ID}`, + accounts: [`0x${PRIVATE_KEY}`], + timeout: 150000, + }, + hardhat: { + forking: { + url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, + blockNumber: 12696000, + }, + blockGasLimit: 12000000, + }, + matic: { + url: "https://rpc-mainnet.maticvigil.com/", + accounts: [`0x${PRIVATE_KEY}`], + timeout: 150000, + gasPrice: parseInt(utils.parseUnits("1", "gwei")), + }, + }, + etherscan: { + apiKey: ETHERSCAN_API_KEY, + }, + tenderly: { + project: process.env.TENDERLY_PROJECT, + username: process.env.TENDERLY_USERNAME, + }, + mocha: { + timeout: 100 * 1000, + }, +}; \ No newline at end of file diff --git a/test/sushiswap/sushiswap.test.js b/test/sushiswap/sushiswap.test.js index ead9dfd3..baaf3876 100644 --- a/test/sushiswap/sushiswap.test.js +++ b/test/sushiswap/sushiswap.test.js @@ -1,44 +1,21 @@ const { expect } = require("chai"); const hre = require("hardhat"); -const { web3, deployments, waffle, ethers } = hre; -const { provider, deployContract } = waffle +const { waffle, ethers } = hre; +const { provider } = waffle const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") const buildDSAv2 = require("../../scripts/buildDSAv2") const encodeSpells = require("../../scripts/encodeSpells.js") -const encodeFlashcastData = require("../../scripts/encodeFlashcastData.js") const getMasterSigner = require("../../scripts/getMasterSigner") const addLiquidity = require("../../scripts/addLiquidity"); const addresses = require("../../scripts/constant/addresses"); const abis = require("../../scripts/constant/abis"); -const constants = require("../../scripts/constant/constant"); -const tokens = require("../../scripts/constant/tokens"); -const { abi: nftManagerAbi } = require("@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json") const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); -const { eth } = require("../../scripts/constant/tokens"); -const { BigNumber } = require("ethers"); -const FeeAmount = { - LOW: 500, - MEDIUM: 3000, - HIGH: 10000, -} - -const TICK_SPACINGS = { - 500: 10, - 3000: 60, - 10000: 200 -} - -const USDT_ADDR = "0xdac17f958d2ee523a2206206994597c13d831ec7" const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" -let tokenIds = [] -let liquidities = [] -const abiCoder = ethers.utils.defaultAbiCoder - describe("Sushiswap", function () { const connectorName = "Sushiswap-v1" @@ -134,30 +111,6 @@ describe("Sushiswap", function () { const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) let receipt = await tx.wait() - // let castEvent = new Promise((resolve, reject) => { - // dsaWallet0.on('LogCast', (origin, sender, value, targetNames, targets, eventNames, eventParams, event) => { - // const params = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[0]); - // const params1 = abiCoder.decode(["uint256", "uint256", "uint256", "uint256", "int24", "int24"], eventParams[2]); - // tokenIds.push(params[0]); - // tokenIds.push(params1[0]); - // liquidities.push(params[1]); - // event.removeListener(); - - // resolve({ - // eventNames, - // }); - // }); - - // setTimeout(() => { - // reject(new Error('timeout')); - // }, 60000) - // }); - - // let event = await castEvent - - // const data = await nftManager.positions(tokenIds[0]) - - // expect(data.liquidity).to.be.equals(liquidities[0]); }).timeout(10000000000); it("Should withdraw successfully", async function () { diff --git a/test/sushiswapIncentive/sushiIncentive.test.js b/test/sushiswapIncentive/sushiIncentive.test.js new file mode 100644 index 00000000..1b2fd01b --- /dev/null +++ b/test/sushiswapIncentive/sushiIncentive.test.js @@ -0,0 +1,237 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { waffle, ethers } = hre; +const { provider } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") +const addLiquidity = require("../../scripts/addLiquidity"); + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); + +const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); +const connectV2SushiswapIncentiveArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushi-incentive/main.sol/ConnectV2SushiswapIncentive.json"); + +const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" +const WETH_ADDR = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + +describe("Sushiswap", function () { + const connectorName = "Sushiswap-v1" + const incentiveConnectorName = "Sushiswp-Incentive-v1" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector, connectorIncentive; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785, + }, + }, + ], + }); + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2SushiswapArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + + connectorIncentive = await deployAndEnableConnector({ + connectorName: incentiveConnectorName, + contractArtifact: connectV2SushiswapIncentiveArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Incentive Connector address", connectorIncentive.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("2") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + await tx.wait() + + describe("Incentive", () => { + it("Should deposit successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "deposit", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("10"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should harvest successfully", async () => { + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "harvest", + args: [ + WETH_ADDR, + DAI_ADDR, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should harvest and withdraw successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "withdrawAndHarvest", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("1"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should withdraw successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "withdraw", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("1"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + }) + }).timeout(10000000000); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) \ No newline at end of file From 627e839c70a676ff67f31d2a31a9661d59985c69 Mon Sep 17 00:00:00 2001 From: cryptoDev222 Date: Mon, 15 Nov 2021 08:58:14 -0600 Subject: [PATCH 03/31] minor fixes --- contracts/mainnet/common/basic.sol | 4 ++ .../connectors/sushi-incentive/events.sol | 5 -- .../connectors/sushi-incentive/interface.sol | 25 ++++++- .../connectors/sushi-incentive/main.sol | 72 +++++++++++++------ 4 files changed, 78 insertions(+), 28 deletions(-) diff --git a/contracts/mainnet/common/basic.sol b/contracts/mainnet/common/basic.sol index febeb784..c0650dfb 100644 --- a/contracts/mainnet/common/basic.sol +++ b/contracts/mainnet/common/basic.sol @@ -41,6 +41,10 @@ abstract contract Basic is DSMath, Stores { _sell = sell == ethAddr ? TokenInterface(wethAddr) : TokenInterface(sell); } + function changeEthAddrToWethAddr(address token) internal pure returns(address tokenAddr){ + tokenAddr = token == ethAddr ? wethAddr : token; + } + function convertEthToWeth(bool isEth, TokenInterface token, uint amount) internal { if(isEth) token.deposit{value: amount}(); } diff --git a/contracts/mainnet/connectors/sushi-incentive/events.sol b/contracts/mainnet/connectors/sushi-incentive/events.sol index ebf68ebd..aa1c890d 100644 --- a/contracts/mainnet/connectors/sushi-incentive/events.sol +++ b/contracts/mainnet/connectors/sushi-incentive/events.sol @@ -2,32 +2,27 @@ pragma solidity ^0.7.0; contract Events { event LogDeposit( - address indexed user, uint256 indexed pid, uint256 indexed version, uint256 amount ); event LogWithdraw( - address indexed user, uint256 indexed pid, uint256 indexed version, uint256 amount ); event LogEmergencyWithdraw( - address indexed user, uint256 indexed pid, uint256 indexed version, uint256 lpAmount, uint256 rewardsAmount ); event LogHarvest( - address indexed user, uint256 indexed pid, uint256 indexed version, uint256 amount ); event LogWithdrawAndHarvest( - address indexed user, uint256 indexed pid, uint256 indexed version, uint256 widrawAmount, diff --git a/contracts/mainnet/connectors/sushi-incentive/interface.sol b/contracts/mainnet/connectors/sushi-incentive/interface.sol index 865ec361..ba3b1c6c 100644 --- a/contracts/mainnet/connectors/sushi-incentive/interface.sol +++ b/contracts/mainnet/connectors/sushi-incentive/interface.sol @@ -1,6 +1,5 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; -import "./libraries/IERC20.sol"; struct UserInfo { uint256 amount; @@ -14,6 +13,30 @@ struct PoolInfo { uint256 accSushiPerShare; // Accumulated SUSHIs per share, times 1e12. See below. } +interface IERC20 { + function totalSupply() external view returns (uint256); + + function balanceOf(address account) external view returns (uint256); + + function allowance(address owner, address spender) external view returns (uint256); + + function approve(address spender, uint256 amount) external returns (bool); + + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + + /// @notice EIP 2612 + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; +} + interface IMasterChef { function poolLength() external view returns (uint256); diff --git a/contracts/mainnet/connectors/sushi-incentive/main.sol b/contracts/mainnet/connectors/sushi-incentive/main.sol index a60e6940..cc448434 100644 --- a/contracts/mainnet/connectors/sushi-incentive/main.sol +++ b/contracts/mainnet/connectors/sushi-incentive/main.sol @@ -13,6 +13,7 @@ import {Events} from "./events.sol"; abstract contract SushipswapIncentiveResolver is Helpers, Events { /** * @dev deposit LP token to masterChef + * @notice deposit LP token to masterChef * @param token1 token1 of LP token * @param token2 token2 of LP token * @param amount amount of LP token @@ -25,7 +26,13 @@ abstract contract SushipswapIncentiveResolver is Helpers, Events { uint256 amount, uint256 getId, uint256 setId - ) external { + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + token1 = changeEthAddrToWethAddr(token1); + token2 = changeEthAddrToWethAddr(token2); amount = getUint(getId, amount); (uint256 _pid, uint256 _version, address lpTokenAddr) = _getPoolId( token1, @@ -36,11 +43,13 @@ abstract contract SushipswapIncentiveResolver is Helpers, Events { TokenInterface lpToken = TokenInterface(lpTokenAddr); lpToken.approve(address(masterChef), amount); _deposit(_pid, amount, _version); - emit LogDeposit(address(this), _pid, _version, amount); + _eventName = "LogDeposit(uint256,uint256,uint256)"; + _eventParam = abi.encode(_pid, _version, amount); } /** * @dev withdraw LP token from masterChef + * @notice withdraw LP token from masterChef * @param token1 token1 of LP token * @param token2 token2 of LP token * @param amount amount of LP token @@ -53,17 +62,25 @@ abstract contract SushipswapIncentiveResolver is Helpers, Events { uint256 amount, uint256 getId, uint256 setId - ) external { + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + token1 = changeEthAddrToWethAddr(token1); + token2 = changeEthAddrToWethAddr(token2); amount = getUint(getId, amount); (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); setUint(setId, _pid); require(_pid != uint256(-1), "pool-does-not-exist"); _withdraw(_pid, amount, _version); - emit LogWithdraw(address(this), _pid, _version, amount); + _eventName = "LogWithdraw(uint256,uint256,uint256)"; + _eventParam = abi.encode(_pid, _version, amount); } /** * @dev harvest from masterChef + * @notice harvest from masterChef * @param token1 token1 deposited of LP token * @param token2 token2 deposited LP token * @param setId ID stores Pool ID @@ -72,18 +89,26 @@ abstract contract SushipswapIncentiveResolver is Helpers, Events { address token1, address token2, uint256 setId - ) external { + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + token1 = changeEthAddrToWethAddr(token1); + token2 = changeEthAddrToWethAddr(token2); (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); setUint(setId, _pid); require(_pid != uint256(-1), "pool-does-not-exist"); (, uint256 rewardsAmount) = _getUserInfo(_pid, _version); if (_version == 2) _harvest(_pid); else _withdraw(_pid, 0, _version); - emit LogHarvest(address(this), _pid, _version, rewardsAmount); + _eventName = "LogHarvest(uint256,uint256,uint256)"; + _eventParam = abi.encode(_pid, _version, rewardsAmount); } /** * @dev withdraw LP token and harvest from masterChef + * @notice withdraw LP token and harvest from masterChef * @param token1 token1 of LP token * @param token2 token2 of LP token * @param amount amount of LP token @@ -96,24 +121,26 @@ abstract contract SushipswapIncentiveResolver is Helpers, Events { uint256 amount, uint256 getId, uint256 setId - ) external { + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + token1 = changeEthAddrToWethAddr(token1); + token2 = changeEthAddrToWethAddr(token2); amount = getUint(getId, amount); (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); setUint(setId, _pid); require(_pid != uint256(-1), "pool-does-not-exist"); (, uint256 rewardsAmount) = _getUserInfo(_pid, _version); _withdrawAndHarvest(_pid, amount, _version); - emit LogWithdrawAndHarvest( - address(this), - _pid, - _version, - amount, - rewardsAmount - ); + _eventName = "LogWithdrawAndHarvest(uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(_pid, _version, amount, rewardsAmount); } /** * @dev emergency withdraw from masterChef + * @notice emergency withdraw from masterChef * @param token1 token1 deposited of LP token * @param token2 token2 deposited LP token * @param setId ID stores Pool ID @@ -122,7 +149,13 @@ abstract contract SushipswapIncentiveResolver is Helpers, Events { address token1, address token2, uint256 setId - ) external { + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + token1 = changeEthAddrToWethAddr(token1); + token2 = changeEthAddrToWethAddr(token2); (uint256 _pid, uint256 _version, ) = _getPoolId(token1, token2); setUint(setId, _pid); require(_pid != uint256(-1), "pool-does-not-exist"); @@ -131,13 +164,8 @@ abstract contract SushipswapIncentiveResolver is Helpers, Events { _version ); _emergencyWithdraw(_pid, _version); - emit LogEmergencyWithdraw( - address(this), - _pid, - _version, - lpAmount, - rewardsAmount - ); + _eventName = "LogEmergencyWithdraw(uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(_pid, _version, lpAmount, rewardsAmount); } } From d7b69b4d875d0d7a46e0926c8f6bb9803ad11156 Mon Sep 17 00:00:00 2001 From: cryptoDev222 Date: Mon, 15 Nov 2021 09:00:46 -0600 Subject: [PATCH 04/31] implement quickswap --- .../polygon/connectors/quickswap/events.sol | 41 ++++ .../polygon/connectors/quickswap/helpers.sol | 184 ++++++++++++++++ .../connectors/quickswap/interface.sol | 57 +++++ .../polygon/connectors/quickswap/main.sol | 196 ++++++++++++++++++ 4 files changed, 478 insertions(+) create mode 100644 contracts/polygon/connectors/quickswap/events.sol create mode 100644 contracts/polygon/connectors/quickswap/helpers.sol create mode 100644 contracts/polygon/connectors/quickswap/interface.sol create mode 100644 contracts/polygon/connectors/quickswap/main.sol diff --git a/contracts/polygon/connectors/quickswap/events.sol b/contracts/polygon/connectors/quickswap/events.sol new file mode 100644 index 00000000..2717b0a3 --- /dev/null +++ b/contracts/polygon/connectors/quickswap/events.sol @@ -0,0 +1,41 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDepositLiquidity( + address indexed tokenA, + address indexed tokenB, + uint256 amtA, + uint256 amtB, + uint256 uniAmount, + uint256 getId, + uint256 setId + ); + + event LogWithdrawLiquidity( + address indexed tokenA, + address indexed tokenB, + uint256 amountA, + uint256 amountB, + uint256 uniAmount, + uint256 getId, + uint256[] setId + ); + + event LogBuy( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); + + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} \ No newline at end of file diff --git a/contracts/polygon/connectors/quickswap/helpers.sol b/contracts/polygon/connectors/quickswap/helpers.sol new file mode 100644 index 00000000..2199cfb6 --- /dev/null +++ b/contracts/polygon/connectors/quickswap/helpers.sol @@ -0,0 +1,184 @@ +pragma solidity ^0.7.0; + +import {TokenInterface} from "../../common/interfaces.sol"; +import {DSMath} from "../../common/math.sol"; +import {Basic} from "../../common/basic.sol"; +import {IQuickSwapRouter, IQuickSwapFactory} from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + /** + * @dev IQuickSwapRouter + */ + IQuickSwapRouter internal constant router = + IQuickSwapRouter(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); + + function getExpectedBuyAmt(address[] memory paths, uint256 sellAmt) + internal + view + returns (uint256 buyAmt) + { + uint256[] memory amts = router.getAmountsOut(sellAmt, paths); + buyAmt = amts[1]; + } + + function getExpectedSellAmt(address[] memory paths, uint256 buyAmt) + internal + view + returns (uint256 sellAmt) + { + uint256[] memory amts = router.getAmountsIn(buyAmt, paths); + sellAmt = amts[0]; + } + + function checkPair(address[] memory paths) internal view { + address pair = IQuickSwapFactory(router.factory()).getPair( + paths[0], + paths[1] + ); + require(pair != address(0), "No-exchange-address"); + } + + function getPaths(address buyAddr, address sellAddr) + internal + pure + returns (address[] memory paths) + { + paths = new address[](2); + paths[0] = address(sellAddr); + paths[1] = address(buyAddr); + } + + function getMinAmount( + TokenInterface token, + uint256 amt, + uint256 slippage + ) internal view returns (uint256 minAmt) { + uint256 _amt18 = convertTo18(token.decimals(), amt); + minAmt = wmul(_amt18, sub(WAD, slippage)); + minAmt = convert18ToDec(token.decimals(), minAmt); + } + + function _addLiquidity( + address tokenA, + address tokenB, + uint256 _amt, + uint256 unitAmt, + uint256 slippage + ) + internal + returns ( + uint256 _amtA, + uint256 _amtB, + uint256 _liquidity + ) + { + (TokenInterface _tokenA, TokenInterface _tokenB) = changeMaticAddress( + tokenA, + tokenB + ); + + _amtA = _amt == uint256(-1) + ? getTokenBal(TokenInterface(tokenA)) + : _amt; + _amtB = convert18ToDec( + _tokenB.decimals(), + wmul(unitAmt, convertTo18(_tokenA.decimals(), _amtA)) + ); + + bool isMatic = address(_tokenA) == wmaticAddr; + convertMaticToWmatic(isMatic, _tokenA, _amtA); + + isMatic = address(_tokenB) == wmaticAddr; + convertMaticToWmatic(isMatic, _tokenB, _amtB); + + approve(_tokenA, address(router), _amtA); + approve(_tokenB, address(router), _amtB); + + uint256 minAmtA = getMinAmount(_tokenA, _amtA, slippage); + uint256 minAmtB = getMinAmount(_tokenB, _amtB, slippage); + (_amtA, _amtB, _liquidity) = router.addLiquidity( + address(_tokenA), + address(_tokenB), + _amtA, + _amtB, + minAmtA, + minAmtA, + address(this), + block.timestamp + 1 + ); + } + + function _removeLiquidity( + address tokenA, + address tokenB, + uint256 _amt, + uint256 unitAmtA, + uint256 unitAmtB + ) + internal + returns ( + uint256 _amtA, + uint256 _amtB, + uint256 _uniAmt + ) + { + TokenInterface _tokenA; + TokenInterface _tokenB; + (_tokenA, _tokenB, _uniAmt) = _getRemoveLiquidityData( + tokenA, + tokenB, + _amt + ); + { + uint256 minAmtA = convert18ToDec( + _tokenA.decimals(), + wmul(unitAmtA, _uniAmt) + ); + uint256 minAmtB = convert18ToDec( + _tokenB.decimals(), + wmul(unitAmtB, _uniAmt) + ); + (_amtA, _amtB) = router.removeLiquidity( + address(_tokenA), + address(_tokenB), + _uniAmt, + minAmtA, + minAmtB, + address(this), + block.timestamp + 1 + ); + } + + bool isMatic = address(_tokenA) == wmaticAddr; + convertWmaticToMatic(isMatic, _tokenA, _amtA); + + isMatic = address(_tokenB) == wmaticAddr; + convertWmaticToMatic(isMatic, _tokenB, _amtB); + } + + function _getRemoveLiquidityData( + address tokenA, + address tokenB, + uint256 _amt + ) + internal + returns ( + TokenInterface _tokenA, + TokenInterface _tokenB, + uint256 _uniAmt + ) + { + (_tokenA, _tokenB) = changeMaticAddress(tokenA, tokenB); + address exchangeAddr = IQuickSwapFactory(router.factory()).getPair( + address(_tokenA), + address(_tokenB) + ); + require(exchangeAddr != address(0), "pair-not-found."); + + TokenInterface uniToken = TokenInterface(exchangeAddr); + _uniAmt = _amt == uint256(-1) + ? uniToken.balanceOf(address(this)) + : _amt; + approve(uniToken, address(router), _uniAmt); + } +} diff --git a/contracts/polygon/connectors/quickswap/interface.sol b/contracts/polygon/connectors/quickswap/interface.sol new file mode 100644 index 00000000..4986dca7 --- /dev/null +++ b/contracts/polygon/connectors/quickswap/interface.sol @@ -0,0 +1,57 @@ +pragma solidity ^0.7.0; + +interface IQuickSwapRouter { + function factory() external pure returns (address); + function WETH() external pure returns (address); + + function addLiquidity( + address tokenA, + address tokenB, + uint amountADesired, + uint amountBDesired, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB, uint liquidity); + function removeLiquidity( + address tokenA, + address tokenB, + uint liquidity, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB); + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + function swapTokensForExactTokens( + uint amountOut, + uint amountInMax, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + + function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); + function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); + function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); + function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); + function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); +} + +interface IQuickSwapFactory { + function getPair(address tokenA, address tokenB) external view returns (address pair); + function allPairs(uint) external view returns (address pair); + function allPairsLength() external view returns (uint); + + function feeTo() external view returns (address); + function feeToSetter() external view returns (address); + + function createPair(address tokenA, address tokenB) external returns (address pair); +} diff --git a/contracts/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol new file mode 100644 index 00000000..b8c0a79a --- /dev/null +++ b/contracts/polygon/connectors/quickswap/main.sol @@ -0,0 +1,196 @@ +pragma solidity ^0.7.0; + +/** + * @title QuickSwap. + * @dev Decentralized Exchange. + */ + +import { TokenInterface } from "../../common/interfaces.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract QuickpswapResolver is Helpers, Events { + /** + * @dev Deposit Liquidity. + * @notice Deposit Liquidity to a QuickSwap pool. + * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amtA The amount of A tokens to deposit. + * @param unitAmt The unit amount of of amtB/amtA with slippage. + * @param slippage Slippage amount. + * @param getId ID to retrieve amtA. + * @param setId ID stores the amount of pools tokens received. + */ + function deposit( + address tokenA, + address tokenB, + uint256 amtA, + uint256 unitAmt, + uint256 slippage, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amtA); + + (uint _amtA, uint _amtB, uint _uniAmt) = _addLiquidity( + tokenA, + tokenB, + _amt, + unitAmt, + slippage + ); + setUint(setId, _uniAmt); + + _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setId); + } + + /** + * @dev Withdraw Liquidity. + * @notice Withdraw Liquidity from a QuickSwap pool. + * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param uniAmt The amount of pool tokens to withdraw. + * @param unitAmtA The unit amount of amtA/uniAmt with slippage. + * @param unitAmtB The unit amount of amtB/uniAmt with slippage. + * @param getId ID to retrieve uniAmt. + * @param setIds Array of IDs to store the amount tokens received. + */ + function withdraw( + address tokenA, + address tokenB, + uint256 uniAmt, + uint256 unitAmtA, + uint256 unitAmtB, + uint256 getId, + uint256[] calldata setIds + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, uniAmt); + + (uint _amtA, uint _amtB, uint _uniAmt) = _removeLiquidity( + tokenA, + tokenB, + _amt, + unitAmtA, + unitAmtB + ); + + setUint(setIds[0], _amtA); + setUint(setIds[1], _amtB); + + _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; + _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setIds); + } + + /** + * @dev Buy ETH/ERC20_Token. + * @notice Buy a token using a QuickSwap + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param buyAmt The amount of tokens to buy. + * @param unitAmt The unit amount of sellAmt/buyAmt with slippage. + * @param getId ID to retrieve buyAmt. + * @param setId ID to store the amount of tokens sold. + */ + function buy( + address buyAddr, + address sellAddr, + uint256 buyAmt, + uint256 unitAmt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _buyAmt = getUint(getId, buyAmt); + (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + + uint _slippageAmt = convert18ToDec(_sellAddr.decimals(), + wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt)) + ); + + checkPair(paths); + uint _expectedAmt = getExpectedSellAmt(paths, _buyAmt); + require(_slippageAmt >= _expectedAmt, "Too much slippage"); + + bool isEth = address(_sellAddr) == wmaticAddr; + convertMaticToWmatic(isEth, _sellAddr, _expectedAmt); + approve(_sellAddr, address(router), _expectedAmt); + + uint _sellAmt = router.swapTokensForExactTokens( + _buyAmt, + _expectedAmt, + paths, + address(this), + block.timestamp + 1 + )[0]; + + isEth = address(_buyAddr) == wmaticAddr; + convertWmaticToMatic(isEth, _buyAddr, _buyAmt); + + setUint(setId, _sellAmt); + + _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + } + + /** + * @dev Sell ETH/ERC20_Token. + * @notice Sell a token using a QuickSwap + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmt The unit amount of buyAmt/sellAmt with slippage. + * @param getId ID to retrieve sellAmt. + * @param setId ID stores the amount of token brought. + */ + function sell( + address buyAddr, + address sellAddr, + uint256 sellAmt, + uint256 unitAmt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _sellAmt = getUint(getId, sellAmt); + (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + + if (_sellAmt == uint(-1)) { + _sellAmt = sellAddr == maticAddr ? + address(this).balance : + _sellAddr.balanceOf(address(this)); + } + + uint _slippageAmt = convert18ToDec(_buyAddr.decimals(), + wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt)) + ); + + checkPair(paths); + uint _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); + require(_slippageAmt <= _expectedAmt, "Too much slippage"); + + bool isEth = address(_sellAddr) == wmaticAddr; + convertMaticToWmatic(isEth, _sellAddr, _sellAmt); + approve(_sellAddr, address(router), _sellAmt); + + uint _buyAmt = router.swapExactTokensForTokens( + _sellAmt, + _expectedAmt, + paths, + address(this), + block.timestamp + 1 + )[1]; + + isEth = address(_buyAddr) == wmaticAddr; + convertWmaticToMatic(isEth, _buyAddr, _buyAmt); + + setUint(setId, _buyAmt); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + } +} + +contract ConnectV2Quickswap is QuickpswapResolver { + string public constant name = "Quickpswap-v1.1"; +} From 5d01bc00d27f235620b2cd08bfe1c6d0a1c4aed0 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Tue, 7 Dec 2021 15:11:49 +0530 Subject: [PATCH 05/31] fixed quickswap polygon address --- contracts/polygon/connectors/quickswap/helpers.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/polygon/connectors/quickswap/helpers.sol b/contracts/polygon/connectors/quickswap/helpers.sol index 2199cfb6..07316a2c 100644 --- a/contracts/polygon/connectors/quickswap/helpers.sol +++ b/contracts/polygon/connectors/quickswap/helpers.sol @@ -10,7 +10,7 @@ abstract contract Helpers is DSMath, Basic { * @dev IQuickSwapRouter */ IQuickSwapRouter internal constant router = - IQuickSwapRouter(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F); + IQuickSwapRouter(0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff); function getExpectedBuyAmt(address[] memory paths, uint256 sellAmt) internal From baa2200cf2f69b6e0b58a7a10c977e9eabb14170 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Tue, 7 Dec 2021 22:57:37 +0530 Subject: [PATCH 06/31] added quickswap testcases --- test/quickswap-polygon/quickswap.test.js | 169 +++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 test/quickswap-polygon/quickswap.test.js diff --git a/test/quickswap-polygon/quickswap.test.js b/test/quickswap-polygon/quickswap.test.js new file mode 100644 index 00000000..e9d2d53b --- /dev/null +++ b/test/quickswap-polygon/quickswap.test.js @@ -0,0 +1,169 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { waffle, ethers } = hre; +const { provider } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") +const addLiquidity = require("../../scripts/addLiquidity"); + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); + +const connectV2QuickswapArtifacts = require("../../artifacts/contracts/polygon/connectors/quickswap/main.sol/ConnectV2Quickswap.json"); + +const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063" + +describe("Quickswap", function () { + const connectorName = "Quickpswap-v1.1" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + // await hre.network.provider.request({ + // method: "hardhat_reset", + // params: [ + // { + // forking: { + // jsonRpcUrl: hre.config.networks.hardhat.forking.url, + // blockNumber: 13005785, + // }, + // }, + // ], + // }); + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2QuickswapArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("100") // 1 ETH + const daiUnitAmount = ethers.utils.parseUnits("4", 6) // 1 ETH + const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH + const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }).timeout(10000000000); + + it("Should withdraw successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setIds = ["0", "0"] + + const spells = [ + { + connector: connectorName, + method: "withdraw", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + 0, + 0, + getId, + setIds + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) From c7fc18143ca479df82ff75e8873101e88613d813 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Sun, 12 Dec 2021 01:29:54 +0530 Subject: [PATCH 07/31] added typescript support --- .../polygon/connectors/quickswap/events.sol | 4 +- .../connectors/quickswap/interface.sol | 108 +++++--- .../polygon/connectors/quickswap/main.sol | 146 +++++++---- test/polygon/quickswap/quickswap.test.ts | 177 +++++++++++++ test/quickswap-polygon/quickswap.test.js | 169 ------------- test/sushiswap/sushiswap.test.js | 170 ------------- .../sushiswapIncentive/sushiIncentive.test.js | 237 ------------------ 7 files changed, 356 insertions(+), 655 deletions(-) create mode 100644 test/polygon/quickswap/quickswap.test.ts delete mode 100644 test/quickswap-polygon/quickswap.test.js delete mode 100644 test/sushiswap/sushiswap.test.js delete mode 100644 test/sushiswapIncentive/sushiIncentive.test.js diff --git a/contracts/polygon/connectors/quickswap/events.sol b/contracts/polygon/connectors/quickswap/events.sol index 2717b0a3..c8fc41d6 100644 --- a/contracts/polygon/connectors/quickswap/events.sol +++ b/contracts/polygon/connectors/quickswap/events.sol @@ -20,7 +20,7 @@ contract Events { uint256 getId, uint256[] setId ); - + event LogBuy( address indexed buyToken, address indexed sellToken, @@ -38,4 +38,4 @@ contract Events { uint256 getId, uint256 setId ); -} \ No newline at end of file +} diff --git a/contracts/polygon/connectors/quickswap/interface.sol b/contracts/polygon/connectors/quickswap/interface.sol index 4986dca7..438d89c3 100644 --- a/contracts/polygon/connectors/quickswap/interface.sol +++ b/contracts/polygon/connectors/quickswap/interface.sol @@ -2,56 +2,96 @@ pragma solidity ^0.7.0; interface IQuickSwapRouter { function factory() external pure returns (address); + function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, + uint256 amountADesired, + uint256 amountBDesired, + uint256 amountAMin, + uint256 amountBMin, address to, - uint deadline - ) external returns (uint amountA, uint amountB, uint liquidity); + uint256 deadline + ) + external + returns ( + uint256 amountA, + uint256 amountB, + uint256 liquidity + ); + function removeLiquidity( address tokenA, address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, + uint256 liquidity, + uint256 amountAMin, + uint256 amountBMin, address to, - uint deadline - ) external returns (uint amountA, uint amountB); - function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - function swapTokensForExactTokens( - uint amountOut, - uint amountInMax, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); + uint256 deadline + ) external returns (uint256 amountA, uint256 amountB); - function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); - function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); - function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); - function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); + function swapExactTokensForTokens( + uint256 amountIn, + uint256 amountOutMin, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); + + function swapTokensForExactTokens( + uint256 amountOut, + uint256 amountInMax, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); + + function quote( + uint256 amountA, + uint256 reserveA, + uint256 reserveB + ) external pure returns (uint256 amountB); + + function getAmountOut( + uint256 amountIn, + uint256 reserveIn, + uint256 reserveOut + ) external pure returns (uint256 amountOut); + + function getAmountIn( + uint256 amountOut, + uint256 reserveIn, + uint256 reserveOut + ) external pure returns (uint256 amountIn); + + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); + + function getAmountsIn(uint256 amountOut, address[] calldata path) + external + view + returns (uint256[] memory amounts); } interface IQuickSwapFactory { - function getPair(address tokenA, address tokenB) external view returns (address pair); - function allPairs(uint) external view returns (address pair); - function allPairsLength() external view returns (uint); + function getPair(address tokenA, address tokenB) + external + view + returns (address pair); + + function allPairs(uint256) external view returns (address pair); + + function allPairsLength() external view returns (uint256); function feeTo() external view returns (address); + function feeToSetter() external view returns (address); - function createPair(address tokenA, address tokenB) external returns (address pair); + function createPair(address tokenA, address tokenB) + external + returns (address pair); } diff --git a/contracts/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol index b8c0a79a..2cc07049 100644 --- a/contracts/polygon/connectors/quickswap/main.sol +++ b/contracts/polygon/connectors/quickswap/main.sol @@ -5,9 +5,9 @@ pragma solidity ^0.7.0; * @dev Decentralized Exchange. */ -import { TokenInterface } from "../../common/interfaces.sol"; -import { Helpers } from "./helpers.sol"; -import { Events } from "./events.sol"; +import {TokenInterface} from "../../common/interfaces.sol"; +import {Helpers} from "./helpers.sol"; +import {Events} from "./events.sol"; abstract contract QuickpswapResolver is Helpers, Events { /** @@ -20,7 +20,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param slippage Slippage amount. * @param getId ID to retrieve amtA. * @param setId ID stores the amount of pools tokens received. - */ + */ function deposit( address tokenA, address tokenB, @@ -29,20 +29,32 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 slippage, uint256 getId, uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, amtA); + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amtA); - (uint _amtA, uint _amtB, uint _uniAmt) = _addLiquidity( - tokenA, - tokenB, - _amt, - unitAmt, - slippage - ); + (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _addLiquidity( + tokenA, + tokenB, + _amt, + unitAmt, + slippage + ); setUint(setId, _uniAmt); - + _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setId); + _eventParam = abi.encode( + tokenA, + tokenB, + _amtA, + _amtB, + _uniAmt, + getId, + setId + ); } /** @@ -55,7 +67,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmtB The unit amount of amtB/uniAmt with slippage. * @param getId ID to retrieve uniAmt. * @param setIds Array of IDs to store the amount tokens received. - */ + */ function withdraw( address tokenA, address tokenB, @@ -64,10 +76,14 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmtB, uint256 getId, uint256[] calldata setIds - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, uniAmt); + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, uniAmt); - (uint _amtA, uint _amtB, uint _uniAmt) = _removeLiquidity( + (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _removeLiquidity( tokenA, tokenB, _amt, @@ -77,9 +93,17 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setIds[0], _amtA); setUint(setIds[1], _amtB); - + _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; - _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setIds); + _eventParam = abi.encode( + tokenA, + tokenB, + _amtA, + _amtB, + _uniAmt, + getId, + setIds + ); } /** @@ -91,7 +115,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmt The unit amount of sellAmt/buyAmt with slippage. * @param getId ID to retrieve buyAmt. * @param setId ID to store the amount of tokens sold. - */ + */ function buy( address buyAddr, address sellAddr, @@ -99,24 +123,35 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmt, uint256 getId, uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _buyAmt = getUint(getId, buyAmt); - (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); - address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _buyAmt = getUint(getId, buyAmt); + ( + TokenInterface _buyAddr, + TokenInterface _sellAddr + ) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths( + address(_buyAddr), + address(_sellAddr) + ); - uint _slippageAmt = convert18ToDec(_sellAddr.decimals(), + uint256 _slippageAmt = convert18ToDec( + _sellAddr.decimals(), wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt)) ); checkPair(paths); - uint _expectedAmt = getExpectedSellAmt(paths, _buyAmt); + uint256 _expectedAmt = getExpectedSellAmt(paths, _buyAmt); require(_slippageAmt >= _expectedAmt, "Too much slippage"); bool isEth = address(_sellAddr) == wmaticAddr; convertMaticToWmatic(isEth, _sellAddr, _expectedAmt); approve(_sellAddr, address(router), _expectedAmt); - uint _sellAmt = router.swapTokensForExactTokens( + uint256 _sellAmt = router.swapTokensForExactTokens( _buyAmt, _expectedAmt, paths, @@ -130,7 +165,14 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setId, _sellAmt); _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + _eventParam = abi.encode( + buyAddr, + sellAddr, + _buyAmt, + _sellAmt, + getId, + setId + ); } /** @@ -142,7 +184,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmt The unit amount of buyAmt/sellAmt with slippage. * @param getId ID to retrieve sellAmt. * @param setId ID stores the amount of token brought. - */ + */ function sell( address buyAddr, address sellAddr, @@ -150,30 +192,41 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmt, uint256 getId, uint256 setId - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _sellAmt = getUint(getId, sellAmt); - (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); - address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _sellAmt = getUint(getId, sellAmt); + ( + TokenInterface _buyAddr, + TokenInterface _sellAddr + ) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths( + address(_buyAddr), + address(_sellAddr) + ); - if (_sellAmt == uint(-1)) { - _sellAmt = sellAddr == maticAddr ? - address(this).balance : - _sellAddr.balanceOf(address(this)); + if (_sellAmt == uint256(-1)) { + _sellAmt = sellAddr == maticAddr + ? address(this).balance + : _sellAddr.balanceOf(address(this)); } - uint _slippageAmt = convert18ToDec(_buyAddr.decimals(), + uint256 _slippageAmt = convert18ToDec( + _buyAddr.decimals(), wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt)) ); checkPair(paths); - uint _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); + uint256 _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); require(_slippageAmt <= _expectedAmt, "Too much slippage"); bool isEth = address(_sellAddr) == wmaticAddr; convertMaticToWmatic(isEth, _sellAddr, _sellAmt); approve(_sellAddr, address(router), _sellAmt); - uint _buyAmt = router.swapExactTokensForTokens( + uint256 _buyAmt = router.swapExactTokensForTokens( _sellAmt, _expectedAmt, paths, @@ -187,7 +240,14 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setId, _buyAmt); _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); + _eventParam = abi.encode( + buyAddr, + sellAddr, + _buyAmt, + _sellAmt, + getId, + setId + ); } } diff --git a/test/polygon/quickswap/quickswap.test.ts b/test/polygon/quickswap/quickswap.test.ts new file mode 100644 index 00000000..b831dfe5 --- /dev/null +++ b/test/polygon/quickswap/quickswap.test.ts @@ -0,0 +1,177 @@ +import { expect } from "chai"; +import hre from "hardhat"; +const { waffle, ethers } = hre; +const { provider } = waffle; + +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addLiquidity } from "../../../scripts/tests/addLiquidity"; + +import { addresses } from "../../../scripts/tests/polygon/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2Quickswap__factory, ConnectV2Quickswap } from "../../../typechain"; +import type { Signer, Contract } from "ethers"; + +const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063"; + +describe("Quickswap", function() { + const connectorName = "Quickpswap-v1.1"; + + let dsaWallet0: Contract; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + const wallets = provider.getWallets(); + const [wallet0, wallet1, wallet2, wallet3] = wallets; + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785, + }, + }, + ], + }); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt( + abis.core.connectorsV2, + addresses.core.connectorsV2 + ); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2Quickswap__factory, + signer: masterSigner, + connectors: instaConnectorsV2, + }); + console.log("Connector address", connector.address); + }); + + it("Should have contracts deployed.", async function() { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function() { + it("Should build DSA v2", async function() { + dsaWallet0 = await buildDSAv2(wallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function() { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10"), + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( + ethers.utils.parseEther("10") + ); + + await addLiquidity( + "dai", + dsaWallet0.address, + ethers.utils.parseEther("100000") + ); + }); + + it("Deposit ETH & USDT into DSA wallet", async function() { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10"), + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( + ethers.utils.parseEther("10") + ); + + await addLiquidity( + "usdt", + dsaWallet0.address, + ethers.utils.parseEther("100000") + ); + }); + }); + + describe("Main", function() { + it("Should deposit successfully", async function() { + const ethAmount = ethers.utils.parseEther("100"); // 1 ETH + const daiUnitAmount = ethers.utils.parseUnits("4", 6); // 1 ETH + const usdtAmount = Number(ethers.utils.parseEther("400")) / Math.pow(10, 12); // 1 ETH + const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; + + const getId = "0"; + const setId = "0"; + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId, + ], + }, + ]; + + const tx = await dsaWallet0 + .connect(wallet0) + .cast(...encodeSpells(spells), wallet1.address); + let receipt = await tx.wait(); + }).timeout(10000000000); + + it("Should withdraw successfully", async function() { + const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + + const getId = "0"; + const setIds = ["0", "0"]; + + const spells = [ + { + connector: connectorName, + method: "withdraw", + args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds], + }, + ]; + + const tx = await dsaWallet0 + .connect(wallet0) + .cast(...encodeSpells(spells), wallet1.address); + let receipt = await tx.wait(); + }); + + it("Should buy successfully", async function() { + const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + + const getId = "0"; + const setId = "0"; + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId], + }, + ]; + + const tx = await dsaWallet0 + .connect(wallet0) + .cast(...encodeSpells(spells), wallet1.address); + let receipt = await tx.wait(); + }); + }); +}); diff --git a/test/quickswap-polygon/quickswap.test.js b/test/quickswap-polygon/quickswap.test.js deleted file mode 100644 index e9d2d53b..00000000 --- a/test/quickswap-polygon/quickswap.test.js +++ /dev/null @@ -1,169 +0,0 @@ -const { expect } = require("chai"); -const hre = require("hardhat"); -const { waffle, ethers } = hre; -const { provider } = waffle - -const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") -const buildDSAv2 = require("../../scripts/buildDSAv2") -const encodeSpells = require("../../scripts/encodeSpells.js") -const getMasterSigner = require("../../scripts/getMasterSigner") -const addLiquidity = require("../../scripts/addLiquidity"); - -const addresses = require("../../scripts/constant/addresses"); -const abis = require("../../scripts/constant/abis"); - -const connectV2QuickswapArtifacts = require("../../artifacts/contracts/polygon/connectors/quickswap/main.sol/ConnectV2Quickswap.json"); - -const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063" - -describe("Quickswap", function () { - const connectorName = "Quickpswap-v1.1" - - let dsaWallet0 - let masterSigner; - let instaConnectorsV2; - let connector; - - const wallets = provider.getWallets() - const [wallet0, wallet1, wallet2, wallet3] = wallets - before(async () => { - // await hre.network.provider.request({ - // method: "hardhat_reset", - // params: [ - // { - // forking: { - // jsonRpcUrl: hre.config.networks.hardhat.forking.url, - // blockNumber: 13005785, - // }, - // }, - // ], - // }); - masterSigner = await getMasterSigner(wallet3) - instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: connectV2QuickswapArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Connector address", connector.address) - }) - - it("Should have contracts deployed.", async function () { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; - expect(!!masterSigner.address).to.be.true; - }); - - describe("DSA wallet setup", function () { - it("Should build DSA v2", async function () { - dsaWallet0 = await buildDSAv2(wallet0.address) - expect(!!dsaWallet0.address).to.be.true; - }); - - it("Deposit ETH & DAI into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - - it("Deposit ETH & USDT into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - }); - - describe("Main", function () { - it("Should deposit successfully", async function () { - const ethAmount = ethers.utils.parseEther("100") // 1 ETH - const daiUnitAmount = ethers.utils.parseUnits("4", 6) // 1 ETH - const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH - const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId - ], - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }).timeout(10000000000); - - it("Should withdraw successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setIds = ["0", "0"] - - const spells = [ - { - connector: connectorName, - method: "withdraw", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - 0, - 0, - getId, - setIds - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - - it("Should buy successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "buy", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - }); -}) diff --git a/test/sushiswap/sushiswap.test.js b/test/sushiswap/sushiswap.test.js deleted file mode 100644 index baaf3876..00000000 --- a/test/sushiswap/sushiswap.test.js +++ /dev/null @@ -1,170 +0,0 @@ -const { expect } = require("chai"); -const hre = require("hardhat"); -const { waffle, ethers } = hre; -const { provider } = waffle - -const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") -const buildDSAv2 = require("../../scripts/buildDSAv2") -const encodeSpells = require("../../scripts/encodeSpells.js") -const getMasterSigner = require("../../scripts/getMasterSigner") -const addLiquidity = require("../../scripts/addLiquidity"); - -const addresses = require("../../scripts/constant/addresses"); -const abis = require("../../scripts/constant/abis"); - -const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); - -const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" - -describe("Sushiswap", function () { - const connectorName = "Sushiswap-v1" - - let dsaWallet0 - let masterSigner; - let instaConnectorsV2; - let connector; - - const wallets = provider.getWallets() - const [wallet0, wallet1, wallet2, wallet3] = wallets - before(async () => { - await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 13005785, - }, - }, - ], - }); - masterSigner = await getMasterSigner(wallet3) - instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: connectV2SushiswapArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Connector address", connector.address) - }) - - it("Should have contracts deployed.", async function () { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; - expect(!!masterSigner.address).to.be.true; - }); - - describe("DSA wallet setup", function () { - it("Should build DSA v2", async function () { - dsaWallet0 = await buildDSAv2(wallet0.address) - expect(!!dsaWallet0.address).to.be.true; - }); - - it("Deposit ETH & DAI into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - - it("Deposit ETH & USDT into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - }); - - describe("Main", function () { - - it("Should deposit successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId - ], - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }).timeout(10000000000); - - it("Should withdraw successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setIds = ["0", "0"] - - const spells = [ - { - connector: connectorName, - method: "withdraw", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - 0, - 0, - getId, - setIds - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - - it("Should buy successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "buy", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - }); -}) \ No newline at end of file diff --git a/test/sushiswapIncentive/sushiIncentive.test.js b/test/sushiswapIncentive/sushiIncentive.test.js deleted file mode 100644 index 1b2fd01b..00000000 --- a/test/sushiswapIncentive/sushiIncentive.test.js +++ /dev/null @@ -1,237 +0,0 @@ -const { expect } = require("chai"); -const hre = require("hardhat"); -const { waffle, ethers } = hre; -const { provider } = waffle - -const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") -const buildDSAv2 = require("../../scripts/buildDSAv2") -const encodeSpells = require("../../scripts/encodeSpells.js") -const getMasterSigner = require("../../scripts/getMasterSigner") -const addLiquidity = require("../../scripts/addLiquidity"); - -const addresses = require("../../scripts/constant/addresses"); -const abis = require("../../scripts/constant/abis"); - -const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); -const connectV2SushiswapIncentiveArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushi-incentive/main.sol/ConnectV2SushiswapIncentive.json"); - -const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" -const WETH_ADDR = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - -describe("Sushiswap", function () { - const connectorName = "Sushiswap-v1" - const incentiveConnectorName = "Sushiswp-Incentive-v1" - - let dsaWallet0 - let masterSigner; - let instaConnectorsV2; - let connector, connectorIncentive; - - const wallets = provider.getWallets() - const [wallet0, wallet1, wallet2, wallet3] = wallets - before(async () => { - await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 13005785, - }, - }, - ], - }); - masterSigner = await getMasterSigner(wallet3) - instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: connectV2SushiswapArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Connector address", connector.address) - - connectorIncentive = await deployAndEnableConnector({ - connectorName: incentiveConnectorName, - contractArtifact: connectV2SushiswapIncentiveArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Incentive Connector address", connectorIncentive.address) - }) - - it("Should have contracts deployed.", async function () { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; - expect(!!masterSigner.address).to.be.true; - }); - - describe("DSA wallet setup", function () { - it("Should build DSA v2", async function () { - dsaWallet0 = await buildDSAv2(wallet0.address) - expect(!!dsaWallet0.address).to.be.true; - }); - - it("Deposit ETH & DAI into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - - it("Deposit ETH & USDT into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - }); - - describe("Main", function () { - - it("Should deposit successfully", async function () { - const ethAmount = ethers.utils.parseEther("2") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId - ], - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - await tx.wait() - - describe("Incentive", () => { - it("Should deposit successfully", async () => { - const getId = 0 - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "deposit", - args: [ - WETH_ADDR, - DAI_ADDR, - ethers.utils.parseEther("10"), - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - - it("Should harvest successfully", async () => { - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "harvest", - args: [ - WETH_ADDR, - DAI_ADDR, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - - it("Should harvest and withdraw successfully", async () => { - const getId = 0 - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "withdrawAndHarvest", - args: [ - WETH_ADDR, - DAI_ADDR, - ethers.utils.parseEther("1"), - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - - it("Should withdraw successfully", async () => { - const getId = 0 - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "withdraw", - args: [ - WETH_ADDR, - DAI_ADDR, - ethers.utils.parseEther("1"), - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - }) - }).timeout(10000000000); - - it("Should buy successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "buy", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - }); -}) \ No newline at end of file From 4162176d96db103dacbe171688fd1c6552092116 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Sun, 12 Dec 2021 01:31:48 +0530 Subject: [PATCH 08/31] Merge branch 'feat/quickswap' of https://github.com/Instadapp/dsa-connectors into feat/quickswap --- .../polygon/connectors/quickswap/events.sol | 8 + .../connectors/quickswap/interface.sol | 53 ++++ .../polygon/connectors/quickswap/main.sol | 100 ++++++++ test/quickswap-polygon/quickswap.test.js | 169 +++++++++++++ test/sushiswap/sushiswap.test.js | 170 +++++++++++++ .../sushiswapIncentive/sushiIncentive.test.js | 237 ++++++++++++++++++ 6 files changed, 737 insertions(+) create mode 100644 test/quickswap-polygon/quickswap.test.js create mode 100644 test/sushiswap/sushiswap.test.js create mode 100644 test/sushiswapIncentive/sushiIncentive.test.js diff --git a/contracts/polygon/connectors/quickswap/events.sol b/contracts/polygon/connectors/quickswap/events.sol index c8fc41d6..5f8c0f48 100644 --- a/contracts/polygon/connectors/quickswap/events.sol +++ b/contracts/polygon/connectors/quickswap/events.sol @@ -20,7 +20,11 @@ contract Events { uint256 getId, uint256[] setId ); +<<<<<<< HEAD +======= + +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 event LogBuy( address indexed buyToken, address indexed sellToken, @@ -38,4 +42,8 @@ contract Events { uint256 getId, uint256 setId ); +<<<<<<< HEAD } +======= +} +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 diff --git a/contracts/polygon/connectors/quickswap/interface.sol b/contracts/polygon/connectors/quickswap/interface.sol index 438d89c3..65c0482d 100644 --- a/contracts/polygon/connectors/quickswap/interface.sol +++ b/contracts/polygon/connectors/quickswap/interface.sol @@ -2,12 +2,16 @@ pragma solidity ^0.7.0; interface IQuickSwapRouter { function factory() external pure returns (address); +<<<<<<< HEAD +======= +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, +<<<<<<< HEAD uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, @@ -94,4 +98,53 @@ interface IQuickSwapFactory { function createPair(address tokenA, address tokenB) external returns (address pair); +======= + uint amountADesired, + uint amountBDesired, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB, uint liquidity); + function removeLiquidity( + address tokenA, + address tokenB, + uint liquidity, + uint amountAMin, + uint amountBMin, + address to, + uint deadline + ) external returns (uint amountA, uint amountB); + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + function swapTokensForExactTokens( + uint amountOut, + uint amountInMax, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); + + function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); + function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); + function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); + function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); + function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); +} + +interface IQuickSwapFactory { + function getPair(address tokenA, address tokenB) external view returns (address pair); + function allPairs(uint) external view returns (address pair); + function allPairsLength() external view returns (uint); + + function feeTo() external view returns (address); + function feeToSetter() external view returns (address); + + function createPair(address tokenA, address tokenB) external returns (address pair); +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } diff --git a/contracts/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol index 2cc07049..de7a1926 100644 --- a/contracts/polygon/connectors/quickswap/main.sol +++ b/contracts/polygon/connectors/quickswap/main.sol @@ -5,9 +5,15 @@ pragma solidity ^0.7.0; * @dev Decentralized Exchange. */ +<<<<<<< HEAD import {TokenInterface} from "../../common/interfaces.sol"; import {Helpers} from "./helpers.sol"; import {Events} from "./events.sol"; +======= +import { TokenInterface } from "../../common/interfaces.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 abstract contract QuickpswapResolver is Helpers, Events { /** @@ -20,7 +26,11 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param slippage Slippage amount. * @param getId ID to retrieve amtA. * @param setId ID stores the amount of pools tokens received. +<<<<<<< HEAD */ +======= + */ +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function deposit( address tokenA, address tokenB, @@ -29,6 +39,7 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 slippage, uint256 getId, uint256 setId +<<<<<<< HEAD ) external payable @@ -55,6 +66,22 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setId ); +======= + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amtA); + + (uint _amtA, uint _amtB, uint _uniAmt) = _addLiquidity( + tokenA, + tokenB, + _amt, + unitAmt, + slippage + ); + setUint(setId, _uniAmt); + + _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setId); +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } /** @@ -67,7 +94,11 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmtB The unit amount of amtB/uniAmt with slippage. * @param getId ID to retrieve uniAmt. * @param setIds Array of IDs to store the amount tokens received. +<<<<<<< HEAD */ +======= + */ +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function withdraw( address tokenA, address tokenB, @@ -76,6 +107,7 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmtB, uint256 getId, uint256[] calldata setIds +<<<<<<< HEAD ) external payable @@ -84,6 +116,12 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 _amt = getUint(getId, uniAmt); (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _removeLiquidity( +======= + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, uniAmt); + + (uint _amtA, uint _amtB, uint _uniAmt) = _removeLiquidity( +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 tokenA, tokenB, _amt, @@ -93,6 +131,7 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setIds[0], _amtA); setUint(setIds[1], _amtB); +<<<<<<< HEAD _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; _eventParam = abi.encode( @@ -104,6 +143,11 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setIds ); +======= + + _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; + _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setIds); +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } /** @@ -115,7 +159,11 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmt The unit amount of sellAmt/buyAmt with slippage. * @param getId ID to retrieve buyAmt. * @param setId ID to store the amount of tokens sold. +<<<<<<< HEAD */ +======= + */ +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function buy( address buyAddr, address sellAddr, @@ -123,6 +171,7 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmt, uint256 getId, uint256 setId +<<<<<<< HEAD ) external payable @@ -140,18 +189,34 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 _slippageAmt = convert18ToDec( _sellAddr.decimals(), +======= + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _buyAmt = getUint(getId, buyAmt); + (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + + uint _slippageAmt = convert18ToDec(_sellAddr.decimals(), +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt)) ); checkPair(paths); +<<<<<<< HEAD uint256 _expectedAmt = getExpectedSellAmt(paths, _buyAmt); +======= + uint _expectedAmt = getExpectedSellAmt(paths, _buyAmt); +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 require(_slippageAmt >= _expectedAmt, "Too much slippage"); bool isEth = address(_sellAddr) == wmaticAddr; convertMaticToWmatic(isEth, _sellAddr, _expectedAmt); approve(_sellAddr, address(router), _expectedAmt); +<<<<<<< HEAD uint256 _sellAmt = router.swapTokensForExactTokens( +======= + uint _sellAmt = router.swapTokensForExactTokens( +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 _buyAmt, _expectedAmt, paths, @@ -165,6 +230,7 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setId, _sellAmt); _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)"; +<<<<<<< HEAD _eventParam = abi.encode( buyAddr, sellAddr, @@ -173,6 +239,9 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setId ); +======= + _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } /** @@ -184,7 +253,11 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmt The unit amount of buyAmt/sellAmt with slippage. * @param getId ID to retrieve sellAmt. * @param setId ID stores the amount of token brought. +<<<<<<< HEAD */ +======= + */ +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function sell( address buyAddr, address sellAddr, @@ -192,6 +265,7 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmt, uint256 getId, uint256 setId +<<<<<<< HEAD ) external payable @@ -215,18 +289,40 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 _slippageAmt = convert18ToDec( _buyAddr.decimals(), +======= + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _sellAmt = getUint(getId, sellAmt); + (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); + + if (_sellAmt == uint(-1)) { + _sellAmt = sellAddr == maticAddr ? + address(this).balance : + _sellAddr.balanceOf(address(this)); + } + + uint _slippageAmt = convert18ToDec(_buyAddr.decimals(), +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt)) ); checkPair(paths); +<<<<<<< HEAD uint256 _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); +======= + uint _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 require(_slippageAmt <= _expectedAmt, "Too much slippage"); bool isEth = address(_sellAddr) == wmaticAddr; convertMaticToWmatic(isEth, _sellAddr, _sellAmt); approve(_sellAddr, address(router), _sellAmt); +<<<<<<< HEAD uint256 _buyAmt = router.swapExactTokensForTokens( +======= + uint _buyAmt = router.swapExactTokensForTokens( +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 _sellAmt, _expectedAmt, paths, @@ -240,6 +336,7 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setId, _buyAmt); _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; +<<<<<<< HEAD _eventParam = abi.encode( buyAddr, sellAddr, @@ -248,6 +345,9 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setId ); +======= + _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); +>>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } } diff --git a/test/quickswap-polygon/quickswap.test.js b/test/quickswap-polygon/quickswap.test.js new file mode 100644 index 00000000..e9d2d53b --- /dev/null +++ b/test/quickswap-polygon/quickswap.test.js @@ -0,0 +1,169 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { waffle, ethers } = hre; +const { provider } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") +const addLiquidity = require("../../scripts/addLiquidity"); + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); + +const connectV2QuickswapArtifacts = require("../../artifacts/contracts/polygon/connectors/quickswap/main.sol/ConnectV2Quickswap.json"); + +const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063" + +describe("Quickswap", function () { + const connectorName = "Quickpswap-v1.1" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + // await hre.network.provider.request({ + // method: "hardhat_reset", + // params: [ + // { + // forking: { + // jsonRpcUrl: hre.config.networks.hardhat.forking.url, + // blockNumber: 13005785, + // }, + // }, + // ], + // }); + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2QuickswapArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("100") // 1 ETH + const daiUnitAmount = ethers.utils.parseUnits("4", 6) // 1 ETH + const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH + const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }).timeout(10000000000); + + it("Should withdraw successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setIds = ["0", "0"] + + const spells = [ + { + connector: connectorName, + method: "withdraw", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + 0, + 0, + getId, + setIds + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) diff --git a/test/sushiswap/sushiswap.test.js b/test/sushiswap/sushiswap.test.js new file mode 100644 index 00000000..baaf3876 --- /dev/null +++ b/test/sushiswap/sushiswap.test.js @@ -0,0 +1,170 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { waffle, ethers } = hre; +const { provider } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") +const addLiquidity = require("../../scripts/addLiquidity"); + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); + +const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); + +const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" + +describe("Sushiswap", function () { + const connectorName = "Sushiswap-v1" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785, + }, + }, + ], + }); + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2SushiswapArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }).timeout(10000000000); + + it("Should withdraw successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setIds = ["0", "0"] + + const spells = [ + { + connector: connectorName, + method: "withdraw", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + 0, + 0, + getId, + setIds + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) \ No newline at end of file diff --git a/test/sushiswapIncentive/sushiIncentive.test.js b/test/sushiswapIncentive/sushiIncentive.test.js new file mode 100644 index 00000000..1b2fd01b --- /dev/null +++ b/test/sushiswapIncentive/sushiIncentive.test.js @@ -0,0 +1,237 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { waffle, ethers } = hre; +const { provider } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") +const addLiquidity = require("../../scripts/addLiquidity"); + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); + +const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); +const connectV2SushiswapIncentiveArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushi-incentive/main.sol/ConnectV2SushiswapIncentive.json"); + +const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" +const WETH_ADDR = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + +describe("Sushiswap", function () { + const connectorName = "Sushiswap-v1" + const incentiveConnectorName = "Sushiswp-Incentive-v1" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector, connectorIncentive; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785, + }, + }, + ], + }); + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2SushiswapArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + + connectorIncentive = await deployAndEnableConnector({ + connectorName: incentiveConnectorName, + contractArtifact: connectV2SushiswapIncentiveArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Incentive Connector address", connectorIncentive.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("2") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + await tx.wait() + + describe("Incentive", () => { + it("Should deposit successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "deposit", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("10"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should harvest successfully", async () => { + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "harvest", + args: [ + WETH_ADDR, + DAI_ADDR, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should harvest and withdraw successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "withdrawAndHarvest", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("1"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should withdraw successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "withdraw", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("1"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + }) + }).timeout(10000000000); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) \ No newline at end of file From 7b8659b91cbe08bd148b43a0fe31802448969b75 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Sun, 12 Dec 2021 01:33:32 +0530 Subject: [PATCH 09/31] update --- test/quickswap-polygon/quickswap.test.js | 169 ------------- test/sushiswap/sushiswap.test.js | 170 ------------- .../sushiswapIncentive/sushiIncentive.test.js | 237 ------------------ 3 files changed, 576 deletions(-) delete mode 100644 test/quickswap-polygon/quickswap.test.js delete mode 100644 test/sushiswap/sushiswap.test.js delete mode 100644 test/sushiswapIncentive/sushiIncentive.test.js diff --git a/test/quickswap-polygon/quickswap.test.js b/test/quickswap-polygon/quickswap.test.js deleted file mode 100644 index e9d2d53b..00000000 --- a/test/quickswap-polygon/quickswap.test.js +++ /dev/null @@ -1,169 +0,0 @@ -const { expect } = require("chai"); -const hre = require("hardhat"); -const { waffle, ethers } = hre; -const { provider } = waffle - -const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") -const buildDSAv2 = require("../../scripts/buildDSAv2") -const encodeSpells = require("../../scripts/encodeSpells.js") -const getMasterSigner = require("../../scripts/getMasterSigner") -const addLiquidity = require("../../scripts/addLiquidity"); - -const addresses = require("../../scripts/constant/addresses"); -const abis = require("../../scripts/constant/abis"); - -const connectV2QuickswapArtifacts = require("../../artifacts/contracts/polygon/connectors/quickswap/main.sol/ConnectV2Quickswap.json"); - -const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063" - -describe("Quickswap", function () { - const connectorName = "Quickpswap-v1.1" - - let dsaWallet0 - let masterSigner; - let instaConnectorsV2; - let connector; - - const wallets = provider.getWallets() - const [wallet0, wallet1, wallet2, wallet3] = wallets - before(async () => { - // await hre.network.provider.request({ - // method: "hardhat_reset", - // params: [ - // { - // forking: { - // jsonRpcUrl: hre.config.networks.hardhat.forking.url, - // blockNumber: 13005785, - // }, - // }, - // ], - // }); - masterSigner = await getMasterSigner(wallet3) - instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: connectV2QuickswapArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Connector address", connector.address) - }) - - it("Should have contracts deployed.", async function () { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; - expect(!!masterSigner.address).to.be.true; - }); - - describe("DSA wallet setup", function () { - it("Should build DSA v2", async function () { - dsaWallet0 = await buildDSAv2(wallet0.address) - expect(!!dsaWallet0.address).to.be.true; - }); - - it("Deposit ETH & DAI into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - - it("Deposit ETH & USDT into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - }); - - describe("Main", function () { - it("Should deposit successfully", async function () { - const ethAmount = ethers.utils.parseEther("100") // 1 ETH - const daiUnitAmount = ethers.utils.parseUnits("4", 6) // 1 ETH - const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH - const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId - ], - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }).timeout(10000000000); - - it("Should withdraw successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setIds = ["0", "0"] - - const spells = [ - { - connector: connectorName, - method: "withdraw", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - 0, - 0, - getId, - setIds - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - - it("Should buy successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "buy", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - }); -}) diff --git a/test/sushiswap/sushiswap.test.js b/test/sushiswap/sushiswap.test.js deleted file mode 100644 index baaf3876..00000000 --- a/test/sushiswap/sushiswap.test.js +++ /dev/null @@ -1,170 +0,0 @@ -const { expect } = require("chai"); -const hre = require("hardhat"); -const { waffle, ethers } = hre; -const { provider } = waffle - -const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") -const buildDSAv2 = require("../../scripts/buildDSAv2") -const encodeSpells = require("../../scripts/encodeSpells.js") -const getMasterSigner = require("../../scripts/getMasterSigner") -const addLiquidity = require("../../scripts/addLiquidity"); - -const addresses = require("../../scripts/constant/addresses"); -const abis = require("../../scripts/constant/abis"); - -const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); - -const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" - -describe("Sushiswap", function () { - const connectorName = "Sushiswap-v1" - - let dsaWallet0 - let masterSigner; - let instaConnectorsV2; - let connector; - - const wallets = provider.getWallets() - const [wallet0, wallet1, wallet2, wallet3] = wallets - before(async () => { - await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 13005785, - }, - }, - ], - }); - masterSigner = await getMasterSigner(wallet3) - instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: connectV2SushiswapArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Connector address", connector.address) - }) - - it("Should have contracts deployed.", async function () { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; - expect(!!masterSigner.address).to.be.true; - }); - - describe("DSA wallet setup", function () { - it("Should build DSA v2", async function () { - dsaWallet0 = await buildDSAv2(wallet0.address) - expect(!!dsaWallet0.address).to.be.true; - }); - - it("Deposit ETH & DAI into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - - it("Deposit ETH & USDT into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - }); - - describe("Main", function () { - - it("Should deposit successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId - ], - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }).timeout(10000000000); - - it("Should withdraw successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setIds = ["0", "0"] - - const spells = [ - { - connector: connectorName, - method: "withdraw", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - 0, - 0, - getId, - setIds - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - - it("Should buy successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "buy", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - }); -}) \ No newline at end of file diff --git a/test/sushiswapIncentive/sushiIncentive.test.js b/test/sushiswapIncentive/sushiIncentive.test.js deleted file mode 100644 index 1b2fd01b..00000000 --- a/test/sushiswapIncentive/sushiIncentive.test.js +++ /dev/null @@ -1,237 +0,0 @@ -const { expect } = require("chai"); -const hre = require("hardhat"); -const { waffle, ethers } = hre; -const { provider } = waffle - -const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") -const buildDSAv2 = require("../../scripts/buildDSAv2") -const encodeSpells = require("../../scripts/encodeSpells.js") -const getMasterSigner = require("../../scripts/getMasterSigner") -const addLiquidity = require("../../scripts/addLiquidity"); - -const addresses = require("../../scripts/constant/addresses"); -const abis = require("../../scripts/constant/abis"); - -const connectV2SushiswapArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushiswap/main.sol/ConnectV2Sushiswap.json"); -const connectV2SushiswapIncentiveArtifacts = require("../../artifacts/contracts/mainnet/connectors/sushi-incentive/main.sol/ConnectV2SushiswapIncentive.json"); - -const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" -const WETH_ADDR = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - -describe("Sushiswap", function () { - const connectorName = "Sushiswap-v1" - const incentiveConnectorName = "Sushiswp-Incentive-v1" - - let dsaWallet0 - let masterSigner; - let instaConnectorsV2; - let connector, connectorIncentive; - - const wallets = provider.getWallets() - const [wallet0, wallet1, wallet2, wallet3] = wallets - before(async () => { - await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 13005785, - }, - }, - ], - }); - masterSigner = await getMasterSigner(wallet3) - instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: connectV2SushiswapArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Connector address", connector.address) - - connectorIncentive = await deployAndEnableConnector({ - connectorName: incentiveConnectorName, - contractArtifact: connectV2SushiswapIncentiveArtifacts, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Incentive Connector address", connectorIncentive.address) - }) - - it("Should have contracts deployed.", async function () { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; - expect(!!masterSigner.address).to.be.true; - }); - - describe("DSA wallet setup", function () { - it("Should build DSA v2", async function () { - dsaWallet0 = await buildDSAv2(wallet0.address) - expect(!!dsaWallet0.address).to.be.true; - }); - - it("Deposit ETH & DAI into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - - it("Deposit ETH & USDT into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); - }); - - describe("Main", function () { - - it("Should deposit successfully", async function () { - const ethAmount = ethers.utils.parseEther("2") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const usdtAmount = ethers.utils.parseEther("400") / Math.pow(10, 12) // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId - ], - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - await tx.wait() - - describe("Incentive", () => { - it("Should deposit successfully", async () => { - const getId = 0 - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "deposit", - args: [ - WETH_ADDR, - DAI_ADDR, - ethers.utils.parseEther("10"), - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - - it("Should harvest successfully", async () => { - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "harvest", - args: [ - WETH_ADDR, - DAI_ADDR, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - - it("Should harvest and withdraw successfully", async () => { - const getId = 0 - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "withdrawAndHarvest", - args: [ - WETH_ADDR, - DAI_ADDR, - ethers.utils.parseEther("1"), - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - - it("Should withdraw successfully", async () => { - const getId = 0 - const setId = 0 - const spells = [ - { - connector: incentiveConnectorName, - method: "withdraw", - args: [ - WETH_ADDR, - DAI_ADDR, - ethers.utils.parseEther("1"), - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) - await tx.wait(); - }) - }) - }).timeout(10000000000); - - it("Should buy successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" - - const getId = "0" - const setId = "0" - - const spells = [ - { - connector: connectorName, - method: "buy", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); - }); -}) \ No newline at end of file From 494b5fd7c4135e52dc749c27f7af3d2f93c7185b Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Sun, 12 Dec 2021 01:58:53 +0530 Subject: [PATCH 10/31] fixed bugs --- .../polygon/connectors/quickswap/events.sol | 8 -- .../connectors/quickswap/interface.sol | 53 ---------- .../polygon/connectors/quickswap/main.sol | 100 ------------------ hardhat.config.js | 90 ---------------- 4 files changed, 251 deletions(-) delete mode 100644 hardhat.config.js diff --git a/contracts/polygon/connectors/quickswap/events.sol b/contracts/polygon/connectors/quickswap/events.sol index 5f8c0f48..c8fc41d6 100644 --- a/contracts/polygon/connectors/quickswap/events.sol +++ b/contracts/polygon/connectors/quickswap/events.sol @@ -20,11 +20,7 @@ contract Events { uint256 getId, uint256[] setId ); -<<<<<<< HEAD -======= - ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 event LogBuy( address indexed buyToken, address indexed sellToken, @@ -42,8 +38,4 @@ contract Events { uint256 getId, uint256 setId ); -<<<<<<< HEAD } -======= -} ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 diff --git a/contracts/polygon/connectors/quickswap/interface.sol b/contracts/polygon/connectors/quickswap/interface.sol index 65c0482d..438d89c3 100644 --- a/contracts/polygon/connectors/quickswap/interface.sol +++ b/contracts/polygon/connectors/quickswap/interface.sol @@ -2,16 +2,12 @@ pragma solidity ^0.7.0; interface IQuickSwapRouter { function factory() external pure returns (address); -<<<<<<< HEAD -======= ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, -<<<<<<< HEAD uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, @@ -98,53 +94,4 @@ interface IQuickSwapFactory { function createPair(address tokenA, address tokenB) external returns (address pair); -======= - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB, uint liquidity); - function removeLiquidity( - address tokenA, - address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB); - function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - function swapTokensForExactTokens( - uint amountOut, - uint amountInMax, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - - function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); - function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); - function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); - function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); -} - -interface IQuickSwapFactory { - function getPair(address tokenA, address tokenB) external view returns (address pair); - function allPairs(uint) external view returns (address pair); - function allPairsLength() external view returns (uint); - - function feeTo() external view returns (address); - function feeToSetter() external view returns (address); - - function createPair(address tokenA, address tokenB) external returns (address pair); ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } diff --git a/contracts/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol index de7a1926..2cc07049 100644 --- a/contracts/polygon/connectors/quickswap/main.sol +++ b/contracts/polygon/connectors/quickswap/main.sol @@ -5,15 +5,9 @@ pragma solidity ^0.7.0; * @dev Decentralized Exchange. */ -<<<<<<< HEAD import {TokenInterface} from "../../common/interfaces.sol"; import {Helpers} from "./helpers.sol"; import {Events} from "./events.sol"; -======= -import { TokenInterface } from "../../common/interfaces.sol"; -import { Helpers } from "./helpers.sol"; -import { Events } from "./events.sol"; ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 abstract contract QuickpswapResolver is Helpers, Events { /** @@ -26,11 +20,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param slippage Slippage amount. * @param getId ID to retrieve amtA. * @param setId ID stores the amount of pools tokens received. -<<<<<<< HEAD */ -======= - */ ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function deposit( address tokenA, address tokenB, @@ -39,7 +29,6 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 slippage, uint256 getId, uint256 setId -<<<<<<< HEAD ) external payable @@ -66,22 +55,6 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setId ); -======= - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, amtA); - - (uint _amtA, uint _amtB, uint _uniAmt) = _addLiquidity( - tokenA, - tokenB, - _amt, - unitAmt, - slippage - ); - setUint(setId, _uniAmt); - - _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setId); ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } /** @@ -94,11 +67,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmtB The unit amount of amtB/uniAmt with slippage. * @param getId ID to retrieve uniAmt. * @param setIds Array of IDs to store the amount tokens received. -<<<<<<< HEAD */ -======= - */ ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function withdraw( address tokenA, address tokenB, @@ -107,7 +76,6 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmtB, uint256 getId, uint256[] calldata setIds -<<<<<<< HEAD ) external payable @@ -116,12 +84,6 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 _amt = getUint(getId, uniAmt); (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _removeLiquidity( -======= - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _amt = getUint(getId, uniAmt); - - (uint _amtA, uint _amtB, uint _uniAmt) = _removeLiquidity( ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 tokenA, tokenB, _amt, @@ -131,7 +93,6 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setIds[0], _amtA); setUint(setIds[1], _amtB); -<<<<<<< HEAD _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; _eventParam = abi.encode( @@ -143,11 +104,6 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setIds ); -======= - - _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; - _eventParam = abi.encode(tokenA, tokenB, _amtA, _amtB, _uniAmt, getId, setIds); ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } /** @@ -159,11 +115,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmt The unit amount of sellAmt/buyAmt with slippage. * @param getId ID to retrieve buyAmt. * @param setId ID to store the amount of tokens sold. -<<<<<<< HEAD */ -======= - */ ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function buy( address buyAddr, address sellAddr, @@ -171,7 +123,6 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmt, uint256 getId, uint256 setId -<<<<<<< HEAD ) external payable @@ -189,34 +140,18 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 _slippageAmt = convert18ToDec( _sellAddr.decimals(), -======= - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _buyAmt = getUint(getId, buyAmt); - (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); - address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); - - uint _slippageAmt = convert18ToDec(_sellAddr.decimals(), ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt)) ); checkPair(paths); -<<<<<<< HEAD uint256 _expectedAmt = getExpectedSellAmt(paths, _buyAmt); -======= - uint _expectedAmt = getExpectedSellAmt(paths, _buyAmt); ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 require(_slippageAmt >= _expectedAmt, "Too much slippage"); bool isEth = address(_sellAddr) == wmaticAddr; convertMaticToWmatic(isEth, _sellAddr, _expectedAmt); approve(_sellAddr, address(router), _expectedAmt); -<<<<<<< HEAD uint256 _sellAmt = router.swapTokensForExactTokens( -======= - uint _sellAmt = router.swapTokensForExactTokens( ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 _buyAmt, _expectedAmt, paths, @@ -230,7 +165,6 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setId, _sellAmt); _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)"; -<<<<<<< HEAD _eventParam = abi.encode( buyAddr, sellAddr, @@ -239,9 +173,6 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setId ); -======= - _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } /** @@ -253,11 +184,7 @@ abstract contract QuickpswapResolver is Helpers, Events { * @param unitAmt The unit amount of buyAmt/sellAmt with slippage. * @param getId ID to retrieve sellAmt. * @param setId ID stores the amount of token brought. -<<<<<<< HEAD */ -======= - */ ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 function sell( address buyAddr, address sellAddr, @@ -265,7 +192,6 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 unitAmt, uint256 getId, uint256 setId -<<<<<<< HEAD ) external payable @@ -289,40 +215,18 @@ abstract contract QuickpswapResolver is Helpers, Events { uint256 _slippageAmt = convert18ToDec( _buyAddr.decimals(), -======= - ) external payable returns (string memory _eventName, bytes memory _eventParam) { - uint _sellAmt = getUint(getId, sellAmt); - (TokenInterface _buyAddr, TokenInterface _sellAddr) = changeMaticAddress(buyAddr, sellAddr); - address[] memory paths = getPaths(address(_buyAddr), address(_sellAddr)); - - if (_sellAmt == uint(-1)) { - _sellAmt = sellAddr == maticAddr ? - address(this).balance : - _sellAddr.balanceOf(address(this)); - } - - uint _slippageAmt = convert18ToDec(_buyAddr.decimals(), ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt)) ); checkPair(paths); -<<<<<<< HEAD uint256 _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); -======= - uint _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 require(_slippageAmt <= _expectedAmt, "Too much slippage"); bool isEth = address(_sellAddr) == wmaticAddr; convertMaticToWmatic(isEth, _sellAddr, _sellAmt); approve(_sellAddr, address(router), _sellAmt); -<<<<<<< HEAD uint256 _buyAmt = router.swapExactTokensForTokens( -======= - uint _buyAmt = router.swapExactTokensForTokens( ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 _sellAmt, _expectedAmt, paths, @@ -336,7 +240,6 @@ abstract contract QuickpswapResolver is Helpers, Events { setUint(setId, _buyAmt); _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; -<<<<<<< HEAD _eventParam = abi.encode( buyAddr, sellAddr, @@ -345,9 +248,6 @@ abstract contract QuickpswapResolver is Helpers, Events { getId, setId ); -======= - _eventParam = abi.encode(buyAddr, sellAddr, _buyAmt, _sellAmt, getId, setId); ->>>>>>> d9a7bfba85acceb302ac1d1dd854e9b380976557 } } diff --git a/hardhat.config.js b/hardhat.config.js deleted file mode 100644 index 7d88c978..00000000 --- a/hardhat.config.js +++ /dev/null @@ -1,90 +0,0 @@ -require("@nomiclabs/hardhat-waffle"); -require("@nomiclabs/hardhat-ethers"); -require("@tenderly/hardhat-tenderly"); -require("@nomiclabs/hardhat-etherscan"); -require("@nomiclabs/hardhat-web3"); -require("hardhat-deploy"); -require("hardhat-deploy-ethers"); -require("dotenv").config(); - -const { utils } = require("ethers"); - -const PRIVATE_KEY = process.env.PRIVATE_KEY; -const ALCHEMY_ID = process.env.ALCHEMY_ID; -const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY; - -if (!process.env.ALCHEMY_ID) { - throw new Error("ENV Variable ALCHEMY_ID not set!"); -} - -/** - * @type import('hardhat/config').HardhatUserConfig - */ -module.exports = { - solidity: { - compilers: [ - { - version: "0.7.6", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - { - version: "0.6.0", - }, - { - version: "0.6.2", - }, - { - version: "0.6.12", - }, - { - version: "0.6.5", - }, - ], - }, - networks: { - // defaultNetwork: "hardhat", - kovan: { - url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_ID}`, - accounts: [`0x${PRIVATE_KEY}`], - }, - mainnet: { - url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, - accounts: [`0x${PRIVATE_KEY}`], - timeout: 150000, - gasPrice: parseInt(utils.parseUnits("30", "gwei")), - }, - rinkeby: { - url: `https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_ID}`, - accounts: [`0x${PRIVATE_KEY}`], - timeout: 150000, - }, - hardhat: { - forking: { - url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, - blockNumber: 12696000, - }, - blockGasLimit: 12000000, - }, - matic: { - url: "https://rpc-mainnet.maticvigil.com/", - accounts: [`0x${PRIVATE_KEY}`], - timeout: 150000, - gasPrice: parseInt(utils.parseUnits("1", "gwei")), - }, - }, - etherscan: { - apiKey: ETHERSCAN_API_KEY, - }, - tenderly: { - project: process.env.TENDERLY_PROJECT, - username: process.env.TENDERLY_USERNAME, - }, - mocha: { - timeout: 100 * 1000, - }, -}; \ No newline at end of file From 95ed18984f79c0adb70e1649de1a3197e97771b5 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Mon, 13 Dec 2021 21:17:28 +0530 Subject: [PATCH 11/31] added sushiswap tests --- .../mainnet/connectors/sushiswap/helpers.sol | 2 +- test/mainnet/sushiswap/sushiswap.test.ts | 331 ++++++++++++++++++ .../sushiswapIncentive.test.ts | 235 +++++++++++++ 3 files changed, 567 insertions(+), 1 deletion(-) create mode 100644 test/mainnet/sushiswap/sushiswap.test.ts create mode 100644 test/mainnet/sushiswapIncentive/sushiswapIncentive.test.ts diff --git a/contracts/mainnet/connectors/sushiswap/helpers.sol b/contracts/mainnet/connectors/sushiswap/helpers.sol index a1baa4c5..ea29a03f 100644 --- a/contracts/mainnet/connectors/sushiswap/helpers.sol +++ b/contracts/mainnet/connectors/sushiswap/helpers.sol @@ -102,7 +102,7 @@ abstract contract Helpers is DSMath, Basic { _amtA, _amtB, minAmtA, - minAmtA, + minAmtB, address(this), block.timestamp + 1 ); diff --git a/test/mainnet/sushiswap/sushiswap.test.ts b/test/mainnet/sushiswap/sushiswap.test.ts new file mode 100644 index 00000000..8257b47d --- /dev/null +++ b/test/mainnet/sushiswap/sushiswap.test.ts @@ -0,0 +1,331 @@ +import { expect } from "chai"; +import hre from "hardhat"; +const { waffle, ethers } = hre; +const { provider } = waffle; + +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addLiquidity } from "../../../scripts/tests/addLiquidity"; + +import { addresses } from "../../../scripts/tests/mainnet/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2Sushiswap__factory, ConnectV2Sushiswap } from "../../../typechain"; +import type { Signer, Contract } from "ethers"; + +const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" + +describe("Sushiswap", function () { + const connectorName = "Sushiswap-v1" + + let dsaWallet0: Contract; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785, + }, + }, + ], + }); + + masterSigner = await getMasterSigner() + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2Sushiswap__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }).timeout(10000000000); + + it("Should withdraw successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setIds = ["0", "0"] + + const spells = [ + { + connector: connectorName, + method: "withdraw", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + 0, + 0, + getId, + setIds + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) + +// describe("Sushiswap", function() { +// const connectorName = "Sushiswap-v1.1"; + +// let dsaWallet0: Contract; +// let masterSigner: Signer; +// let instaConnectorsV2: Contract; +// let connector: Contract; + +// const wallets = provider.getWallets(); +// const [wallet0, wallet1, wallet2, wallet3] = wallets; +// before(async () => { +// await hre.network.provider.request({ +// method: "hardhat_reset", +// params: [ +// { +// forking: { +// // @ts-ignore +// jsonRpcUrl: hre.config.networks.hardhat.forking.url, +// blockNumber: 13005785, +// }, +// }, +// ], +// }); + +// masterSigner = await getMasterSigner(); +// instaConnectorsV2 = await ethers.getContractAt( +// abis.core.connectorsV2, +// addresses.core.connectorsV2 +// ); +// connector = await deployAndEnableConnector({ +// connectorName, +// contractArtifact: ConnectV2Sushiswap__factory, +// signer: masterSigner, +// connectors: instaConnectorsV2, +// }); +// console.log("Connector address", connector.address); +// }); + +// it("Should have contracts deployed.", async function() { +// expect(!!instaConnectorsV2.address).to.be.true; +// expect(!!connector.address).to.be.true; +// expect(!!(await masterSigner.getAddress())).to.be.true; +// }); + +// describe("DSA wallet setup", function() { +// it("Should build DSA v2", async function() { +// dsaWallet0 = await buildDSAv2(wallet0.address); +// expect(!!dsaWallet0.address).to.be.true; +// }); + +// it("Deposit ETH & DAI into DSA wallet", async function() { +// await wallet0.sendTransaction({ +// to: dsaWallet0.address, +// value: ethers.utils.parseEther("10"), +// }); +// expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( +// ethers.utils.parseEther("10") +// ); + +// await addLiquidity( +// "dai", +// dsaWallet0.address, +// ethers.utils.parseEther("100000") +// ); +// }); + +// it("Deposit ETH & USDT into DSA wallet", async function() { +// await wallet0.sendTransaction({ +// to: dsaWallet0.address, +// value: ethers.utils.parseEther("10"), +// }); +// expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( +// ethers.utils.parseEther("10") +// ); + +// await addLiquidity( +// "usdt", +// dsaWallet0.address, +// ethers.utils.parseEther("100000") +// ); +// }); +// }); + +// describe("Main", function() { +// it("Should deposit successfully", async function() { +// const ethAmount = ethers.utils.parseEther("1000"); // 1 ETH +// const daiUnitAmount = ethers.utils.parseUnits("4", 18); // 1 ETH +// const usdtAmount = Number(ethers.utils.parseEther("400")) / Math.pow(10, 12); // 1 ETH +// const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; + +// const getId = "0"; +// const setId = "0"; + +// const spells = [ +// { +// connector: connectorName, +// method: "deposit", +// args: [ +// ethAddress, +// DAI_ADDR, +// ethAmount, +// daiUnitAmount, +// "500000000000000000", +// getId, +// setId, +// ], +// }, +// ]; + +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// let receipt = await tx.wait(); +// }).timeout(10000000000); + +// it("Should withdraw successfully", async function() { +// const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH +// const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + +// const getId = "0"; +// const setIds = ["0", "0"]; + +// const spells = [ +// { +// connector: connectorName, +// method: "withdraw", +// args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds], +// }, +// ]; + +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// let receipt = await tx.wait(); +// }); + +// it("Should buy successfully", async function() { +// const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH +// const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH +// const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; + +// const getId = "0"; +// const setId = "0"; + +// const spells = [ +// { +// connector: connectorName, +// method: "buy", +// args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId], +// }, +// ]; + +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// let receipt = await tx.wait(); +// }); +// }); +// }); diff --git a/test/mainnet/sushiswapIncentive/sushiswapIncentive.test.ts b/test/mainnet/sushiswapIncentive/sushiswapIncentive.test.ts new file mode 100644 index 00000000..b8a9c32a --- /dev/null +++ b/test/mainnet/sushiswapIncentive/sushiswapIncentive.test.ts @@ -0,0 +1,235 @@ +import { expect } from "chai"; +import hre from "hardhat"; +const { waffle, ethers } = hre; +const { provider } = waffle + +import {deployAndEnableConnector} from "../../../scripts/tests/deployAndEnableConnector"; +import {buildDSAv2} from "../../../scripts/tests/buildDSAv2"; +import {encodeSpells} from "../../../scripts/tests/encodeSpells"; +import {getMasterSigner} from "../../../scripts/tests/getMasterSigner"; +import {addLiquidity} from "../../../scripts/tests/addLiquidity"; +import {addresses} from "../../../scripts/tests/mainnet/addresses"; +import {abis} from "../../../scripts/constant/abis"; + +import { ConnectV2Sushiswap__factory, ConnectV2Sushiswap, ConnectV2SushiswapIncentive, ConnectV2SushiswapIncentive__factory } from "../../../typechain"; +import { Contract, Signer } from "ethers"; + +const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" +const WETH_ADDR = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + +describe("Sushiswap", function () { + const connectorName = "Sushiswap-v1" + const incentiveConnectorName = "Sushiswp-Incentive-v1" + + let dsaWallet0: Contract; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract, connectorIncentive; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785, + }, + }, + ], + }); + masterSigner = await getMasterSigner() + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2Sushiswap__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + + connectorIncentive = await deployAndEnableConnector({ + connectorName: incentiveConnectorName, + contractArtifact: ConnectV2SushiswapIncentive__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Incentive Connector address", connectorIncentive.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); + }); + + describe("Main", function () { + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("2") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + "500000000000000000", + getId, + setId + ], + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + await tx.wait() + + describe("Incentive", () => { + it("Should deposit successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "deposit", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("10"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should harvest successfully", async () => { + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "harvest", + args: [ + WETH_ADDR, + DAI_ADDR, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should harvest and withdraw successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "withdrawAndHarvest", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("1"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + + it("Should withdraw successfully", async () => { + const getId = 0 + const setId = 0 + const spells = [ + { + connector: incentiveConnectorName, + method: "withdraw", + args: [ + WETH_ADDR, + DAI_ADDR, + ethers.utils.parseEther("1"), + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address) + await tx.wait(); + }) + }) + }).timeout(10000000000); + + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + + const getId = "0" + const setId = "0" + + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ + ethAddress, + DAI_ADDR, + ethAmount, + daiUnitAmount, + getId, + setId + ] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) + let receipt = await tx.wait() + }); + }); +}) From b9564292bc74ba8f537c8a521a2fb940bc0e4a3e Mon Sep 17 00:00:00 2001 From: croooook Date: Mon, 13 Dec 2021 22:44:49 +0530 Subject: [PATCH 12/31] added in the comments of 1inch docs --- contracts/mainnet/connectors/1inch/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/1inch/main.sol b/contracts/mainnet/connectors/1inch/main.sol index bf215788..0e81d3c1 100644 --- a/contracts/mainnet/connectors/1inch/main.sol +++ b/contracts/mainnet/connectors/1inch/main.sol @@ -96,7 +96,7 @@ abstract contract OneInch is OneInchResolverHelpers { * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmt The amount of buyAmt/sellAmt with slippage. - * @param callData Data from 1inch API. + * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange- [here](https://api.1inch.exchange/swagger/ethereum/#/Swap/SwapFactoryCommonController_getSwap) * @param setId ID stores the amount of token brought. */ function sell( From f524062c3931684eaa339fb410638411ed91358f Mon Sep 17 00:00:00 2001 From: croooook Date: Mon, 13 Dec 2021 23:38:31 +0530 Subject: [PATCH 13/31] updated the 1inch comments for docs --- contracts/mainnet/connectors/1inch/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/1inch/main.sol b/contracts/mainnet/connectors/1inch/main.sol index 0e81d3c1..8509bfbb 100644 --- a/contracts/mainnet/connectors/1inch/main.sol +++ b/contracts/mainnet/connectors/1inch/main.sol @@ -96,7 +96,7 @@ abstract contract OneInch is OneInchResolverHelpers { * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmt The amount of buyAmt/sellAmt with slippage. - * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange- [here](https://api.1inch.exchange/swagger/ethereum/#/Swap/SwapFactoryCommonController_getSwap) + * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange- here * @param setId ID stores the amount of token brought. */ function sell( From 51710a3cf787c1a6999be17abef4de1e6ba8a207 Mon Sep 17 00:00:00 2001 From: croooook Date: Mon, 13 Dec 2021 23:52:20 +0530 Subject: [PATCH 14/31] updated the 1inch comments for docs --- contracts/mainnet/connectors/1inch/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/1inch/main.sol b/contracts/mainnet/connectors/1inch/main.sol index 8509bfbb..66eae5e5 100644 --- a/contracts/mainnet/connectors/1inch/main.sol +++ b/contracts/mainnet/connectors/1inch/main.sol @@ -96,7 +96,7 @@ abstract contract OneInch is OneInchResolverHelpers { * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmt The amount of buyAmt/sellAmt with slippage. - * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange- here + * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange- here * @param setId ID stores the amount of token brought. */ function sell( From a3d1a1f6bf1a488d9df8f2ceaa136d98e75da351 Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 14 Dec 2021 00:02:35 +0530 Subject: [PATCH 15/31] Update contracts/mainnet/connectors/1inch/main.sol --- contracts/mainnet/connectors/1inch/main.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mainnet/connectors/1inch/main.sol b/contracts/mainnet/connectors/1inch/main.sol index 66eae5e5..7f1622b6 100644 --- a/contracts/mainnet/connectors/1inch/main.sol +++ b/contracts/mainnet/connectors/1inch/main.sol @@ -96,7 +96,7 @@ abstract contract OneInch is OneInchResolverHelpers { * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmt The amount of buyAmt/sellAmt with slippage. - * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange- here + * @param callData Data from 1inch API. You can generate calldata for calling 1inch route for exchange: here * @param setId ID stores the amount of token brought. */ function sell( From da09b6b1cba620958982df0f6f5a6b6a14ee4f72 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Wed, 15 Dec 2021 16:35:10 +0530 Subject: [PATCH 16/31] updated quickswap --- .../polygon/connectors/quickswap/events.sol | 68 +-- .../polygon/connectors/quickswap/helpers.sol | 326 ++++++------- .../connectors/quickswap/interface.sol | 150 +++--- .../polygon/connectors/quickswap/main.sol | 440 +++++++++--------- 4 files changed, 492 insertions(+), 492 deletions(-) diff --git a/contracts/polygon/connectors/quickswap/events.sol b/contracts/polygon/connectors/quickswap/events.sol index c8fc41d6..9e01ef9d 100644 --- a/contracts/polygon/connectors/quickswap/events.sol +++ b/contracts/polygon/connectors/quickswap/events.sol @@ -1,41 +1,41 @@ pragma solidity ^0.7.0; contract Events { - event LogDepositLiquidity( - address indexed tokenA, - address indexed tokenB, - uint256 amtA, - uint256 amtB, - uint256 uniAmount, - uint256 getId, - uint256 setId - ); + event LogDepositLiquidity( + address indexed tokenA, + address indexed tokenB, + uint256 amtA, + uint256 amtB, + uint256 uniAmount, + uint256 getId, + uint256 setId + ); - event LogWithdrawLiquidity( - address indexed tokenA, - address indexed tokenB, - uint256 amountA, - uint256 amountB, - uint256 uniAmount, - uint256 getId, - uint256[] setId - ); + event LogWithdrawLiquidity( + address indexed tokenA, + address indexed tokenB, + uint256 amountA, + uint256 amountB, + uint256 uniAmount, + uint256 getId, + uint256[] setId + ); - event LogBuy( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); + event LogBuy( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); - event LogSell( - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 getId, - uint256 setId - ); + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); } diff --git a/contracts/polygon/connectors/quickswap/helpers.sol b/contracts/polygon/connectors/quickswap/helpers.sol index 07316a2c..594b56e1 100644 --- a/contracts/polygon/connectors/quickswap/helpers.sol +++ b/contracts/polygon/connectors/quickswap/helpers.sol @@ -1,184 +1,184 @@ pragma solidity ^0.7.0; -import {TokenInterface} from "../../common/interfaces.sol"; -import {DSMath} from "../../common/math.sol"; -import {Basic} from "../../common/basic.sol"; -import {IQuickSwapRouter, IQuickSwapFactory} from "./interface.sol"; +import { TokenInterface } from "../../common/interfaces.sol"; +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; +import { IQuickSwapRouter, IQuickSwapFactory } from "./interface.sol"; abstract contract Helpers is DSMath, Basic { - /** - * @dev IQuickSwapRouter - */ - IQuickSwapRouter internal constant router = - IQuickSwapRouter(0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff); + /** + * @dev IQuickSwapRouter + */ + IQuickSwapRouter internal constant router = + IQuickSwapRouter(0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff); - function getExpectedBuyAmt(address[] memory paths, uint256 sellAmt) - internal - view - returns (uint256 buyAmt) - { - uint256[] memory amts = router.getAmountsOut(sellAmt, paths); - buyAmt = amts[1]; - } + function getExpectedBuyAmt(address[] memory paths, uint256 sellAmt) + internal + view + returns (uint256 buyAmt) + { + uint256[] memory amts = router.getAmountsOut(sellAmt, paths); + buyAmt = amts[1]; + } - function getExpectedSellAmt(address[] memory paths, uint256 buyAmt) - internal - view - returns (uint256 sellAmt) - { - uint256[] memory amts = router.getAmountsIn(buyAmt, paths); - sellAmt = amts[0]; - } + function getExpectedSellAmt(address[] memory paths, uint256 buyAmt) + internal + view + returns (uint256 sellAmt) + { + uint256[] memory amts = router.getAmountsIn(buyAmt, paths); + sellAmt = amts[0]; + } - function checkPair(address[] memory paths) internal view { - address pair = IQuickSwapFactory(router.factory()).getPair( - paths[0], - paths[1] - ); - require(pair != address(0), "No-exchange-address"); - } + function checkPair(address[] memory paths) internal view { + address pair = IQuickSwapFactory(router.factory()).getPair( + paths[0], + paths[1] + ); + require(pair != address(0), "No-exchange-address"); + } - function getPaths(address buyAddr, address sellAddr) - internal - pure - returns (address[] memory paths) - { - paths = new address[](2); - paths[0] = address(sellAddr); - paths[1] = address(buyAddr); - } + function getPaths(address buyAddr, address sellAddr) + internal + pure + returns (address[] memory paths) + { + paths = new address[](2); + paths[0] = address(sellAddr); + paths[1] = address(buyAddr); + } - function getMinAmount( - TokenInterface token, - uint256 amt, - uint256 slippage - ) internal view returns (uint256 minAmt) { - uint256 _amt18 = convertTo18(token.decimals(), amt); - minAmt = wmul(_amt18, sub(WAD, slippage)); - minAmt = convert18ToDec(token.decimals(), minAmt); - } + function getMinAmount( + TokenInterface token, + uint256 amt, + uint256 slippage + ) internal view returns (uint256 minAmt) { + uint256 _amt18 = convertTo18(token.decimals(), amt); + minAmt = wmul(_amt18, sub(WAD, slippage)); + minAmt = convert18ToDec(token.decimals(), minAmt); + } - function _addLiquidity( - address tokenA, - address tokenB, - uint256 _amt, - uint256 unitAmt, - uint256 slippage - ) - internal - returns ( - uint256 _amtA, - uint256 _amtB, - uint256 _liquidity - ) - { - (TokenInterface _tokenA, TokenInterface _tokenB) = changeMaticAddress( - tokenA, - tokenB - ); + function _addLiquidity( + address tokenA, + address tokenB, + uint256 _amt, + uint256 unitAmt, + uint256 slippage + ) + internal + returns ( + uint256 _amtA, + uint256 _amtB, + uint256 _liquidity + ) + { + (TokenInterface _tokenA, TokenInterface _tokenB) = changeMaticAddress( + tokenA, + tokenB + ); - _amtA = _amt == uint256(-1) - ? getTokenBal(TokenInterface(tokenA)) - : _amt; - _amtB = convert18ToDec( - _tokenB.decimals(), - wmul(unitAmt, convertTo18(_tokenA.decimals(), _amtA)) - ); + _amtA = _amt == uint256(-1) + ? getTokenBal(TokenInterface(tokenA)) + : _amt; + _amtB = convert18ToDec( + _tokenB.decimals(), + wmul(unitAmt, convertTo18(_tokenA.decimals(), _amtA)) + ); - bool isMatic = address(_tokenA) == wmaticAddr; - convertMaticToWmatic(isMatic, _tokenA, _amtA); + bool isMatic = address(_tokenA) == wmaticAddr; + convertMaticToWmatic(isMatic, _tokenA, _amtA); - isMatic = address(_tokenB) == wmaticAddr; - convertMaticToWmatic(isMatic, _tokenB, _amtB); + isMatic = address(_tokenB) == wmaticAddr; + convertMaticToWmatic(isMatic, _tokenB, _amtB); - approve(_tokenA, address(router), _amtA); - approve(_tokenB, address(router), _amtB); + approve(_tokenA, address(router), _amtA); + approve(_tokenB, address(router), _amtB); - uint256 minAmtA = getMinAmount(_tokenA, _amtA, slippage); - uint256 minAmtB = getMinAmount(_tokenB, _amtB, slippage); - (_amtA, _amtB, _liquidity) = router.addLiquidity( - address(_tokenA), - address(_tokenB), - _amtA, - _amtB, - minAmtA, - minAmtA, - address(this), - block.timestamp + 1 - ); - } + uint256 minAmtA = getMinAmount(_tokenA, _amtA, slippage); + uint256 minAmtB = getMinAmount(_tokenB, _amtB, slippage); + (_amtA, _amtB, _liquidity) = router.addLiquidity( + address(_tokenA), + address(_tokenB), + _amtA, + _amtB, + minAmtA, + minAmtB, + address(this), + block.timestamp + 1 + ); + } - function _removeLiquidity( - address tokenA, - address tokenB, - uint256 _amt, - uint256 unitAmtA, - uint256 unitAmtB - ) - internal - returns ( - uint256 _amtA, - uint256 _amtB, - uint256 _uniAmt - ) - { - TokenInterface _tokenA; - TokenInterface _tokenB; - (_tokenA, _tokenB, _uniAmt) = _getRemoveLiquidityData( - tokenA, - tokenB, - _amt - ); - { - uint256 minAmtA = convert18ToDec( - _tokenA.decimals(), - wmul(unitAmtA, _uniAmt) - ); - uint256 minAmtB = convert18ToDec( - _tokenB.decimals(), - wmul(unitAmtB, _uniAmt) - ); - (_amtA, _amtB) = router.removeLiquidity( - address(_tokenA), - address(_tokenB), - _uniAmt, - minAmtA, - minAmtB, - address(this), - block.timestamp + 1 - ); - } + function _removeLiquidity( + address tokenA, + address tokenB, + uint256 _amt, + uint256 unitAmtA, + uint256 unitAmtB + ) + internal + returns ( + uint256 _amtA, + uint256 _amtB, + uint256 _uniAmt + ) + { + TokenInterface _tokenA; + TokenInterface _tokenB; + (_tokenA, _tokenB, _uniAmt) = _getRemoveLiquidityData( + tokenA, + tokenB, + _amt + ); + { + uint256 minAmtA = convert18ToDec( + _tokenA.decimals(), + wmul(unitAmtA, _uniAmt) + ); + uint256 minAmtB = convert18ToDec( + _tokenB.decimals(), + wmul(unitAmtB, _uniAmt) + ); + (_amtA, _amtB) = router.removeLiquidity( + address(_tokenA), + address(_tokenB), + _uniAmt, + minAmtA, + minAmtB, + address(this), + block.timestamp + 1 + ); + } - bool isMatic = address(_tokenA) == wmaticAddr; - convertWmaticToMatic(isMatic, _tokenA, _amtA); + bool isMatic = address(_tokenA) == wmaticAddr; + convertWmaticToMatic(isMatic, _tokenA, _amtA); - isMatic = address(_tokenB) == wmaticAddr; - convertWmaticToMatic(isMatic, _tokenB, _amtB); - } + isMatic = address(_tokenB) == wmaticAddr; + convertWmaticToMatic(isMatic, _tokenB, _amtB); + } - function _getRemoveLiquidityData( - address tokenA, - address tokenB, - uint256 _amt - ) - internal - returns ( - TokenInterface _tokenA, - TokenInterface _tokenB, - uint256 _uniAmt - ) - { - (_tokenA, _tokenB) = changeMaticAddress(tokenA, tokenB); - address exchangeAddr = IQuickSwapFactory(router.factory()).getPair( - address(_tokenA), - address(_tokenB) - ); - require(exchangeAddr != address(0), "pair-not-found."); + function _getRemoveLiquidityData( + address tokenA, + address tokenB, + uint256 _amt + ) + internal + returns ( + TokenInterface _tokenA, + TokenInterface _tokenB, + uint256 _uniAmt + ) + { + (_tokenA, _tokenB) = changeMaticAddress(tokenA, tokenB); + address exchangeAddr = IQuickSwapFactory(router.factory()).getPair( + address(_tokenA), + address(_tokenB) + ); + require(exchangeAddr != address(0), "pair-not-found."); - TokenInterface uniToken = TokenInterface(exchangeAddr); - _uniAmt = _amt == uint256(-1) - ? uniToken.balanceOf(address(this)) - : _amt; - approve(uniToken, address(router), _uniAmt); - } + TokenInterface uniToken = TokenInterface(exchangeAddr); + _uniAmt = _amt == uint256(-1) + ? uniToken.balanceOf(address(this)) + : _amt; + approve(uniToken, address(router), _uniAmt); + } } diff --git a/contracts/polygon/connectors/quickswap/interface.sol b/contracts/polygon/connectors/quickswap/interface.sol index 438d89c3..bd210215 100644 --- a/contracts/polygon/connectors/quickswap/interface.sol +++ b/contracts/polygon/connectors/quickswap/interface.sol @@ -1,97 +1,97 @@ pragma solidity ^0.7.0; interface IQuickSwapRouter { - function factory() external pure returns (address); + function factory() external pure returns (address); - function WETH() external pure returns (address); + function WETH() external pure returns (address); - function addLiquidity( - address tokenA, - address tokenB, - uint256 amountADesired, - uint256 amountBDesired, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) - external - returns ( - uint256 amountA, - uint256 amountB, - uint256 liquidity - ); + function addLiquidity( + address tokenA, + address tokenB, + uint256 amountADesired, + uint256 amountBDesired, + uint256 amountAMin, + uint256 amountBMin, + address to, + uint256 deadline + ) + external + returns ( + uint256 amountA, + uint256 amountB, + uint256 liquidity + ); - function removeLiquidity( - address tokenA, - address tokenB, - uint256 liquidity, - uint256 amountAMin, - uint256 amountBMin, - address to, - uint256 deadline - ) external returns (uint256 amountA, uint256 amountB); + function removeLiquidity( + address tokenA, + address tokenB, + uint256 liquidity, + uint256 amountAMin, + uint256 amountBMin, + address to, + uint256 deadline + ) external returns (uint256 amountA, uint256 amountB); - function swapExactTokensForTokens( - uint256 amountIn, - uint256 amountOutMin, - address[] calldata path, - address to, - uint256 deadline - ) external returns (uint256[] memory amounts); + function swapExactTokensForTokens( + uint256 amountIn, + uint256 amountOutMin, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); - function swapTokensForExactTokens( - uint256 amountOut, - uint256 amountInMax, - address[] calldata path, - address to, - uint256 deadline - ) external returns (uint256[] memory amounts); + function swapTokensForExactTokens( + uint256 amountOut, + uint256 amountInMax, + address[] calldata path, + address to, + uint256 deadline + ) external returns (uint256[] memory amounts); - function quote( - uint256 amountA, - uint256 reserveA, - uint256 reserveB - ) external pure returns (uint256 amountB); + function quote( + uint256 amountA, + uint256 reserveA, + uint256 reserveB + ) external pure returns (uint256 amountB); - function getAmountOut( - uint256 amountIn, - uint256 reserveIn, - uint256 reserveOut - ) external pure returns (uint256 amountOut); + function getAmountOut( + uint256 amountIn, + uint256 reserveIn, + uint256 reserveOut + ) external pure returns (uint256 amountOut); - function getAmountIn( - uint256 amountOut, - uint256 reserveIn, - uint256 reserveOut - ) external pure returns (uint256 amountIn); + function getAmountIn( + uint256 amountOut, + uint256 reserveIn, + uint256 reserveOut + ) external pure returns (uint256 amountIn); - function getAmountsOut(uint256 amountIn, address[] calldata path) - external - view - returns (uint256[] memory amounts); + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); - function getAmountsIn(uint256 amountOut, address[] calldata path) - external - view - returns (uint256[] memory amounts); + function getAmountsIn(uint256 amountOut, address[] calldata path) + external + view + returns (uint256[] memory amounts); } interface IQuickSwapFactory { - function getPair(address tokenA, address tokenB) - external - view - returns (address pair); + function getPair(address tokenA, address tokenB) + external + view + returns (address pair); - function allPairs(uint256) external view returns (address pair); + function allPairs(uint256) external view returns (address pair); - function allPairsLength() external view returns (uint256); + function allPairsLength() external view returns (uint256); - function feeTo() external view returns (address); + function feeTo() external view returns (address); - function feeToSetter() external view returns (address); + function feeToSetter() external view returns (address); - function createPair(address tokenA, address tokenB) - external - returns (address pair); + function createPair(address tokenA, address tokenB) + external + returns (address pair); } diff --git a/contracts/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol index 2cc07049..6973948b 100644 --- a/contracts/polygon/connectors/quickswap/main.sol +++ b/contracts/polygon/connectors/quickswap/main.sol @@ -5,252 +5,252 @@ pragma solidity ^0.7.0; * @dev Decentralized Exchange. */ -import {TokenInterface} from "../../common/interfaces.sol"; -import {Helpers} from "./helpers.sol"; -import {Events} from "./events.sol"; +import { TokenInterface } from "../../common/interfaces.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; abstract contract QuickpswapResolver is Helpers, Events { - /** - * @dev Deposit Liquidity. - * @notice Deposit Liquidity to a QuickSwap pool. - * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param amtA The amount of A tokens to deposit. - * @param unitAmt The unit amount of of amtB/amtA with slippage. - * @param slippage Slippage amount. - * @param getId ID to retrieve amtA. - * @param setId ID stores the amount of pools tokens received. - */ - function deposit( - address tokenA, - address tokenB, - uint256 amtA, - uint256 unitAmt, - uint256 slippage, - uint256 getId, - uint256 setId - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - uint256 _amt = getUint(getId, amtA); + /** + * @dev Deposit Liquidity. + * @notice Deposit Liquidity to a QuickSwap pool. + * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param amtA The amount of A tokens to deposit. + * @param unitAmt The unit amount of of amtB/amtA with slippage. + * @param slippage Slippage amount. + * @param getId ID to retrieve amtA. + * @param setId ID stores the amount of pools tokens received. + */ + function deposit( + address tokenA, + address tokenB, + uint256 amtA, + uint256 unitAmt, + uint256 slippage, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, amtA); - (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _addLiquidity( - tokenA, - tokenB, - _amt, - unitAmt, - slippage - ); - setUint(setId, _uniAmt); + (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _addLiquidity( + tokenA, + tokenB, + _amt, + unitAmt, + slippage + ); + setUint(setId, _uniAmt); - _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode( - tokenA, - tokenB, - _amtA, - _amtB, - _uniAmt, - getId, - setId - ); - } + _eventName = "LogDepositLiquidity(address,address,uint256,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + tokenA, + tokenB, + _amtA, + _amtB, + _uniAmt, + getId, + setId + ); + } - /** - * @dev Withdraw Liquidity. - * @notice Withdraw Liquidity from a QuickSwap pool. - * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param uniAmt The amount of pool tokens to withdraw. - * @param unitAmtA The unit amount of amtA/uniAmt with slippage. - * @param unitAmtB The unit amount of amtB/uniAmt with slippage. - * @param getId ID to retrieve uniAmt. - * @param setIds Array of IDs to store the amount tokens received. - */ - function withdraw( - address tokenA, - address tokenB, - uint256 uniAmt, - uint256 unitAmtA, - uint256 unitAmtB, - uint256 getId, - uint256[] calldata setIds - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - uint256 _amt = getUint(getId, uniAmt); + /** + * @dev Withdraw Liquidity. + * @notice Withdraw Liquidity from a QuickSwap pool. + * @param tokenA The address of token A.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param tokenB The address of token B.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param uniAmt The amount of pool tokens to withdraw. + * @param unitAmtA The unit amount of amtA/uniAmt with slippage. + * @param unitAmtB The unit amount of amtB/uniAmt with slippage. + * @param getId ID to retrieve uniAmt. + * @param setIds Array of IDs to store the amount tokens received. + */ + function withdraw( + address tokenA, + address tokenB, + uint256 uniAmt, + uint256 unitAmtA, + uint256 unitAmtB, + uint256 getId, + uint256[] calldata setIds + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amt = getUint(getId, uniAmt); - (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _removeLiquidity( - tokenA, - tokenB, - _amt, - unitAmtA, - unitAmtB - ); + (uint256 _amtA, uint256 _amtB, uint256 _uniAmt) = _removeLiquidity( + tokenA, + tokenB, + _amt, + unitAmtA, + unitAmtB + ); - setUint(setIds[0], _amtA); - setUint(setIds[1], _amtB); + setUint(setIds[0], _amtA); + setUint(setIds[1], _amtB); - _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; - _eventParam = abi.encode( - tokenA, - tokenB, - _amtA, - _amtB, - _uniAmt, - getId, - setIds - ); - } + _eventName = "LogWithdrawLiquidity(address,address,uint256,uint256,uint256,uint256,uint256[])"; + _eventParam = abi.encode( + tokenA, + tokenB, + _amtA, + _amtB, + _uniAmt, + getId, + setIds + ); + } - /** - * @dev Buy ETH/ERC20_Token. - * @notice Buy a token using a QuickSwap - * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param buyAmt The amount of tokens to buy. - * @param unitAmt The unit amount of sellAmt/buyAmt with slippage. - * @param getId ID to retrieve buyAmt. - * @param setId ID to store the amount of tokens sold. - */ - function buy( - address buyAddr, - address sellAddr, - uint256 buyAmt, - uint256 unitAmt, - uint256 getId, - uint256 setId - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - uint256 _buyAmt = getUint(getId, buyAmt); - ( - TokenInterface _buyAddr, - TokenInterface _sellAddr - ) = changeMaticAddress(buyAddr, sellAddr); - address[] memory paths = getPaths( - address(_buyAddr), - address(_sellAddr) - ); + /** + * @dev Buy ETH/ERC20_Token. + * @notice Buy a token using a QuickSwap + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param buyAmt The amount of tokens to buy. + * @param unitAmt The unit amount of sellAmt/buyAmt with slippage. + * @param getId ID to retrieve buyAmt. + * @param setId ID to store the amount of tokens sold. + */ + function buy( + address buyAddr, + address sellAddr, + uint256 buyAmt, + uint256 unitAmt, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _buyAmt = getUint(getId, buyAmt); + ( + TokenInterface _buyAddr, + TokenInterface _sellAddr + ) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths( + address(_buyAddr), + address(_sellAddr) + ); - uint256 _slippageAmt = convert18ToDec( - _sellAddr.decimals(), - wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt)) - ); + uint256 _slippageAmt = convert18ToDec( + _sellAddr.decimals(), + wmul(unitAmt, convertTo18(_buyAddr.decimals(), _buyAmt)) + ); - checkPair(paths); - uint256 _expectedAmt = getExpectedSellAmt(paths, _buyAmt); - require(_slippageAmt >= _expectedAmt, "Too much slippage"); + checkPair(paths); + uint256 _expectedAmt = getExpectedSellAmt(paths, _buyAmt); + require(_slippageAmt >= _expectedAmt, "Too much slippage"); - bool isEth = address(_sellAddr) == wmaticAddr; - convertMaticToWmatic(isEth, _sellAddr, _expectedAmt); - approve(_sellAddr, address(router), _expectedAmt); + bool isEth = address(_sellAddr) == wmaticAddr; + convertMaticToWmatic(isEth, _sellAddr, _expectedAmt); + approve(_sellAddr, address(router), _expectedAmt); - uint256 _sellAmt = router.swapTokensForExactTokens( - _buyAmt, - _expectedAmt, - paths, - address(this), - block.timestamp + 1 - )[0]; + uint256 _sellAmt = router.swapTokensForExactTokens( + _buyAmt, + _expectedAmt, + paths, + address(this), + block.timestamp + 1 + )[0]; - isEth = address(_buyAddr) == wmaticAddr; - convertWmaticToMatic(isEth, _buyAddr, _buyAmt); + isEth = address(_buyAddr) == wmaticAddr; + convertWmaticToMatic(isEth, _buyAddr, _buyAmt); - setUint(setId, _sellAmt); + setUint(setId, _sellAmt); - _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode( - buyAddr, - sellAddr, - _buyAmt, - _sellAmt, - getId, - setId - ); - } + _eventName = "LogBuy(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + buyAddr, + sellAddr, + _buyAmt, + _sellAmt, + getId, + setId + ); + } - /** - * @dev Sell ETH/ERC20_Token. - * @notice Sell a token using a QuickSwap - * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt The amount of the token to sell. - * @param unitAmt The unit amount of buyAmt/sellAmt with slippage. - * @param getId ID to retrieve sellAmt. - * @param setId ID stores the amount of token brought. - */ - function sell( - address buyAddr, - address sellAddr, - uint256 sellAmt, - uint256 unitAmt, - uint256 getId, - uint256 setId - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - uint256 _sellAmt = getUint(getId, sellAmt); - ( - TokenInterface _buyAddr, - TokenInterface _sellAddr - ) = changeMaticAddress(buyAddr, sellAddr); - address[] memory paths = getPaths( - address(_buyAddr), - address(_sellAddr) - ); + /** + * @dev Sell ETH/ERC20_Token. + * @notice Sell a token using a QuickSwap + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmt The unit amount of buyAmt/sellAmt with slippage. + * @param getId ID to retrieve sellAmt. + * @param setId ID stores the amount of token brought. + */ + function sell( + address buyAddr, + address sellAddr, + uint256 sellAmt, + uint256 unitAmt, + uint256 getId, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _sellAmt = getUint(getId, sellAmt); + ( + TokenInterface _buyAddr, + TokenInterface _sellAddr + ) = changeMaticAddress(buyAddr, sellAddr); + address[] memory paths = getPaths( + address(_buyAddr), + address(_sellAddr) + ); - if (_sellAmt == uint256(-1)) { - _sellAmt = sellAddr == maticAddr - ? address(this).balance - : _sellAddr.balanceOf(address(this)); - } + if (_sellAmt == uint256(-1)) { + _sellAmt = sellAddr == maticAddr + ? address(this).balance + : _sellAddr.balanceOf(address(this)); + } - uint256 _slippageAmt = convert18ToDec( - _buyAddr.decimals(), - wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt)) - ); + uint256 _slippageAmt = convert18ToDec( + _buyAddr.decimals(), + wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt)) + ); - checkPair(paths); - uint256 _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); - require(_slippageAmt <= _expectedAmt, "Too much slippage"); + checkPair(paths); + uint256 _expectedAmt = getExpectedBuyAmt(paths, _sellAmt); + require(_slippageAmt <= _expectedAmt, "Too much slippage"); - bool isEth = address(_sellAddr) == wmaticAddr; - convertMaticToWmatic(isEth, _sellAddr, _sellAmt); - approve(_sellAddr, address(router), _sellAmt); + bool isEth = address(_sellAddr) == wmaticAddr; + convertMaticToWmatic(isEth, _sellAddr, _sellAmt); + approve(_sellAddr, address(router), _sellAmt); - uint256 _buyAmt = router.swapExactTokensForTokens( - _sellAmt, - _expectedAmt, - paths, - address(this), - block.timestamp + 1 - )[1]; + uint256 _buyAmt = router.swapExactTokensForTokens( + _sellAmt, + _expectedAmt, + paths, + address(this), + block.timestamp + 1 + )[1]; - isEth = address(_buyAddr) == wmaticAddr; - convertWmaticToMatic(isEth, _buyAddr, _buyAmt); + isEth = address(_buyAddr) == wmaticAddr; + convertWmaticToMatic(isEth, _buyAddr, _buyAmt); - setUint(setId, _buyAmt); + setUint(setId, _buyAmt); - _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode( - buyAddr, - sellAddr, - _buyAmt, - _sellAmt, - getId, - setId - ); - } + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + buyAddr, + sellAddr, + _buyAmt, + _sellAmt, + getId, + setId + ); + } } contract ConnectV2Quickswap is QuickpswapResolver { - string public constant name = "Quickpswap-v1.1"; + string public constant name = "Quickpswap-v1.1"; } From 99d9d17f23dd2b170bee739277356f9f3cd1c921 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Wed, 15 Dec 2021 16:37:32 +0530 Subject: [PATCH 17/31] updated sushi tests --- test/mainnet/sushiswap/sushiswap.test.ts | 376 ++++++----------------- 1 file changed, 96 insertions(+), 280 deletions(-) diff --git a/test/mainnet/sushiswap/sushiswap.test.ts b/test/mainnet/sushiswap/sushiswap.test.ts index 8257b47d..8c70125b 100644 --- a/test/mainnet/sushiswap/sushiswap.test.ts +++ b/test/mainnet/sushiswap/sushiswap.test.ts @@ -14,318 +14,134 @@ import { abis } from "../../../scripts/constant/abis"; import { ConnectV2Sushiswap__factory, ConnectV2Sushiswap } from "../../../typechain"; import type { Signer, Contract } from "ethers"; -const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f" +const DAI_ADDR = "0x6b175474e89094c44da98b954eedeac495271d0f"; describe("Sushiswap", function () { - const connectorName = "Sushiswap-v1" + const connectorName = "Sushiswap-v1"; let dsaWallet0: Contract; let masterSigner: Signer; let instaConnectorsV2: Contract; let connector: Contract; - const wallets = provider.getWallets() - const [wallet0, wallet1, wallet2, wallet3] = wallets + const wallets = provider.getWallets(); + const [wallet0, wallet1, wallet2, wallet3] = wallets; before(async () => { - await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - // @ts-ignore - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 13005785, - }, - }, - ], - }); - - masterSigner = await getMasterSigner() - instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: ConnectV2Sushiswap__factory, - signer: masterSigner, - connectors: instaConnectorsV2 - }) - console.log("Connector address", connector.address) - }) + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 13005785 + } + } + ] + }); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2Sushiswap__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }); + console.log("Connector address", connector.address); + }); it("Should have contracts deployed.", async function () { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; expect(!!(await masterSigner.getAddress())).to.be.true; }); describe("DSA wallet setup", function () { - it("Should build DSA v2", async function () { - dsaWallet0 = await buildDSAv2(wallet0.address) - expect(!!dsaWallet0.address).to.be.true; + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH & DAI into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - it("Deposit ETH & DAI into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); - await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("100000")); + it("Deposit ETH & USDT into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - it("Deposit ETH & USDT into DSA wallet", async function () { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10") - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - - await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); - }); + await addLiquidity("usdt", dsaWallet0.address, ethers.utils.parseEther("100000")); + }); }); describe("Main", function () { + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; - it("Should deposit successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + const getId = "0"; + const setId = "0"; - const getId = "0" - const setId = "0" + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, "500000000000000000", getId, setId] + } + ]; - const spells = [ - { - connector: connectorName, - method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId - ], - } - ] + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address); + let receipt = await tx.wait(); + }).timeout(10000000000); - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }).timeout(10000000000); + it("Should withdraw successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; - it("Should withdraw successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + const getId = "0"; + const setIds = ["0", "0"]; - const getId = "0" - const setIds = ["0", "0"] + const spells = [ + { + connector: connectorName, + method: "withdraw", + args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds] + } + ]; - const spells = [ - { - connector: connectorName, - method: "withdraw", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - 0, - 0, - getId, - setIds - ] - } - ] + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address); + let receipt = await tx.wait(); + }); - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); + it("Should buy successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; - it("Should buy successfully", async function () { - const ethAmount = ethers.utils.parseEther("0.1") // 1 ETH - const daiUnitAmount = ethers.utils.parseEther("4000") // 1 ETH - const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" + const getId = "0"; + const setId = "0"; - const getId = "0" - const setId = "0" + const spells = [ + { + connector: connectorName, + method: "buy", + args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId] + } + ]; - const spells = [ - { - connector: connectorName, - method: "buy", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - getId, - setId - ] - } - ] - - const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address) - let receipt = await tx.wait() - }); + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address); + let receipt = await tx.wait(); + }); }); -}) - -// describe("Sushiswap", function() { -// const connectorName = "Sushiswap-v1.1"; - -// let dsaWallet0: Contract; -// let masterSigner: Signer; -// let instaConnectorsV2: Contract; -// let connector: Contract; - -// const wallets = provider.getWallets(); -// const [wallet0, wallet1, wallet2, wallet3] = wallets; -// before(async () => { -// await hre.network.provider.request({ -// method: "hardhat_reset", -// params: [ -// { -// forking: { -// // @ts-ignore -// jsonRpcUrl: hre.config.networks.hardhat.forking.url, -// blockNumber: 13005785, -// }, -// }, -// ], -// }); - -// masterSigner = await getMasterSigner(); -// instaConnectorsV2 = await ethers.getContractAt( -// abis.core.connectorsV2, -// addresses.core.connectorsV2 -// ); -// connector = await deployAndEnableConnector({ -// connectorName, -// contractArtifact: ConnectV2Sushiswap__factory, -// signer: masterSigner, -// connectors: instaConnectorsV2, -// }); -// console.log("Connector address", connector.address); -// }); - -// it("Should have contracts deployed.", async function() { -// expect(!!instaConnectorsV2.address).to.be.true; -// expect(!!connector.address).to.be.true; -// expect(!!(await masterSigner.getAddress())).to.be.true; -// }); - -// describe("DSA wallet setup", function() { -// it("Should build DSA v2", async function() { -// dsaWallet0 = await buildDSAv2(wallet0.address); -// expect(!!dsaWallet0.address).to.be.true; -// }); - -// it("Deposit ETH & DAI into DSA wallet", async function() { -// await wallet0.sendTransaction({ -// to: dsaWallet0.address, -// value: ethers.utils.parseEther("10"), -// }); -// expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( -// ethers.utils.parseEther("10") -// ); - -// await addLiquidity( -// "dai", -// dsaWallet0.address, -// ethers.utils.parseEther("100000") -// ); -// }); - -// it("Deposit ETH & USDT into DSA wallet", async function() { -// await wallet0.sendTransaction({ -// to: dsaWallet0.address, -// value: ethers.utils.parseEther("10"), -// }); -// expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( -// ethers.utils.parseEther("10") -// ); - -// await addLiquidity( -// "usdt", -// dsaWallet0.address, -// ethers.utils.parseEther("100000") -// ); -// }); -// }); - -// describe("Main", function() { -// it("Should deposit successfully", async function() { -// const ethAmount = ethers.utils.parseEther("1000"); // 1 ETH -// const daiUnitAmount = ethers.utils.parseUnits("4", 18); // 1 ETH -// const usdtAmount = Number(ethers.utils.parseEther("400")) / Math.pow(10, 12); // 1 ETH -// const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; - -// const getId = "0"; -// const setId = "0"; - -// const spells = [ -// { -// connector: connectorName, -// method: "deposit", -// args: [ -// ethAddress, -// DAI_ADDR, -// ethAmount, -// daiUnitAmount, -// "500000000000000000", -// getId, -// setId, -// ], -// }, -// ]; - -// const tx = await dsaWallet0 -// .connect(wallet0) -// .cast(...encodeSpells(spells), wallet1.address); -// let receipt = await tx.wait(); -// }).timeout(10000000000); - -// it("Should withdraw successfully", async function() { -// const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH -// const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; - -// const getId = "0"; -// const setIds = ["0", "0"]; - -// const spells = [ -// { -// connector: connectorName, -// method: "withdraw", -// args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds], -// }, -// ]; - -// const tx = await dsaWallet0 -// .connect(wallet0) -// .cast(...encodeSpells(spells), wallet1.address); -// let receipt = await tx.wait(); -// }); - -// it("Should buy successfully", async function() { -// const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH -// const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH -// const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; - -// const getId = "0"; -// const setId = "0"; - -// const spells = [ -// { -// connector: connectorName, -// method: "buy", -// args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId], -// }, -// ]; - -// const tx = await dsaWallet0 -// .connect(wallet0) -// .cast(...encodeSpells(spells), wallet1.address); -// let receipt = await tx.wait(); -// }); -// }); -// }); +}); From 4f5fb523be86a94b967be30c143af3ec646c1f45 Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Wed, 15 Dec 2021 17:52:53 +0530 Subject: [PATCH 18/31] fixed quickswap tests --- test/polygon/quickswap/quickswap.test.ts | 116 ++++++++--------------- 1 file changed, 38 insertions(+), 78 deletions(-) diff --git a/test/polygon/quickswap/quickswap.test.ts b/test/polygon/quickswap/quickswap.test.ts index b831dfe5..5047fd61 100644 --- a/test/polygon/quickswap/quickswap.test.ts +++ b/test/polygon/quickswap/quickswap.test.ts @@ -16,8 +16,8 @@ import type { Signer, Contract } from "ethers"; const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063"; -describe("Quickswap", function() { - const connectorName = "Quickpswap-v1.1"; +describe("Quickswap", function () { + const connectorName = "Quickswap-v1"; let dsaWallet0: Contract; let masterSigner: Signer; @@ -28,83 +28,57 @@ describe("Quickswap", function() { const [wallet0, wallet1, wallet2, wallet3] = wallets; before(async () => { await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - // @ts-ignore - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 13005785, - }, - }, - ], + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url + // blockNumber: 13005785 + } + } + ] }); masterSigner = await getMasterSigner(); - instaConnectorsV2 = await ethers.getContractAt( - abis.core.connectorsV2, - addresses.core.connectorsV2 - ); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); connector = await deployAndEnableConnector({ connectorName, contractArtifact: ConnectV2Quickswap__factory, signer: masterSigner, - connectors: instaConnectorsV2, + connectors: instaConnectorsV2 }); console.log("Connector address", connector.address); }); - it("Should have contracts deployed.", async function() { + it("Should have contracts deployed.", async function () { expect(!!instaConnectorsV2.address).to.be.true; expect(!!connector.address).to.be.true; expect(!!(await masterSigner.getAddress())).to.be.true; }); - describe("DSA wallet setup", function() { - it("Should build DSA v2", async function() { + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { dsaWallet0 = await buildDSAv2(wallet0.address); expect(!!dsaWallet0.address).to.be.true; }); - it("Deposit ETH & DAI into DSA wallet", async function() { + it("Deposit ETH & DAI into DSA wallet", async function () { await wallet0.sendTransaction({ to: dsaWallet0.address, - value: ethers.utils.parseEther("10"), + value: ethers.utils.parseEther("10") }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( - ethers.utils.parseEther("10") - ); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); - await addLiquidity( - "dai", - dsaWallet0.address, - ethers.utils.parseEther("100000") - ); - }); - - it("Deposit ETH & USDT into DSA wallet", async function() { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10"), - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( - ethers.utils.parseEther("10") - ); - - await addLiquidity( - "usdt", - dsaWallet0.address, - ethers.utils.parseEther("100000") - ); + await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("10000")); }); }); - describe("Main", function() { - it("Should deposit successfully", async function() { - const ethAmount = ethers.utils.parseEther("100"); // 1 ETH - const daiUnitAmount = ethers.utils.parseUnits("4", 6); // 1 ETH - const usdtAmount = Number(ethers.utils.parseEther("400")) / Math.pow(10, 12); // 1 ETH - const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; + describe("Main", function () { + it("Should deposit successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH + const daiUnitAmount = ethers.utils.parseEther("1"); // 1 ETH + const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const getId = "0"; const setId = "0"; @@ -113,26 +87,16 @@ describe("Quickswap", function() { { connector: connectorName, method: "deposit", - args: [ - ethAddress, - DAI_ADDR, - ethAmount, - daiUnitAmount, - "500000000000000000", - getId, - setId, - ], - }, + args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, "500000000000000000", getId, setId] + } ]; - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address); let receipt = await tx.wait(); }).timeout(10000000000); - it("Should withdraw successfully", async function() { - const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH + it("Should withdraw successfully", async function () { + const ethAmount = ethers.utils.parseEther("0.001"); // 1 ETH const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; const getId = "0"; @@ -142,17 +106,15 @@ describe("Quickswap", function() { { connector: connectorName, method: "withdraw", - args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds], - }, + args: [ethAddress, DAI_ADDR, ethAmount, 0, 0, getId, setIds] + } ]; - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address); let receipt = await tx.wait(); }); - it("Should buy successfully", async function() { + it("Should buy successfully", async function () { const ethAmount = ethers.utils.parseEther("0.1"); // 1 ETH const daiUnitAmount = ethers.utils.parseEther("4000"); // 1 ETH const ethAddress = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; @@ -164,13 +126,11 @@ describe("Quickswap", function() { { connector: connectorName, method: "buy", - args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId], - }, + args: [ethAddress, DAI_ADDR, ethAmount, daiUnitAmount, getId, setId] + } ]; - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address); let receipt = await tx.wait(); }); }); From 37f5fe57485b503d40536f60f4d7f798455f657e Mon Sep 17 00:00:00 2001 From: pradyuman-verma Date: Wed, 15 Dec 2021 18:13:58 +0530 Subject: [PATCH 19/31] quickswap deployed update --- contracts/polygon/connectors/quickswap/main.sol | 2 +- scripts/deployment/deploy.ts | 1 + test/polygon/quickswap/quickswap.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol index 6973948b..404b6be0 100644 --- a/contracts/polygon/connectors/quickswap/main.sol +++ b/contracts/polygon/connectors/quickswap/main.sol @@ -251,6 +251,6 @@ abstract contract QuickpswapResolver is Helpers, Events { } } -contract ConnectV2Quickswap is QuickpswapResolver { +contract ConnectV2QuickswapPolygon is QuickpswapResolver { string public constant name = "Quickpswap-v1.1"; } diff --git a/scripts/deployment/deploy.ts b/scripts/deployment/deploy.ts index 381fe091..ac66d9ad 100644 --- a/scripts/deployment/deploy.ts +++ b/scripts/deployment/deploy.ts @@ -18,6 +18,7 @@ async function main() { "GELATO-A": "ConnectV2Gelato", "MAKERDAO-A": "ConnectV2Maker", "UNISWAP-A": "ConnectV2UniswapV2", + "QUICKSWAP-A": "ConnectV2QuickswapPolygon" }; const addressMapping: Record = {}; diff --git a/test/polygon/quickswap/quickswap.test.ts b/test/polygon/quickswap/quickswap.test.ts index 5047fd61..3d3a9346 100644 --- a/test/polygon/quickswap/quickswap.test.ts +++ b/test/polygon/quickswap/quickswap.test.ts @@ -11,7 +11,7 @@ import { addLiquidity } from "../../../scripts/tests/addLiquidity"; import { addresses } from "../../../scripts/tests/polygon/addresses"; import { abis } from "../../../scripts/constant/abis"; -import { ConnectV2Quickswap__factory, ConnectV2Quickswap } from "../../../typechain"; +import { ConnectV2QuickswapPolygon__factory, ConnectV2QuickswapPolygon } from "../../../typechain"; import type { Signer, Contract } from "ethers"; const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063"; @@ -44,7 +44,7 @@ describe("Quickswap", function () { instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); connector = await deployAndEnableConnector({ connectorName, - contractArtifact: ConnectV2Quickswap__factory, + contractArtifact: ConnectV2QuickswapPolygon__factory, signer: masterSigner, connectors: instaConnectorsV2 }); From 70a341244d0ba503085af347ea453952e984feeb Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 21 Dec 2021 15:10:31 +0530 Subject: [PATCH 20/31] Added createAndInitializePool function --- .../polygon/connectors/uniswap/v3/events.sol | 8 ++++++ .../polygon/connectors/uniswap/v3/helpers.sol | 27 ++++++++++++++++--- .../polygon/connectors/uniswap/v3/main.sol | 25 +++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/contracts/polygon/connectors/uniswap/v3/events.sol b/contracts/polygon/connectors/uniswap/v3/events.sol index 829fadd2..b464e28e 100644 --- a/contracts/polygon/connectors/uniswap/v3/events.sol +++ b/contracts/polygon/connectors/uniswap/v3/events.sol @@ -1,6 +1,14 @@ pragma solidity ^0.7.0; contract Events { + event LogcreateAndInitializePool ( + address tokenA, + address tokenB, + address pool, + uint24 fee, + int24 initialTick + ); + event LogMint( uint256 indexed tokenId, uint256 liquidity, diff --git a/contracts/polygon/connectors/uniswap/v3/helpers.sol b/contracts/polygon/connectors/uniswap/v3/helpers.sol index f43be452..70be7093 100644 --- a/contracts/polygon/connectors/uniswap/v3/helpers.sol +++ b/contracts/polygon/connectors/uniswap/v3/helpers.sol @@ -1,9 +1,9 @@ pragma solidity ^0.7.6; pragma abicoder v2; -import {TokenInterface} from "../../../common/interfaces.sol"; -import {DSMath} from "../../../common/math.sol"; -import {Basic} from "../../../common/basic.sol"; +import { TokenInterface} from "../../../common/interfaces.sol"; +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; import "./interface.sol"; import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; import "@uniswap/v3-core/contracts/libraries/TickMath.sol"; @@ -65,6 +65,27 @@ abstract contract Helpers is DSMath, Basic { } } + function _createAndInitializePoolIfNecessary ( + address tokenA, + address tokenB, + uint24 fee, + int24 initialTick + ) internal returns (address pool) { + (tokenA, tokenB) = sortTokenAddress(tokenA, tokenB); + + (TokenInterface _token0, TokenInterface _token1) = changeMaticAddress( + tokenA, + tokenB + ); + + return nftManager.createAndInitializePoolIfNecessary( + address(_token0), + address(_tokenA), + fee, + TickMath.getSqrtRatioAtTick(initialTick) + ); + } + /** * @dev Mint function which interact with Uniswap v3 */ diff --git a/contracts/polygon/connectors/uniswap/v3/main.sol b/contracts/polygon/connectors/uniswap/v3/main.sol index b6195a6f..25fd8d1b 100644 --- a/contracts/polygon/connectors/uniswap/v3/main.sol +++ b/contracts/polygon/connectors/uniswap/v3/main.sol @@ -11,6 +11,31 @@ import {Helpers} from "./helpers.sol"; import {Events} from "./events.sol"; abstract contract UniswapResolver is Helpers, Events { + + function createAndInitializePool ( + address tokenA, + address tokenB, + uint24 fee, + int24 initialTick + ) { + + address pool = _createAndInitializePoolIfNecessary( + tokenA, + tokenB, + fee, + initialTick + ); + + _eventName = "LogcreateAndInitializePool(address,address,address,uint24,int24)"; + _eventParam = abi.encode( + tokenA, + tokenB, + pool, + fee, + initialTick + ); + } + /** * @dev Mint New Position * @notice Mint New NFT LP Position From 4ef4c48a7750134de475a31334f3399df985ff1d Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 21 Dec 2021 15:16:43 +0530 Subject: [PATCH 21/31] minor fix --- contracts/polygon/connectors/uniswap/v3/helpers.sol | 2 +- contracts/polygon/connectors/uniswap/v3/main.sol | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/polygon/connectors/uniswap/v3/helpers.sol b/contracts/polygon/connectors/uniswap/v3/helpers.sol index 70be7093..b93c3284 100644 --- a/contracts/polygon/connectors/uniswap/v3/helpers.sol +++ b/contracts/polygon/connectors/uniswap/v3/helpers.sol @@ -80,7 +80,7 @@ abstract contract Helpers is DSMath, Basic { return nftManager.createAndInitializePoolIfNecessary( address(_token0), - address(_tokenA), + address(_token1), fee, TickMath.getSqrtRatioAtTick(initialTick) ); diff --git a/contracts/polygon/connectors/uniswap/v3/main.sol b/contracts/polygon/connectors/uniswap/v3/main.sol index 25fd8d1b..f0f46689 100644 --- a/contracts/polygon/connectors/uniswap/v3/main.sol +++ b/contracts/polygon/connectors/uniswap/v3/main.sol @@ -17,7 +17,11 @@ abstract contract UniswapResolver is Helpers, Events { address tokenB, uint24 fee, int24 initialTick - ) { + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { address pool = _createAndInitializePoolIfNecessary( tokenA, From a1a5ea743815a61459063b573d4f8da276c000b6 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 21 Dec 2021 17:38:05 +0530 Subject: [PATCH 22/31] Added comments --- contracts/polygon/connectors/uniswap/v3/main.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contracts/polygon/connectors/uniswap/v3/main.sol b/contracts/polygon/connectors/uniswap/v3/main.sol index f0f46689..4cb74195 100644 --- a/contracts/polygon/connectors/uniswap/v3/main.sol +++ b/contracts/polygon/connectors/uniswap/v3/main.sol @@ -12,6 +12,14 @@ import {Events} from "./events.sol"; abstract contract UniswapResolver is Helpers, Events { + /** + * @dev Create and Initialize pool + * @notice Create and Initialize new pool if required + * @param tokenA tokenA addreess + * @param tokenB tokenB addreess + * @param fee fee percentage + * @param initialTick Initial tick for the pool + */ function createAndInitializePool ( address tokenA, address tokenB, From 8269728186dd55e0ba134670625e2a9f8a43ac2e Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Tue, 21 Dec 2021 18:05:49 +0530 Subject: [PATCH 23/31] Updated hardhat.config.ts --- hardhat.config.ts | 11 +- yarn.lock | 515 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 490 insertions(+), 36 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 1c102759..a8e617e1 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -39,15 +39,22 @@ const mnemonic = process.env.MNEMONIC ?? "test test test test test test test test test test test junk"; +const networkGasPriceConfig: Record = { + "mainnet": "160", + "polygon": "50", + "avalanche": "50", + "arbitrum": "2" +} + function createConfig(network: string) { return { url: getNetworkUrl(network), accounts: !!PRIVATE_KEY ? [`0x${PRIVATE_KEY}`] : { mnemonic }, + gasPrice: utils.parseUnits(networkGasPriceConfig[network], "gwei").toNumber(), }; } function getNetworkUrl(networkType: string) { - //console.log(process.env); if (networkType === "avalanche") return "https://api.avax.network/ext/bc/C/rpc"; else if (networkType === "polygon") @@ -112,7 +119,7 @@ const config: HardhatUserConfig = { tests: "./test", }, etherscan: { - apiKey: getScanApiKey(getNetworkUrl(String(process.env.networkType))), + apiKey: getScanApiKey(String(process.env.networkType)), }, typechain: { outDir: "typechain", diff --git a/yarn.lock b/yarn.lock index a5bbacb4..42a9309f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,27 @@ # yarn lockfile v1 +"@babel/code-frame@^7.0.0": + "integrity" "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz" + "version" "7.16.0" + dependencies: + "@babel/highlight" "^7.16.0" + +"@babel/helper-validator-identifier@^7.15.7": + "integrity" "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz" + "version" "7.15.7" + +"@babel/highlight@^7.16.0": + "integrity" "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==" + "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz" + "version" "7.16.0" + dependencies: + "@babel/helper-validator-identifier" "^7.15.7" + "chalk" "^2.0.0" + "js-tokens" "^4.0.0" + "@babel/runtime@^7.4.4": "integrity" "sha512-121rumjddw9c3NCQ55KGkyE1h/nzWhU/owjhw0l4mQrkzz4x9SGS1X8gFLraHwX7td3Yo4QTL+qj0NcIzN87BA==" "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.5.tgz" @@ -1700,6 +1721,11 @@ dependencies: "acorn" "^4.0.3" +"acorn-jsx@^5.0.0": + "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + "version" "5.3.2" + "acorn-walk@^8.1.1": "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" @@ -1715,7 +1741,7 @@ "resolved" "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz" "version" "5.7.4" -"acorn@^6.4.1": +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^6.0.7", "acorn@^6.4.1": "integrity" "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" "resolved" "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" "version" "6.4.2" @@ -1760,7 +1786,7 @@ "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" "version" "3.5.2" -"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.3", "ajv@^6.9.1", "ajv@>=5.0.0": +"ajv@^6.1.0", "ajv@^6.10.0", "ajv@^6.10.2", "ajv@^6.12.3", "ajv@^6.6.1", "ajv@^6.9.1", "ajv@>=5.0.0": "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" "version" "6.12.6" @@ -1799,6 +1825,11 @@ "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz" "version" "3.2.3" +"ansi-escapes@^3.2.0": + "integrity" "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz" + "version" "3.2.0" + "ansi-escapes@^4.2.1", "ansi-escapes@^4.3.0": "integrity" "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==" "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" @@ -1854,6 +1885,11 @@ dependencies: "color-convert" "^2.0.1" +"antlr4@4.7.1": + "integrity" "sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ==" + "resolved" "https://registry.npmjs.org/antlr4/-/antlr4-4.7.1.tgz" + "version" "4.7.1" + "antlr4ts@^0.5.0-alpha.4": "integrity" "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==" "resolved" "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz" @@ -1996,6 +2032,16 @@ "resolved" "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" "version" "1.0.0" +"ast-parents@0.0.1": + "integrity" "sha1-UI/Q8F0MSHddnszaLhdEIyYejdM=" + "resolved" "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz" + "version" "0.0.1" + +"astral-regex@^1.0.0": + "integrity" "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + "resolved" "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz" + "version" "1.0.0" + "async-each@^1.0.1": "integrity" "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" "resolved" "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz" @@ -2940,6 +2986,30 @@ "function-bind" "^1.1.1" "get-intrinsic" "^1.0.2" +"caller-callsite@^2.0.0": + "integrity" "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=" + "resolved" "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "callsites" "^2.0.0" + +"caller-path@^2.0.0": + "integrity" "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=" + "resolved" "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "caller-callsite" "^2.0.0" + +"callsites@^2.0.0": + "integrity" "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + "resolved" "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz" + "version" "2.0.0" + +"callsites@^3.0.0": + "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + "version" "3.1.0" + "camel-case@^3.0.0", "camel-case@3.0.x": "integrity" "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=" "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" @@ -3030,6 +3100,24 @@ "strip-ansi" "^3.0.0" "supports-color" "^2.0.0" +"chalk@^2.0.0": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^2.1.0", "chalk@^2.4.2": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + "chalk@^2.3.2": "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" @@ -3048,15 +3136,6 @@ "escape-string-regexp" "^1.0.5" "supports-color" "^5.3.0" -"chalk@^2.4.2": - "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" - "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - "version" "2.4.2" - dependencies: - "ansi-styles" "^3.2.1" - "escape-string-regexp" "^1.0.5" - "supports-color" "^5.3.0" - "chalk@^4.1.0": "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" @@ -3254,6 +3333,13 @@ dependencies: "source-map" "~0.6.0" +"cli-cursor@^2.1.0": + "integrity" "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=" + "resolved" "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "restore-cursor" "^2.0.0" + "cli-cursor@^3.1.0": "integrity" "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==" "resolved" "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" @@ -3266,6 +3352,11 @@ "resolved" "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz" "version" "2.6.1" +"cli-width@^2.0.0": + "integrity" "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + "resolved" "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz" + "version" "2.2.1" + "cli-width@^3.0.0": "integrity" "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" "resolved" "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz" @@ -3396,6 +3487,11 @@ "resolved" "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz" "version" "2.17.1" +"commander@2.18.0": + "integrity" "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==" + "resolved" "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz" + "version" "2.18.0" + "commander@3.0.2": "integrity" "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" "resolved" "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz" @@ -3548,6 +3644,16 @@ "object-assign" "^4" "vary" "^1" +"cosmiconfig@^5.0.7": + "integrity" "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==" + "resolved" "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz" + "version" "5.2.1" + dependencies: + "import-fresh" "^2.0.0" + "is-directory" "^0.3.1" + "js-yaml" "^3.13.1" + "parse-json" "^4.0.0" + "crc-32@^1.2.0": "integrity" "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==" "resolved" "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz" @@ -3765,7 +3871,7 @@ dependencies: "ms" "^2.1.1" -"debug@^4.1.1", "debug@^4.3.1", "debug@4": +"debug@^4.0.1", "debug@^4.1.1", "debug@^4.3.1", "debug@4": "integrity" "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==" "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" "version" "4.3.1" @@ -3984,6 +4090,13 @@ dependencies: "path-type" "^4.0.0" +"doctrine@^3.0.0": + "integrity" "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==" + "resolved" "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "esutils" "^2.0.2" + "dom-converter@^0.2.0": "integrity" "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==" "resolved" "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz" @@ -4103,6 +4216,11 @@ "minimalistic-assert" "^1.0.0" "minimalistic-crypto-utils" "^1.0.0" +"emoji-regex@^10.0.0": + "integrity" "sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.0.0.tgz" + "version" "10.0.0" + "emoji-regex@^7.0.1": "integrity" "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" @@ -4207,7 +4325,7 @@ dependencies: "prr" "~1.0.1" -"error-ex@^1.2.0": +"error-ex@^1.2.0", "error-ex@^1.3.1": "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" "version" "1.3.2" @@ -4357,6 +4475,11 @@ "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" "version" "1.0.5" +"escape-string-regexp@^4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + "escodegen@1.8.x": "integrity" "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=" "resolved" "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz" @@ -4387,6 +4510,69 @@ "esrecurse" "^4.1.0" "estraverse" "^4.1.1" +"eslint-utils@^1.3.1": + "integrity" "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==" + "resolved" "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz" + "version" "1.4.3" + dependencies: + "eslint-visitor-keys" "^1.1.0" + +"eslint-visitor-keys@^1.0.0", "eslint-visitor-keys@^1.1.0": + "integrity" "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + "version" "1.3.0" + +"eslint@^5.6.0": + "integrity" "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==" + "resolved" "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz" + "version" "5.16.0" + dependencies: + "@babel/code-frame" "^7.0.0" + "ajv" "^6.9.1" + "chalk" "^2.1.0" + "cross-spawn" "^6.0.5" + "debug" "^4.0.1" + "doctrine" "^3.0.0" + "eslint-scope" "^4.0.3" + "eslint-utils" "^1.3.1" + "eslint-visitor-keys" "^1.0.0" + "espree" "^5.0.1" + "esquery" "^1.0.1" + "esutils" "^2.0.2" + "file-entry-cache" "^5.0.1" + "functional-red-black-tree" "^1.0.1" + "glob" "^7.1.2" + "globals" "^11.7.0" + "ignore" "^4.0.6" + "import-fresh" "^3.0.0" + "imurmurhash" "^0.1.4" + "inquirer" "^6.2.2" + "js-yaml" "^3.13.0" + "json-stable-stringify-without-jsonify" "^1.0.1" + "levn" "^0.3.0" + "lodash" "^4.17.11" + "minimatch" "^3.0.4" + "mkdirp" "^0.5.1" + "natural-compare" "^1.4.0" + "optionator" "^0.8.2" + "path-is-inside" "^1.0.2" + "progress" "^2.0.0" + "regexpp" "^2.0.1" + "semver" "^5.5.1" + "strip-ansi" "^4.0.0" + "strip-json-comments" "^2.0.1" + "table" "^5.2.3" + "text-table" "^0.2.0" + +"espree@^5.0.1": + "integrity" "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==" + "resolved" "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "acorn" "^6.0.7" + "acorn-jsx" "^5.0.0" + "eslint-visitor-keys" "^1.0.0" + "esprima@^2.7.1": "integrity" "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" "resolved" "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" @@ -4402,6 +4588,13 @@ "resolved" "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" "version" "2.7.3" +"esquery@^1.0.1": + "integrity" "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==" + "resolved" "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "estraverse" "^5.1.0" + "esrecurse@^4.1.0": "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" @@ -4419,6 +4612,11 @@ "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" "version" "4.3.0" +"estraverse@^5.1.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + "estraverse@^5.2.0": "integrity" "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" @@ -4897,7 +5095,7 @@ "uuid" "2.0.1" "xmlhttprequest" "1.8.0" -"ethers@^5.0.0", "ethers@^5.0.1", "ethers@^5.0.13", "ethers@^5.0.2", "ethers@^5.1.0", "ethers@^5.1.3", "ethers@^5.4.7", "ethers@^5.5.2": +"ethers@^5.0.0", "ethers@^5.0.1", "ethers@^5.0.13", "ethers@^5.1.0", "ethers@^5.1.3", "ethers@^5.4.7", "ethers@^5.5.2": "integrity" "sha512-EF5W+6Wwcu6BqVwpgmyR5U2+L4c1FQzlM/02dkZOugN3KF0cG9bzHZP+TDJglmPm2/IzCEJDT7KBxzayk7SAHw==" "resolved" "https://registry.npmjs.org/ethers/-/ethers-5.5.2.tgz" "version" "5.5.2" @@ -5151,6 +5349,11 @@ "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" "version" "3.1.3" +"fast-diff@^1.1.2": + "integrity" "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + "resolved" "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" + "version" "1.2.0" + "fast-glob@^3.0.3": "integrity" "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==" "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz" @@ -5189,6 +5392,13 @@ "resolved" "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz" "version" "3.5.2" +"figures@^2.0.0": + "integrity" "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=" + "resolved" "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "escape-string-regexp" "^1.0.5" + "figures@^3.0.0": "integrity" "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==" "resolved" "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" @@ -5196,6 +5406,13 @@ dependencies: "escape-string-regexp" "^1.0.5" +"file-entry-cache@^5.0.1": + "integrity" "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==" + "resolved" "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "flat-cache" "^2.0.1" + "file-uri-to-path@1.0.0": "integrity" "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" "resolved" "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" @@ -5298,6 +5515,15 @@ dependencies: "micromatch" "^4.0.2" +"flat-cache@^2.0.1": + "integrity" "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==" + "resolved" "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "flatted" "^2.0.0" + "rimraf" "2.6.3" + "write" "1.0.3" + "flat@^4.1.0": "integrity" "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==" "resolved" "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz" @@ -5305,6 +5531,11 @@ dependencies: "is-buffer" "~2.0.3" +"flatted@^2.0.0": + "integrity" "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" + "resolved" "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz" + "version" "2.0.2" + "flow-stoplight@^1.0.0": "version" "1.0.0" @@ -5766,6 +5997,11 @@ "min-document" "^2.19.0" "process" "^0.11.10" +"globals@^11.7.0": + "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + "version" "11.12.0" + "globals@^9.18.0": "version" "9.18.0" @@ -6279,6 +6515,11 @@ "resolved" "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz" "version" "0.1.5" +"ignore@^4.0.6": + "integrity" "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" + "version" "4.0.6" + "ignore@^5.1.1": "integrity" "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==" "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz" @@ -6299,6 +6540,22 @@ "resolved" "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz" "version" "4.0.0-rc.12" +"import-fresh@^2.0.0": + "integrity" "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=" + "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "caller-path" "^2.0.0" + "resolve-from" "^3.0.0" + +"import-fresh@^3.0.0": + "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" + "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "parent-module" "^1.0.0" + "resolve-from" "^4.0.0" + "imul@^1.0.0": "integrity" "sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk=" "resolved" "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz" @@ -6342,6 +6599,25 @@ "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" "version" "1.3.8" +"inquirer@^6.2.2": + "integrity" "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==" + "resolved" "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz" + "version" "6.5.2" + dependencies: + "ansi-escapes" "^3.2.0" + "chalk" "^2.4.2" + "cli-cursor" "^2.1.0" + "cli-width" "^2.0.0" + "external-editor" "^3.0.3" + "figures" "^2.0.0" + "lodash" "^4.17.12" + "mute-stream" "0.0.7" + "run-async" "^2.2.0" + "rxjs" "^6.4.0" + "string-width" "^2.1.0" + "strip-ansi" "^5.1.0" + "through" "^2.3.6" + "inquirer@^8.2.0": "integrity" "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==" "resolved" "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz" @@ -6525,6 +6801,11 @@ "is-data-descriptor" "^1.0.0" "kind-of" "^6.0.2" +"is-directory@^0.3.1": + "integrity" "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + "resolved" "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz" + "version" "0.3.1" + "is-docker@^2.0.0": "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" @@ -6825,7 +7106,7 @@ "resolved" "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" "version" "0.8.0" -"js-tokens@^3.0.0 || ^4.0.0": +"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0": "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" "version" "4.0.0" @@ -6833,7 +7114,7 @@ "js-tokens@^3.0.2": "version" "3.0.2" -"js-yaml@^3.14.0", "js-yaml@3.x": +"js-yaml@^3.12.0", "js-yaml@^3.13.0", "js-yaml@^3.13.1", "js-yaml@^3.14.0", "js-yaml@3.x": "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==" "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" "version" "3.14.1" @@ -6870,7 +7151,7 @@ "resolved" "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz" "version" "0.5.7" -"json-parse-better-errors@^1.0.2": +"json-parse-better-errors@^1.0.1", "json-parse-better-errors@^1.0.2": "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" "resolved" "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" "version" "1.0.2" @@ -6903,6 +7184,11 @@ "resolved" "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz" "version" "0.2.3" +"json-stable-stringify-without-jsonify@^1.0.1": + "integrity" "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + "resolved" "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + "version" "1.0.1" + "json-stable-stringify@^1.0.1": "version" "1.0.1" dependencies: @@ -7214,7 +7500,7 @@ "level-supports" "~1.0.0" "xtend" "~4.0.0" -"levn@~0.3.0": +"levn@^0.3.0", "levn@~0.3.0": "integrity" "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=" "resolved" "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" "version" "0.3.0" @@ -7325,7 +7611,7 @@ "resolved" "https://registry.npmjs.org/lodash.sum/-/lodash.sum-4.0.2.tgz" "version" "4.0.2" -"lodash@^4.17.11", "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.20", "lodash@^4.17.21", "lodash@^4.17.3": +"lodash@^4.17.11", "lodash@^4.17.12", "lodash@^4.17.14", "lodash@^4.17.15", "lodash@^4.17.20", "lodash@^4.17.21", "lodash@^4.17.3": "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" "version" "4.17.21" @@ -7929,6 +8215,11 @@ "fmix" "^0.1.0" "imul" "^1.0.0" +"mute-stream@0.0.7": + "integrity" "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + "resolved" "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz" + "version" "0.0.7" + "mute-stream@0.0.8": "integrity" "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" "resolved" "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" @@ -7976,6 +8267,11 @@ "resolved" "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz" "version" "1.0.2" +"natural-compare@^1.4.0": + "integrity" "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + "resolved" "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + "version" "1.4.0" + "negotiator@0.6.2": "integrity" "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz" @@ -8314,6 +8610,13 @@ dependencies: "wrappy" "1" +"onetime@^2.0.0": + "integrity" "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=" + "resolved" "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "mimic-fn" "^1.0.0" + "onetime@^5.1.0": "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" @@ -8329,7 +8632,7 @@ "is-docker" "^2.0.0" "is-wsl" "^2.1.1" -"optionator@^0.8.1": +"optionator@^0.8.1", "optionator@^0.8.2": "integrity" "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==" "resolved" "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" "version" "0.8.3" @@ -8499,6 +8802,13 @@ dependencies: "no-case" "^2.2.0" +"parent-module@^1.0.0": + "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" + "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "callsites" "^3.0.0" + "parse-asn1@^5.0.0", "parse-asn1@^5.1.5": "integrity" "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==" "resolved" "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" @@ -8522,6 +8832,14 @@ dependencies: "error-ex" "^1.2.0" +"parse-json@^4.0.0": + "integrity" "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "error-ex" "^1.3.1" + "json-parse-better-errors" "^1.0.1" + "parse5-htmlparser2-tree-adapter@^6.0.1": "integrity" "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==" "resolved" "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" @@ -8631,6 +8949,11 @@ "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" "version" "1.0.1" +"path-is-inside@^1.0.2": + "integrity" "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "resolved" "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" + "version" "1.0.2" + "path-key@^2.0.0", "path-key@^2.0.1": "integrity" "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" "resolved" "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" @@ -8848,15 +9171,32 @@ "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" "version" "2.0.0" +"prettier-plugin-solidity@^1.0.0-beta.18": + "integrity" "sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g==" + "resolved" "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz" + "version" "1.0.0-beta.19" + dependencies: + "@solidity-parser/parser" "^0.14.0" + "emoji-regex" "^10.0.0" + "escape-string-regexp" "^4.0.0" + "semver" "^7.3.5" + "solidity-comments-extractor" "^0.0.7" + "string-width" "^4.2.3" + +"prettier@^1.14.3": + "integrity" "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==" + "resolved" "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz" + "version" "1.19.1" + "prettier@^1.18.2": "integrity" "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==" "resolved" "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz" "version" "1.19.1" -"prettier@^2.1.2": - "integrity" "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==" - "resolved" "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz" - "version" "2.3.2" +"prettier@^2.1.2", "prettier@^2.3.0", "prettier@^2.4.1": + "integrity" "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==" + "resolved" "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz" + "version" "2.5.1" "pretty-error@^2.0.2": "integrity" "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==" @@ -8884,6 +9224,11 @@ "resolved" "https://registry.npmjs.org/process/-/process-0.11.10.tgz" "version" "0.11.10" +"progress@^2.0.0": + "integrity" "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "resolved" "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" + "version" "2.0.3" + "promise-inflight@^1.0.1": "integrity" "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" "resolved" "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" @@ -9283,6 +9628,11 @@ "define-properties" "^1.1.3" "es-abstract" "^1.17.0-next.1" +"regexpp@^2.0.1": + "integrity" "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + "resolved" "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz" + "version" "2.0.1" + "regexpu-core@^2.0.0": "version" "2.0.0" dependencies: @@ -9385,6 +9735,16 @@ "resolved" "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" "version" "2.0.0" +"resolve-from@^3.0.0": + "integrity" "sha1-six699nWiBvItuZTM17rywoYh0g=" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz" + "version" "3.0.0" + +"resolve-from@^4.0.0": + "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + "version" "4.0.0" + "resolve-url@^0.2.1": "integrity" "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" "resolved" "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" @@ -9414,6 +9774,14 @@ dependencies: "lowercase-keys" "^1.0.0" +"restore-cursor@^2.0.0": + "integrity" "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=" + "resolved" "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "onetime" "^2.0.0" + "signal-exit" "^3.0.2" + "restore-cursor@^3.1.0": "integrity" "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==" "resolved" "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" @@ -9451,6 +9819,13 @@ dependencies: "glob" "^7.1.3" +"rimraf@2.6.3": + "integrity" "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==" + "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz" + "version" "2.6.3" + dependencies: + "glob" "^7.1.3" + "ripemd160-min@0.0.6": "integrity" "sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==" "resolved" "https://registry.npmjs.org/ripemd160-min/-/ripemd160-min-0.0.6.tgz" @@ -9471,7 +9846,7 @@ dependencies: "bn.js" "^4.11.1" -"run-async@^2.4.0": +"run-async@^2.2.0", "run-async@^2.4.0": "integrity" "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" "resolved" "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" "version" "2.4.1" @@ -9495,6 +9870,13 @@ "resolved" "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz" "version" "0.2.0" +"rxjs@^6.4.0", "rxjs@6": + "integrity" "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==" + "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" + "version" "6.6.7" + dependencies: + "tslib" "^1.9.0" + "rxjs@^7.2.0": "integrity" "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==" "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz" @@ -9502,13 +9884,6 @@ dependencies: "tslib" "~2.1.0" -"rxjs@6": - "integrity" "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==" - "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" - "version" "6.6.7" - dependencies: - "tslib" "^1.9.0" - "safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@^5.1.1", "safe-buffer@^5.1.2", "safe-buffer@^5.2.0", "safe-buffer@^5.2.1", "safe-buffer@~5.2.0": "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" @@ -9625,6 +10000,11 @@ "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" "version" "5.7.1" +"semver@^5.5.1": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + "semver@^5.7.0": "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" @@ -9831,6 +10211,15 @@ "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" "version" "3.0.0" +"slice-ansi@^2.1.0": + "integrity" "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==" + "resolved" "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "ansi-styles" "^3.2.0" + "astral-regex" "^1.0.0" + "is-fullwidth-code-point" "^2.0.0" + "snake-case@^2.1.0": "integrity" "sha1-Qb2xtz8w7GagTU4srRt2OH1NbZ8=" "resolved" "https://registry.npmjs.org/snake-case/-/snake-case-2.1.0.tgz" @@ -9923,6 +10312,33 @@ "semver" "^5.5.0" "tmp" "0.0.33" +"solhint@^3.3.6": + "integrity" "sha512-HWUxTAv2h7hx3s3hAab3ifnlwb02ZWhwFU/wSudUHqteMS3ll9c+m1FlGn9V8ztE2rf3Z82fQZA005Wv7KpcFA==" + "resolved" "https://registry.npmjs.org/solhint/-/solhint-3.3.6.tgz" + "version" "3.3.6" + dependencies: + "@solidity-parser/parser" "^0.13.2" + "ajv" "^6.6.1" + "antlr4" "4.7.1" + "ast-parents" "0.0.1" + "chalk" "^2.4.2" + "commander" "2.18.0" + "cosmiconfig" "^5.0.7" + "eslint" "^5.6.0" + "fast-diff" "^1.1.2" + "glob" "^7.1.3" + "ignore" "^4.0.6" + "js-yaml" "^3.12.0" + "lodash" "^4.17.11" + "semver" "^6.3.0" + optionalDependencies: + "prettier" "^1.14.3" + +"solidity-comments-extractor@^0.0.7": + "integrity" "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==" + "resolved" "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz" + "version" "0.0.7" + "solidity-coverage@0.7.17": "integrity" "sha512-Erw2hd2xdACAvDX8jUdYkmgJlIIazGznwDJA5dhRaw4def2SisXN9jUjneeyOZnl/E7j6D3XJYug4Zg9iwodsg==" "resolved" "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.17.tgz" @@ -10147,7 +10563,7 @@ "is-fullwidth-code-point" "^1.0.0" "strip-ansi" "^3.0.0" -"string-width@^1.0.2 || 2", "string-width@^2.0.0": +"string-width@^1.0.2 || 2", "string-width@^2.0.0", "string-width@^2.1.0": "integrity" "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==" "resolved" "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" "version" "2.1.1" @@ -10173,6 +10589,15 @@ "is-fullwidth-code-point" "^3.0.0" "strip-ansi" "^6.0.1" +"string-width@^4.2.3": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" + "string.prototype.trim@~1.2.1": "version" "1.2.3" dependencies: @@ -10265,7 +10690,7 @@ "resolved" "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz" "version" "2.0.0" -"strip-json-comments@~2.0.1", "strip-json-comments@2.0.1": +"strip-json-comments@^2.0.1", "strip-json-comments@~2.0.1", "strip-json-comments@2.0.1": "integrity" "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" "version" "2.0.1" @@ -10345,6 +10770,16 @@ "tar" "^4.0.2" "xhr-request" "^1.0.1" +"table@^5.2.3": + "integrity" "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==" + "resolved" "https://registry.npmjs.org/table/-/table-5.4.6.tgz" + "version" "5.4.6" + dependencies: + "ajv" "^6.10.2" + "lodash" "^4.17.14" + "slice-ansi" "^2.1.0" + "string-width" "^3.0.0" + "tapable@^0.2.7": "integrity" "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==" "resolved" "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz" @@ -10445,6 +10880,11 @@ "resolved" "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz" "version" "0.0.1" +"text-table@^0.2.0": + "integrity" "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + "version" "0.2.0" + "through@^2.3.6": "integrity" "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" "resolved" "https://registry.npmjs.org/through/-/through-2.3.8.tgz" @@ -12034,6 +12474,13 @@ "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" "version" "1.0.2" +"write@1.0.3": + "integrity" "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==" + "resolved" "https://registry.npmjs.org/write/-/write-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "mkdirp" "^0.5.1" + "ws@^3.0.0": "integrity" "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==" "resolved" "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz" From 0e6b071665846798674d3d9bd2b276af6df23dc0 Mon Sep 17 00:00:00 2001 From: Thrilok kumar Date: Tue, 21 Dec 2021 18:46:07 +0530 Subject: [PATCH 24/31] Update contracts/polygon/connectors/uniswap/v3/helpers.sol Co-authored-by: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> --- contracts/polygon/connectors/uniswap/v3/helpers.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/polygon/connectors/uniswap/v3/helpers.sol b/contracts/polygon/connectors/uniswap/v3/helpers.sol index b93c3284..f1ae3324 100644 --- a/contracts/polygon/connectors/uniswap/v3/helpers.sol +++ b/contracts/polygon/connectors/uniswap/v3/helpers.sol @@ -71,16 +71,16 @@ abstract contract Helpers is DSMath, Basic { uint24 fee, int24 initialTick ) internal returns (address pool) { - (tokenA, tokenB) = sortTokenAddress(tokenA, tokenB); - - (TokenInterface _token0, TokenInterface _token1) = changeMaticAddress( + (TokenInterface token0Contract_, TokenInterface token1Contract_) = changeMaticAddress( tokenA, tokenB ); + + (address token0_, address token1_) = sortTokenAddress(address(token0Contract_), address(token1Contract_)); return nftManager.createAndInitializePoolIfNecessary( - address(_token0), - address(_token1), + token0_, + token1_, fee, TickMath.getSqrtRatioAtTick(initialTick) ); From 61686a585f23ff19cf6ef2322bc1185a66193fc6 Mon Sep 17 00:00:00 2001 From: bhavik Date: Thu, 23 Dec 2021 00:20:51 +0530 Subject: [PATCH 25/31] added 1inch-v4 --- connector.sol | 2492 +++++++++++++++++ .../1inch/{ => 1inch-v3}/events.sol | 0 .../1inch/{ => 1inch-v3}/helpers.sol | 0 .../1inch/{ => 1inch-v3}/interface.sol | 0 .../connectors/1inch/{ => 1inch-v3}/main.sol | 0 .../connectors/1inch/1inch-v4}/events.sol | 0 .../connectors/1inch/1inch-v4/helpers.sol | 13 + .../connectors/1inch/1inch-v4}/interface.sol | 0 .../connectors/1inch/1inch-v4/main.sol | 112 + .../connectors/1inch/1inch-v3}/events.sol | 0 .../1inch/{ => 1inch-v3}/helpers.sol | 0 .../connectors/1inch/1inch-v3}/interface.sol | 0 .../connectors/1inch/{ => 1inch-v3}/main.sol | 0 .../connectors/1inch/1inch-v4/events.sol | 12 + .../connectors/1inch/1inch-v4/helpers.sol | 13 + .../connectors/1inch/1inch-v4/interface.sol | 30 + .../connectors/1inch/1inch-v4/main.sol | 111 + .../connectors/1inch/1inch-v3/events.sol | 12 + .../1inch/{ => 1inch-v3}/helpers.sol | 0 .../connectors/1inch/1inch-v3/interface.sol | 30 + .../connectors/1inch/{ => 1inch-v3}/main.sol | 0 .../connectors/1inch/1inch-v4/events.sol | 12 + .../connectors/1inch/1inch-v4/helpers.sol | 13 + .../connectors/1inch/1inch-v4/interface.sol | 30 + .../connectors/1inch/1inch-v4/main.sol | 115 + hardhat.config.ts | 2 +- 26 files changed, 2996 insertions(+), 1 deletion(-) create mode 100644 connector.sol rename contracts/arbitrum/connectors/1inch/{ => 1inch-v3}/events.sol (100%) rename contracts/arbitrum/connectors/1inch/{ => 1inch-v3}/helpers.sol (100%) rename contracts/arbitrum/connectors/1inch/{ => 1inch-v3}/interface.sol (100%) rename contracts/arbitrum/connectors/1inch/{ => 1inch-v3}/main.sol (100%) rename contracts/{mainnet/connectors/1inch => arbitrum/connectors/1inch/1inch-v4}/events.sol (100%) create mode 100644 contracts/arbitrum/connectors/1inch/1inch-v4/helpers.sol rename contracts/{mainnet/connectors/1inch => arbitrum/connectors/1inch/1inch-v4}/interface.sol (100%) create mode 100644 contracts/arbitrum/connectors/1inch/1inch-v4/main.sol rename contracts/{polygon/connectors/1inch => mainnet/connectors/1inch/1inch-v3}/events.sol (100%) rename contracts/mainnet/connectors/1inch/{ => 1inch-v3}/helpers.sol (100%) rename contracts/{polygon/connectors/1inch => mainnet/connectors/1inch/1inch-v3}/interface.sol (100%) rename contracts/mainnet/connectors/1inch/{ => 1inch-v3}/main.sol (100%) create mode 100644 contracts/mainnet/connectors/1inch/1inch-v4/events.sol create mode 100644 contracts/mainnet/connectors/1inch/1inch-v4/helpers.sol create mode 100644 contracts/mainnet/connectors/1inch/1inch-v4/interface.sol create mode 100644 contracts/mainnet/connectors/1inch/1inch-v4/main.sol create mode 100644 contracts/polygon/connectors/1inch/1inch-v3/events.sol rename contracts/polygon/connectors/1inch/{ => 1inch-v3}/helpers.sol (100%) create mode 100644 contracts/polygon/connectors/1inch/1inch-v3/interface.sol rename contracts/polygon/connectors/1inch/{ => 1inch-v3}/main.sol (100%) create mode 100644 contracts/polygon/connectors/1inch/1inch-v4/events.sol create mode 100644 contracts/polygon/connectors/1inch/1inch-v4/helpers.sol create mode 100644 contracts/polygon/connectors/1inch/1inch-v4/interface.sol create mode 100644 contracts/polygon/connectors/1inch/1inch-v4/main.sol diff --git a/connector.sol b/connector.sol new file mode 100644 index 00000000..bfcf70f8 --- /dev/null +++ b/connector.sol @@ -0,0 +1,2492 @@ +// Sources flattened with hardhat v2.7.0 https://hardhat.org + +// File contracts/polygon/common/interfaces.sol + +pragma solidity ^0.7.0; + +interface TokenInterface { + function approve(address, uint256) external; + function transfer(address, uint) external; + function transferFrom(address, address, uint) external; + function deposit() external payable; + function withdraw(uint) external; + function balanceOf(address) external view returns (uint); + function decimals() external view returns (uint); +} + +interface MemoryInterface { + function getUint(uint id) external returns (uint num); + function setUint(uint id, uint val) external; +} + +interface InstaMapping { + function cTokenMapping(address) external view returns (address); + function gemJoinMapping(bytes32) external view returns (address); +} + +interface AccountInterface { + function enable(address) external; + function disable(address) external; + function isAuth(address) external view returns (bool); +} + + +// File @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol@v3.4.2 + +pragma solidity >=0.6.0 <0.8.0; + +/** + * @title ERC721 token receiver interface + * @dev Interface for any contract that wants to support safeTransfers + * from ERC721 asset contracts. + */ +interface IERC721Receiver { + /** + * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} + * by `operator` from `from`, this function is called. + * + * It must return its Solidity selector to confirm the token transfer. + * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. + * + * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. + */ + function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); +} + + +// File @uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title The interface for the Uniswap V3 Factory +/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees +interface IUniswapV3Factory { + /// @notice Emitted when the owner of the factory is changed + /// @param oldOwner The owner before the owner was changed + /// @param newOwner The owner after the owner was changed + event OwnerChanged(address indexed oldOwner, address indexed newOwner); + + /// @notice Emitted when a pool is created + /// @param token0 The first token of the pool by address sort order + /// @param token1 The second token of the pool by address sort order + /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip + /// @param tickSpacing The minimum number of ticks between initialized ticks + /// @param pool The address of the created pool + event PoolCreated( + address indexed token0, + address indexed token1, + uint24 indexed fee, + int24 tickSpacing, + address pool + ); + + /// @notice Emitted when a new fee amount is enabled for pool creation via the factory + /// @param fee The enabled fee, denominated in hundredths of a bip + /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee + event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing); + + /// @notice Returns the current owner of the factory + /// @dev Can be changed by the current owner via setOwner + /// @return The address of the factory owner + function owner() external view returns (address); + + /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled + /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context + /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee + /// @return The tick spacing + function feeAmountTickSpacing(uint24 fee) external view returns (int24); + + /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist + /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order + /// @param tokenA The contract address of either token0 or token1 + /// @param tokenB The contract address of the other token + /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip + /// @return pool The pool address + function getPool( + address tokenA, + address tokenB, + uint24 fee + ) external view returns (address pool); + + /// @notice Creates a pool for the given two tokens and fee + /// @param tokenA One of the two tokens in the desired pool + /// @param tokenB The other of the two tokens in the desired pool + /// @param fee The desired fee for the pool + /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved + /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments + /// are invalid. + /// @return pool The address of the newly created pool + function createPool( + address tokenA, + address tokenB, + uint24 fee + ) external returns (address pool); + + /// @notice Updates the owner of the factory + /// @dev Must be called by the current owner + /// @param _owner The new owner of the factory + function setOwner(address _owner) external; + + /// @notice Enables a fee amount with the given tickSpacing + /// @dev Fee amounts may never be removed once enabled + /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6) + /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount + function enableFeeAmount(uint24 fee, int24 tickSpacing) external; +} + + +// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title Pool state that never changes +/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values +interface IUniswapV3PoolImmutables { + /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface + /// @return The contract address + function factory() external view returns (address); + + /// @notice The first of the two tokens of the pool, sorted by address + /// @return The token contract address + function token0() external view returns (address); + + /// @notice The second of the two tokens of the pool, sorted by address + /// @return The token contract address + function token1() external view returns (address); + + /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6 + /// @return The fee + function fee() external view returns (uint24); + + /// @notice The pool tick spacing + /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive + /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ... + /// This value is an int24 to avoid casting even though it is always positive. + /// @return The tick spacing + function tickSpacing() external view returns (int24); + + /// @notice The maximum amount of position liquidity that can use any tick in the range + /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and + /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool + /// @return The max amount of liquidity per tick + function maxLiquidityPerTick() external view returns (uint128); +} + + +// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title Pool state that can change +/// @notice These methods compose the pool's state, and can change with any frequency including multiple times +/// per transaction +interface IUniswapV3PoolState { + /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas + /// when accessed externally. + /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value + /// tick The current tick of the pool, i.e. according to the last tick transition that was run. + /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick + /// boundary. + /// observationIndex The index of the last oracle observation that was written, + /// observationCardinality The current maximum number of observations stored in the pool, + /// observationCardinalityNext The next maximum number of observations, to be updated when the observation. + /// feeProtocol The protocol fee for both tokens of the pool. + /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0 + /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee. + /// unlocked Whether the pool is currently locked to reentrancy + function slot0() + external + view + returns ( + uint160 sqrtPriceX96, + int24 tick, + uint16 observationIndex, + uint16 observationCardinality, + uint16 observationCardinalityNext, + uint8 feeProtocol, + bool unlocked + ); + + /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool + /// @dev This value can overflow the uint256 + function feeGrowthGlobal0X128() external view returns (uint256); + + /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool + /// @dev This value can overflow the uint256 + function feeGrowthGlobal1X128() external view returns (uint256); + + /// @notice The amounts of token0 and token1 that are owed to the protocol + /// @dev Protocol fees will never exceed uint128 max in either token + function protocolFees() external view returns (uint128 token0, uint128 token1); + + /// @notice The currently in range liquidity available to the pool + /// @dev This value has no relationship to the total liquidity across all ticks + function liquidity() external view returns (uint128); + + /// @notice Look up information about a specific tick in the pool + /// @param tick The tick to look up + /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or + /// tick upper, + /// liquidityNet how much liquidity changes when the pool price crosses the tick, + /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0, + /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1, + /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick + /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick, + /// secondsOutside the seconds spent on the other side of the tick from the current tick, + /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false. + /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0. + /// In addition, these values are only relative and must be used only in comparison to previous snapshots for + /// a specific position. + function ticks(int24 tick) + external + view + returns ( + uint128 liquidityGross, + int128 liquidityNet, + uint256 feeGrowthOutside0X128, + uint256 feeGrowthOutside1X128, + int56 tickCumulativeOutside, + uint160 secondsPerLiquidityOutsideX128, + uint32 secondsOutside, + bool initialized + ); + + /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information + function tickBitmap(int16 wordPosition) external view returns (uint256); + + /// @notice Returns the information about a position by the position's key + /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper + /// @return _liquidity The amount of liquidity in the position, + /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke, + /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke, + /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke, + /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke + function positions(bytes32 key) + external + view + returns ( + uint128 _liquidity, + uint256 feeGrowthInside0LastX128, + uint256 feeGrowthInside1LastX128, + uint128 tokensOwed0, + uint128 tokensOwed1 + ); + + /// @notice Returns data about a specific observation index + /// @param index The element of the observations array to fetch + /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time + /// ago, rather than at a specific index in the array. + /// @return blockTimestamp The timestamp of the observation, + /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp, + /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp, + /// Returns initialized whether the observation has been initialized and the values are safe to use + function observations(uint256 index) + external + view + returns ( + uint32 blockTimestamp, + int56 tickCumulative, + uint160 secondsPerLiquidityCumulativeX128, + bool initialized + ); +} + + +// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title Pool state that is not stored +/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the +/// blockchain. The functions here may have variable gas costs. +interface IUniswapV3PoolDerivedState { + /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp + /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing + /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick, + /// you must call it with secondsAgos = [3600, 0]. + /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in + /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio. + /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned + /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp + /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block + /// timestamp + function observe(uint32[] calldata secondsAgos) + external + view + returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s); + + /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range + /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed. + /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first + /// snapshot is taken and the second snapshot is taken. + /// @param tickLower The lower tick of the range + /// @param tickUpper The upper tick of the range + /// @return tickCumulativeInside The snapshot of the tick accumulator for the range + /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range + /// @return secondsInside The snapshot of seconds per liquidity for the range + function snapshotCumulativesInside(int24 tickLower, int24 tickUpper) + external + view + returns ( + int56 tickCumulativeInside, + uint160 secondsPerLiquidityInsideX128, + uint32 secondsInside + ); +} + + +// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title Permissionless pool actions +/// @notice Contains pool methods that can be called by anyone +interface IUniswapV3PoolActions { + /// @notice Sets the initial price for the pool + /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value + /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96 + function initialize(uint160 sqrtPriceX96) external; + + /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position + /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback + /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends + /// on tickLower, tickUpper, the amount of liquidity, and the current price. + /// @param recipient The address for which the liquidity will be created + /// @param tickLower The lower tick of the position in which to add liquidity + /// @param tickUpper The upper tick of the position in which to add liquidity + /// @param amount The amount of liquidity to mint + /// @param data Any data that should be passed through to the callback + /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback + /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback + function mint( + address recipient, + int24 tickLower, + int24 tickUpper, + uint128 amount, + bytes calldata data + ) external returns (uint256 amount0, uint256 amount1); + + /// @notice Collects tokens owed to a position + /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity. + /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or + /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the + /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity. + /// @param recipient The address which should receive the fees collected + /// @param tickLower The lower tick of the position for which to collect fees + /// @param tickUpper The upper tick of the position for which to collect fees + /// @param amount0Requested How much token0 should be withdrawn from the fees owed + /// @param amount1Requested How much token1 should be withdrawn from the fees owed + /// @return amount0 The amount of fees collected in token0 + /// @return amount1 The amount of fees collected in token1 + function collect( + address recipient, + int24 tickLower, + int24 tickUpper, + uint128 amount0Requested, + uint128 amount1Requested + ) external returns (uint128 amount0, uint128 amount1); + + /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position + /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0 + /// @dev Fees must be collected separately via a call to #collect + /// @param tickLower The lower tick of the position for which to burn liquidity + /// @param tickUpper The upper tick of the position for which to burn liquidity + /// @param amount How much liquidity to burn + /// @return amount0 The amount of token0 sent to the recipient + /// @return amount1 The amount of token1 sent to the recipient + function burn( + int24 tickLower, + int24 tickUpper, + uint128 amount + ) external returns (uint256 amount0, uint256 amount1); + + /// @notice Swap token0 for token1, or token1 for token0 + /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback + /// @param recipient The address to receive the output of the swap + /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0 + /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) + /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this + /// value after the swap. If one for zero, the price cannot be greater than this value after the swap + /// @param data Any data to be passed through to the callback + /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive + /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive + function swap( + address recipient, + bool zeroForOne, + int256 amountSpecified, + uint160 sqrtPriceLimitX96, + bytes calldata data + ) external returns (int256 amount0, int256 amount1); + + /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback + /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback + /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling + /// with 0 amount{0,1} and sending the donation amount(s) from the callback + /// @param recipient The address which will receive the token0 and token1 amounts + /// @param amount0 The amount of token0 to send + /// @param amount1 The amount of token1 to send + /// @param data Any data to be passed through to the callback + function flash( + address recipient, + uint256 amount0, + uint256 amount1, + bytes calldata data + ) external; + + /// @notice Increase the maximum number of price and liquidity observations that this pool will store + /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to + /// the input observationCardinalityNext. + /// @param observationCardinalityNext The desired minimum number of observations for the pool to store + function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external; +} + + +// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title Permissioned pool actions +/// @notice Contains pool methods that may only be called by the factory owner +interface IUniswapV3PoolOwnerActions { + /// @notice Set the denominator of the protocol's % share of the fees + /// @param feeProtocol0 new protocol fee for token0 of the pool + /// @param feeProtocol1 new protocol fee for token1 of the pool + function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external; + + /// @notice Collect the protocol fee accrued to the pool + /// @param recipient The address to which collected protocol fees should be sent + /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1 + /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0 + /// @return amount0 The protocol fee collected in token0 + /// @return amount1 The protocol fee collected in token1 + function collectProtocol( + address recipient, + uint128 amount0Requested, + uint128 amount1Requested + ) external returns (uint128 amount0, uint128 amount1); +} + + +// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title Events emitted by a pool +/// @notice Contains all events emitted by the pool +interface IUniswapV3PoolEvents { + /// @notice Emitted exactly once by a pool when #initialize is first called on the pool + /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize + /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96 + /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool + event Initialize(uint160 sqrtPriceX96, int24 tick); + + /// @notice Emitted when liquidity is minted for a given position + /// @param sender The address that minted the liquidity + /// @param owner The owner of the position and recipient of any minted liquidity + /// @param tickLower The lower tick of the position + /// @param tickUpper The upper tick of the position + /// @param amount The amount of liquidity minted to the position range + /// @param amount0 How much token0 was required for the minted liquidity + /// @param amount1 How much token1 was required for the minted liquidity + event Mint( + address sender, + address indexed owner, + int24 indexed tickLower, + int24 indexed tickUpper, + uint128 amount, + uint256 amount0, + uint256 amount1 + ); + + /// @notice Emitted when fees are collected by the owner of a position + /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees + /// @param owner The owner of the position for which fees are collected + /// @param tickLower The lower tick of the position + /// @param tickUpper The upper tick of the position + /// @param amount0 The amount of token0 fees collected + /// @param amount1 The amount of token1 fees collected + event Collect( + address indexed owner, + address recipient, + int24 indexed tickLower, + int24 indexed tickUpper, + uint128 amount0, + uint128 amount1 + ); + + /// @notice Emitted when a position's liquidity is removed + /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect + /// @param owner The owner of the position for which liquidity is removed + /// @param tickLower The lower tick of the position + /// @param tickUpper The upper tick of the position + /// @param amount The amount of liquidity to remove + /// @param amount0 The amount of token0 withdrawn + /// @param amount1 The amount of token1 withdrawn + event Burn( + address indexed owner, + int24 indexed tickLower, + int24 indexed tickUpper, + uint128 amount, + uint256 amount0, + uint256 amount1 + ); + + /// @notice Emitted by the pool for any swaps between token0 and token1 + /// @param sender The address that initiated the swap call, and that received the callback + /// @param recipient The address that received the output of the swap + /// @param amount0 The delta of the token0 balance of the pool + /// @param amount1 The delta of the token1 balance of the pool + /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96 + /// @param liquidity The liquidity of the pool after the swap + /// @param tick The log base 1.0001 of price of the pool after the swap + event Swap( + address indexed sender, + address indexed recipient, + int256 amount0, + int256 amount1, + uint160 sqrtPriceX96, + uint128 liquidity, + int24 tick + ); + + /// @notice Emitted by the pool for any flashes of token0/token1 + /// @param sender The address that initiated the swap call, and that received the callback + /// @param recipient The address that received the tokens from flash + /// @param amount0 The amount of token0 that was flashed + /// @param amount1 The amount of token1 that was flashed + /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee + /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee + event Flash( + address indexed sender, + address indexed recipient, + uint256 amount0, + uint256 amount1, + uint256 paid0, + uint256 paid1 + ); + + /// @notice Emitted by the pool for increases to the number of observations that can be stored + /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index + /// just before a mint/swap/burn. + /// @param observationCardinalityNextOld The previous value of the next observation cardinality + /// @param observationCardinalityNextNew The updated value of the next observation cardinality + event IncreaseObservationCardinalityNext( + uint16 observationCardinalityNextOld, + uint16 observationCardinalityNextNew + ); + + /// @notice Emitted when the protocol fee is changed by the pool + /// @param feeProtocol0Old The previous value of the token0 protocol fee + /// @param feeProtocol1Old The previous value of the token1 protocol fee + /// @param feeProtocol0New The updated value of the token0 protocol fee + /// @param feeProtocol1New The updated value of the token1 protocol fee + event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New); + + /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner + /// @param sender The address that collects the protocol fees + /// @param recipient The address that receives the collected protocol fees + /// @param amount0 The amount of token0 protocol fees that is withdrawn + /// @param amount0 The amount of token1 protocol fees that is withdrawn + event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1); +} + + +// File @uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol@v1.0.0 + +pragma solidity >=0.5.0; + + + + + + +/// @title The interface for a Uniswap V3 Pool +/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform +/// to the ERC20 specification +/// @dev The pool interface is broken up into many smaller pieces +interface IUniswapV3Pool is + IUniswapV3PoolImmutables, + IUniswapV3PoolState, + IUniswapV3PoolDerivedState, + IUniswapV3PoolActions, + IUniswapV3PoolOwnerActions, + IUniswapV3PoolEvents +{ + +} + + +// File @uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol@v1.0.0 + +pragma solidity >=0.5.0; + +/// @title Minimal ERC20 interface for Uniswap +/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 +interface IERC20Minimal { + /// @notice Returns the balance of a token + /// @param account The account for which to look up the number of tokens it has, i.e. its balance + /// @return The number of tokens held by the account + function balanceOf(address account) external view returns (uint256); + + /// @notice Transfers the amount of token from the `msg.sender` to the recipient + /// @param recipient The account that will receive the amount transferred + /// @param amount The number of tokens to send from the sender to the recipient + /// @return Returns true for a successful transfer, false for an unsuccessful transfer + function transfer(address recipient, uint256 amount) external returns (bool); + + /// @notice Returns the current allowance given to a spender by an owner + /// @param owner The account of the token owner + /// @param spender The account of the token spender + /// @return The current allowance granted by `owner` to `spender` + function allowance(address owner, address spender) external view returns (uint256); + + /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` + /// @param spender The account which will be allowed to spend a given amount of the owners tokens + /// @param amount The amount of tokens allowed to be used by `spender` + /// @return Returns true for a successful approval, false for unsuccessful + function approve(address spender, uint256 amount) external returns (bool); + + /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` + /// @param sender The account from which the transfer will be initiated + /// @param recipient The recipient of the transfer + /// @param amount The amount of the transfer + /// @return Returns true for a successful transfer, false for unsuccessful + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool); + + /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. + /// @param from The account from which the tokens were sent, i.e. the balance decreased + /// @param to The account to which the tokens were sent, i.e. the balance increased + /// @param value The amount of tokens that were transferred + event Transfer(address indexed from, address indexed to, uint256 value); + + /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. + /// @param owner The account that approved spending of its tokens + /// @param spender The account for which the spending allowance was modified + /// @param value The new allowance from the owner to the spender + event Approval(address indexed owner, address indexed spender, uint256 value); +} + + +// File @openzeppelin/contracts/introspection/IERC165.sol@v3.4.2 + + +pragma solidity >=0.6.0 <0.8.0; + +/** + * @dev Interface of the ERC165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[EIP]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165 { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} + + +// File @openzeppelin/contracts/token/ERC721/IERC721.sol@v3.4.2 + + +pragma solidity >=0.6.2 <0.8.0; + +/** + * @dev Required interface of an ERC721 compliant contract. + */ +interface IERC721 is IERC165 { + /** + * @dev Emitted when `tokenId` token is transferred from `from` to `to`. + */ + event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); + + /** + * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. + */ + event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); + + /** + * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. + */ + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + + /** + * @dev Returns the number of tokens in ``owner``'s account. + */ + function balanceOf(address owner) external view returns (uint256 balance); + + /** + * @dev Returns the owner of the `tokenId` token. + * + * Requirements: + * + * - `tokenId` must exist. + */ + function ownerOf(uint256 tokenId) external view returns (address owner); + + /** + * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients + * are aware of the ERC721 protocol to prevent tokens from being forever locked. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must exist and be owned by `from`. + * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function safeTransferFrom(address from, address to, uint256 tokenId) external; + + /** + * @dev Transfers `tokenId` token from `from` to `to`. + * + * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must be owned by `from`. + * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. + * + * Emits a {Transfer} event. + */ + function transferFrom(address from, address to, uint256 tokenId) external; + + /** + * @dev Gives permission to `to` to transfer `tokenId` token to another account. + * The approval is cleared when the token is transferred. + * + * Only a single account can be approved at a time, so approving the zero address clears previous approvals. + * + * Requirements: + * + * - The caller must own the token or be an approved operator. + * - `tokenId` must exist. + * + * Emits an {Approval} event. + */ + function approve(address to, uint256 tokenId) external; + + /** + * @dev Returns the account approved for `tokenId` token. + * + * Requirements: + * + * - `tokenId` must exist. + */ + function getApproved(uint256 tokenId) external view returns (address operator); + + /** + * @dev Approve or remove `operator` as an operator for the caller. + * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. + * + * Requirements: + * + * - The `operator` cannot be the caller. + * + * Emits an {ApprovalForAll} event. + */ + function setApprovalForAll(address operator, bool _approved) external; + + /** + * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. + * + * See {setApprovalForAll} + */ + function isApprovedForAll(address owner, address operator) external view returns (bool); + + /** + * @dev Safely transfers `tokenId` token from `from` to `to`. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `tokenId` token must exist and be owned by `from`. + * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. + * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. + * + * Emits a {Transfer} event. + */ + function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; +} + + +// File @openzeppelin/contracts/token/ERC721/IERC721Metadata.sol@v3.4.2 + + +pragma solidity >=0.6.2 <0.8.0; + +/** + * @title ERC-721 Non-Fungible Token Standard, optional metadata extension + * @dev See https://eips.ethereum.org/EIPS/eip-721 + */ +interface IERC721Metadata is IERC721 { + + /** + * @dev Returns the token collection name. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the token collection symbol. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. + */ + function tokenURI(uint256 tokenId) external view returns (string memory); +} + + +// File @openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol@v3.4.2 + + + +pragma solidity >=0.6.2 <0.8.0; + +/** + * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension + * @dev See https://eips.ethereum.org/EIPS/eip-721 + */ +interface IERC721Enumerable is IERC721 { + + /** + * @dev Returns the total amount of tokens stored by the contract. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns a token ID owned by `owner` at a given `index` of its token list. + * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. + */ + function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); + + /** + * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. + * Use along with {totalSupply} to enumerate all tokens. + */ + function tokenByIndex(uint256 index) external view returns (uint256); +} + + +// File @uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol@v1.3.0 + +pragma solidity >=0.7.5; +pragma abicoder v2; + +/// @title Creates and initializes V3 Pools +/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that +/// require the pool to exist. +interface IPoolInitializer { + /// @notice Creates a new pool if it does not exist, then initializes if not initialized + /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool + /// @param token0 The contract address of token0 of the pool + /// @param token1 The contract address of token1 of the pool + /// @param fee The fee amount of the v3 pool for the specified token pair + /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value + /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary + function createAndInitializePoolIfNecessary( + address token0, + address token1, + uint24 fee, + uint160 sqrtPriceX96 + ) external payable returns (address pool); +} + + +// File @uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol@v1.3.0 + +pragma solidity >=0.7.5; + +/// @title ERC721 with permit +/// @notice Extension to ERC721 that includes a permit function for signature based approvals +interface IERC721Permit is IERC721 { + /// @notice The permit typehash used in the permit signature + /// @return The typehash for the permit + function PERMIT_TYPEHASH() external pure returns (bytes32); + + /// @notice The domain separator used in the permit signature + /// @return The domain seperator used in encoding of permit signature + function DOMAIN_SEPARATOR() external view returns (bytes32); + + /// @notice Approve of a specific token ID for spending by spender via signature + /// @param spender The account that is being approved + /// @param tokenId The ID of the token that is being approved for spending + /// @param deadline The deadline timestamp by which the call must be mined for the approve to work + /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` + /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` + /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` + function permit( + address spender, + uint256 tokenId, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external payable; +} + + +// File @uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol@v1.3.0 + +pragma solidity >=0.7.5; + +/// @title Periphery Payments +/// @notice Functions to ease deposits and withdrawals of ETH +interface IPeripheryPayments { + /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH. + /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users. + /// @param amountMinimum The minimum amount of WETH9 to unwrap + /// @param recipient The address receiving ETH + function unwrapWETH9(uint256 amountMinimum, address recipient) external payable; + + /// @notice Refunds any ETH balance held by this contract to the `msg.sender` + /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps + /// that use ether for the input amount + function refundETH() external payable; + + /// @notice Transfers the full amount of a token held by this contract to recipient + /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users + /// @param token The contract address of the token which will be transferred to `recipient` + /// @param amountMinimum The minimum amount of token required for a transfer + /// @param recipient The destination address of the token + function sweepToken( + address token, + uint256 amountMinimum, + address recipient + ) external payable; +} + + +// File @uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol@v1.3.0 + +pragma solidity >=0.5.0; + +/// @title Immutable state +/// @notice Functions that return immutable state of the router +interface IPeripheryImmutableState { + /// @return Returns the address of the Uniswap V3 factory + function factory() external view returns (address); + + /// @return Returns the address of WETH9 + function WETH9() external view returns (address); +} + + +// File @uniswap/v3-periphery/contracts/libraries/PoolAddress.sol@v1.3.0 + +pragma solidity >=0.5.0; + +/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee +library PoolAddress { + bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; + + /// @notice The identifying key of the pool + struct PoolKey { + address token0; + address token1; + uint24 fee; + } + + /// @notice Returns PoolKey: the ordered tokens with the matched fee levels + /// @param tokenA The first token of a pool, unsorted + /// @param tokenB The second token of a pool, unsorted + /// @param fee The fee level of the pool + /// @return Poolkey The pool details with ordered token0 and token1 assignments + function getPoolKey( + address tokenA, + address tokenB, + uint24 fee + ) internal pure returns (PoolKey memory) { + if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); + return PoolKey({token0: tokenA, token1: tokenB, fee: fee}); + } + + /// @notice Deterministically computes the pool address given the factory and PoolKey + /// @param factory The Uniswap V3 factory contract address + /// @param key The PoolKey + /// @return pool The contract address of the V3 pool + function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) { + require(key.token0 < key.token1); + pool = address( + uint256( + keccak256( + abi.encodePacked( + hex'ff', + factory, + keccak256(abi.encode(key.token0, key.token1, key.fee)), + POOL_INIT_CODE_HASH + ) + ) + ) + ); + } +} + + +// File @uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol@v1.3.0 + +0x929376C77A2fB8152375a089a4Fccf84Ff481479pragma solidity >=0.7.5; +pragma abicoder v2; + + + + + + +/// @title Non-fungible token for positions +/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred +/// and authorized. +interface INonfungiblePositionManager is + IPoolInitializer, + IPeripheryPayments, + IPeripheryImmutableState, + IERC721Metadata, + IERC721Enumerable, + IERC721Permit +{ + /// @notice Emitted when liquidity is increased for a position NFT + /// @dev Also emitted when a token is minted + /// @param tokenId The ID of the token for which liquidity was increased + /// @param liquidity The amount by which liquidity for the NFT position was increased + /// @param amount0 The amount of token0 that was paid for the increase in liquidity + /// @param amount1 The amount of token1 that was paid for the increase in liquidity + event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); + /// @notice Emitted when liquidity is decreased for a position NFT + /// @param tokenId The ID of the token for which liquidity was decreased + /// @param liquidity The amount by which liquidity for the NFT position was decreased + /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity + /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity + event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); + /// @notice Emitted when tokens are collected for a position NFT + /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior + /// @param tokenId The ID of the token for which underlying tokens were collected + /// @param recipient The address of the account that received the collected tokens + /// @param amount0 The amount of token0 owed to the position that was collected + /// @param amount1 The amount of token1 owed to the position that was collected + event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1); + + /// @notice Returns the position information associated with a given token ID. + /// @dev Throws if the token ID is not valid. + /// @param tokenId The ID of the token that represents the position + /// @return nonce The nonce for permits + /// @return operator The address that is approved for spending + /// @return token0 The address of the token0 for a specific pool + /// @return token1 The address of the token1 for a specific pool + /// @return fee The fee associated with the pool + /// @return tickLower The lower end of the tick range for the position + /// @return tickUpper The higher end of the tick range for the position + /// @return liquidity The liquidity of the position + /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position + /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position + /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation + /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation + function positions(uint256 tokenId) + external + view + returns ( + uint96 nonce, + address operator, + address token0, + address token1, + uint24 fee, + int24 tickLower, + int24 tickUpper, + uint128 liquidity, + uint256 feeGrowthInside0LastX128, + uint256 feeGrowthInside1LastX128, + uint128 tokensOwed0, + uint128 tokensOwed1 + ); + + struct MintParams { + address token0; + address token1; + uint24 fee; + int24 tickLower; + int24 tickUpper; + uint256 amount0Desired; + uint256 amount1Desired; + uint256 amount0Min; + uint256 amount1Min; + address recipient; + uint256 deadline; + } + + /// @notice Creates a new position wrapped in a NFT + /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized + /// a method does not exist, i.e. the pool is assumed to be initialized. + /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata + /// @return tokenId The ID of the token that represents the minted position + /// @return liquidity The amount of liquidity for this position + /// @return amount0 The amount of token0 + /// @return amount1 The amount of token1 + function mint(MintParams calldata params) + external + payable + returns ( + uint256 tokenId, + uint128 liquidity, + uint256 amount0, + uint256 amount1 + ); + + struct IncreaseLiquidityParams { + uint256 tokenId; + uint256 amount0Desired; + uint256 amount1Desired; + uint256 amount0Min; + uint256 amount1Min; + uint256 deadline; + } + + /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender` + /// @param params tokenId The ID of the token for which liquidity is being increased, + /// amount0Desired The desired amount of token0 to be spent, + /// amount1Desired The desired amount of token1 to be spent, + /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check, + /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check, + /// deadline The time by which the transaction must be included to effect the change + /// @return liquidity The new liquidity amount as a result of the increase + /// @return amount0 The amount of token0 to acheive resulting liquidity + /// @return amount1 The amount of token1 to acheive resulting liquidity + function increaseLiquidity(IncreaseLiquidityParams calldata params) + external + payable + returns ( + uint128 liquidity, + uint256 amount0, + uint256 amount1 + ); + + struct DecreaseLiquidityParams { + uint256 tokenId; + uint128 liquidity; + uint256 amount0Min; + uint256 amount1Min; + uint256 deadline; + } + + /// @notice Decreases the amount of liquidity in a position and accounts it to the position + /// @param params tokenId The ID of the token for which liquidity is being decreased, + /// amount The amount by which liquidity will be decreased, + /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity, + /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity, + /// deadline The time by which the transaction must be included to effect the change + /// @return amount0 The amount of token0 accounted to the position's tokens owed + /// @return amount1 The amount of token1 accounted to the position's tokens owed + function decreaseLiquidity(DecreaseLiquidityParams calldata params) + external + payable + returns (uint256 amount0, uint256 amount1); + + struct CollectParams { + uint256 tokenId; + address recipient; + uint128 amount0Max; + uint128 amount1Max; + } + + /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient + /// @param params tokenId The ID of the NFT for which tokens are being collected, + /// recipient The account that should receive the tokens, + /// amount0Max The maximum amount of token0 to collect, + /// amount1Max The maximum amount of token1 to collect + /// @return amount0 The amount of fees collected in token0 + /// @return amount1 The amount of fees collected in token1 + function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1); + + /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens + /// must be collected first. + /// @param tokenId The ID of the token that is being burned + function burn(uint256 tokenId) external payable; +} + + +// File @uniswap/v3-periphery/contracts/interfaces/IMulticall.sol@v1.3.0 + +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.7.5; +pragma abicoder v2; + +/// @title Multicall interface +/// @notice Enables calling multiple methods in a single call to the contract +interface IMulticall { + /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed + /// @dev The `msg.value` should not be trusted for any method callable from multicall. + /// @param data The encoded function data for each of the calls to make to this contract + /// @return results The results from each of the calls passed in via data + function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); +} + + +// File contracts/polygon/connectors/uniswap/v3_staker/interface.sol + +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity =0.7.6; +pragma abicoder v2; +/// @title Uniswap V3 Staker Interface +/// @notice Allows staking nonfungible liquidity tokens in exchange for reward tokens +interface IUniswapV3Staker is IERC721Receiver, IMulticall { + /// @param rewardToken The token being distributed as a reward + /// @param pool The Uniswap V3 pool + /// @param startTime The time when the incentive program begins + /// @param endTime The time when rewards stop accruing + /// @param refundee The address which receives any remaining reward tokens when the incentive is ended + struct IncentiveKey { + IERC20Minimal rewardToken; + IUniswapV3Pool pool; + uint256 startTime; + uint256 endTime; + address refundee; + } + + /// @notice The Uniswap V3 Factory + function factory() external view returns (IUniswapV3Factory); + + /// @notice The nonfungible position manager with which this staking contract is compatible + function nonfungiblePositionManager() external view returns (INonfungiblePositionManager); + + /// @notice The max duration of an incentive in seconds + function maxIncentiveDuration() external view returns (uint256); + + /// @notice The max amount of seconds into the future the incentive startTime can be set + function maxIncentiveStartLeadTime() external view returns (uint256); + + /// @notice Represents a staking incentive + /// @param incentiveId The ID of the incentive computed from its parameters + /// @return totalRewardUnclaimed The amount of reward token not yet claimed by users + /// @return totalSecondsClaimedX128 Total liquidity-seconds claimed, represented as a UQ32.128 + /// @return numberOfStakes The count of deposits that are currently staked for the incentive + function incentives(bytes32 incentiveId) + external + view + returns ( + uint256 totalRewardUnclaimed, + uint160 totalSecondsClaimedX128, + uint96 numberOfStakes + ); + + /// @notice Returns information about a deposited NFT + /// @return owner The owner of the deposited NFT + /// @return numberOfStakes Counter of how many incentives for which the liquidity is staked + /// @return tickLower The lower tick of the range + /// @return tickUpper The upper tick of the range + function deposits(uint256 tokenId) + external + view + returns ( + address owner, + uint48 numberOfStakes, + int24 tickLower, + int24 tickUpper + ); + + /// @notice Returns information about a staked liquidity NFT + /// @param tokenId The ID of the staked token + /// @param incentiveId The ID of the incentive for which the token is staked + /// @return secondsPerLiquidityInsideInitialX128 secondsPerLiquidity represented as a UQ32.128 + /// @return liquidity The amount of liquidity in the NFT as of the last time the rewards were computed + function stakes(uint256 tokenId, bytes32 incentiveId) + external + view + returns (uint160 secondsPerLiquidityInsideInitialX128, uint128 liquidity); + + /// @notice Returns amounts of reward tokens owed to a given address according to the last time all stakes were updated + /// @param rewardToken The token for which to check rewards + /// @param owner The owner for which the rewards owed are checked + /// @return rewardsOwed The amount of the reward token claimable by the owner + function rewards(IERC20Minimal rewardToken, address owner) external view returns (uint256 rewardsOwed); + + /// @notice Creates a new liquidity mining incentive program + /// @param key Details of the incentive to create + /// @param reward The amount of reward tokens to be distributed + function createIncentive(IncentiveKey memory key, uint256 reward) external; + + /// @notice Ends an incentive after the incentive end time has passed and all stakes have been withdrawn + /// @param key Details of the incentive to end + /// @return refund The remaining reward tokens when the incentive is ended + function endIncentive(IncentiveKey memory key) external returns (uint256 refund); + + /// @notice Transfers ownership of a deposit from the sender to the given recipient + /// @param tokenId The ID of the token (and the deposit) to transfer + /// @param to The new owner of the deposit + function transferDeposit(uint256 tokenId, address to) external; + + /// @notice Withdraws a Uniswap V3 LP token `tokenId` from this contract to the recipient `to` + /// @param tokenId The unique identifier of an Uniswap V3 LP token + /// @param to The address where the LP token will be sent + /// @param data An optional data array that will be passed along to the `to` address via the NFT safeTransferFrom + function withdrawToken( + uint256 tokenId, + address to, + bytes memory data + ) external; + + /// @notice Stakes a Uniswap V3 LP token + /// @param key The key of the incentive for which to stake the NFT + /// @param tokenId The ID of the token to stake + function stakeToken(IncentiveKey memory key, uint256 tokenId) external; + + /// @notice Unstakes a Uniswap V3 LP token + /// @param key The key of the incentive for which to unstake the NFT + /// @param tokenId The ID of the token to unstake + function unstakeToken(IncentiveKey memory key, uint256 tokenId) external; + + /// @notice Transfers `amountRequested` of accrued `rewardToken` rewards from the contract to the recipient `to` + /// @param rewardToken The token being distributed as a reward + /// @param to The address where claimed rewards will be sent to + /// @param amountRequested The amount of reward tokens to claim. Claims entire reward amount if set to 0. + /// @return reward The amount of reward tokens claimed + function claimReward( + IERC20Minimal rewardToken, + address to, + uint256 amountRequested + ) external returns (uint256 reward); + + /// @notice Calculates the reward amount that will be received for the given stake + /// @param key The key of the incentive + /// @param tokenId The ID of the token + /// @return reward The reward accrued to the NFT for the given incentive thus far + function getRewardInfo(IncentiveKey memory key, uint256 tokenId) + external + returns (uint256 reward, uint160 secondsInsideX128); + + /// @notice Event emitted when a liquidity mining incentive has been created + /// @param rewardToken The token being distributed as a reward + /// @param pool The Uniswap V3 pool + /// @param startTime The time when the incentive program begins + /// @param endTime The time when rewards stop accruing + /// @param refundee The address which receives any remaining reward tokens after the end time + /// @param reward The amount of reward tokens to be distributed + event IncentiveCreated( + IERC20Minimal indexed rewardToken, + IUniswapV3Pool indexed pool, + uint256 startTime, + uint256 endTime, + address refundee, + uint256 reward + ); + + /// @notice Event that can be emitted when a liquidity mining incentive has ended + /// @param incentiveId The incentive which is ending + /// @param refund The amount of reward tokens refunded + event IncentiveEnded(bytes32 indexed incentiveId, uint256 refund); + + /// @notice Emitted when ownership of a deposit changes + /// @param tokenId The ID of the deposit (and token) that is being transferred + /// @param oldOwner The owner before the deposit was transferred + /// @param newOwner The owner after the deposit was transferred + event DepositTransferred(uint256 indexed tokenId, address indexed oldOwner, address indexed newOwner); + + /// @notice Event emitted when a Uniswap V3 LP token has been staked + /// @param tokenId The unique identifier of an Uniswap V3 LP token + /// @param liquidity The amount of liquidity staked + /// @param incentiveId The incentive in which the token is staking + event TokenStaked(uint256 indexed tokenId, bytes32 indexed incentiveId, uint128 liquidity); + + /// @notice Event emitted when a Uniswap V3 LP token has been unstaked + /// @param tokenId The unique identifier of an Uniswap V3 LP token + /// @param incentiveId The incentive in which the token is staking + event TokenUnstaked(uint256 indexed tokenId, bytes32 indexed incentiveId); + + /// @notice Event emitted when a reward token has been claimed + /// @param to The address where claimed rewards were sent to + /// @param reward The amount of reward tokens claimed + event RewardClaimed(address indexed to, uint256 reward); +} + + +// File @openzeppelin/contracts/math/SafeMath.sol@v3.4.2 + +// SPDX-License-Identifier: MIT + +pragma solidity >=0.6.0 <0.8.0; + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { + uint256 c = a + b; + if (c < a) return (false, 0); + return (true, c); + } + + /** + * @dev Returns the substraction of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b > a) return (false, 0); + return (true, a - b); + } + + /** + * @dev Returns the multiplication of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) return (true, 0); + uint256 c = a * b; + if (c / a != b) return (false, 0); + return (true, c); + } + + /** + * @dev Returns the division of two unsigned integers, with a division by zero flag. + * + * _Available since v3.4._ + */ + function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b == 0) return (false, 0); + return (true, a / b); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. + * + * _Available since v3.4._ + */ + function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b == 0) return (false, 0); + return (true, a % b); + } + + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + require(b <= a, "SafeMath: subtraction overflow"); + return a - b; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + if (a == 0) return 0; + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers, reverting on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + require(b > 0, "SafeMath: division by zero"); + return a / b; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * reverting when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + require(b > 0, "SafeMath: modulo by zero"); + return a % b; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {trySub}. + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + return a - b; + } + + /** + * @dev Returns the integer division of two unsigned integers, reverting with custom message on + * division by zero. The result is rounded towards zero. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryDiv}. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b > 0, errorMessage); + return a / b; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * reverting with custom message when dividing by zero. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryMod}. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b > 0, errorMessage); + return a % b; + } +} + + +// File contracts/polygon/common/math.sol + +pragma solidity ^0.7.0; +contract DSMath { + uint constant WAD = 10 ** 18; + uint constant RAY = 10 ** 27; + + function add(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(x, y); + } + + function sub(uint x, uint y) internal virtual pure returns (uint z) { + z = SafeMath.sub(x, y); + } + + function mul(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.mul(x, y); + } + + function div(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.div(x, y); + } + + function wmul(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, y), WAD / 2) / WAD; + } + + function wdiv(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, WAD), y / 2) / y; + } + + function rdiv(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, RAY), y / 2) / y; + } + + function rmul(uint x, uint y) internal pure returns (uint z) { + z = SafeMath.add(SafeMath.mul(x, y), RAY / 2) / RAY; + } + + function toInt(uint x) internal pure returns (int y) { + y = int(x); + require(y >= 0, "int-overflow"); + } + + function toRad(uint wad) internal pure returns (uint rad) { + rad = mul(wad, 10 ** 27); + } + +} + + +// File contracts/polygon/common/stores.sol + +pragma solidity ^0.7.0; +abstract contract Stores { + + /** + * @dev Return ethereum address + */ + address constant internal maticAddr = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + + /** + * @dev Return Wrapped ETH address + */ + address constant internal wmaticAddr = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270; + + /** + * @dev Return memory variable address + */ + MemoryInterface constant internal instaMemory = MemoryInterface(0x6C7256cf7C003dD85683339F75DdE9971f98f2FD); + + /** + * @dev Get Uint value from InstaMemory Contract. + */ + function getUint(uint getId, uint val) internal returns (uint returnVal) { + returnVal = getId == 0 ? val : instaMemory.getUint(getId); + } + + /** + * @dev Set Uint value in InstaMemory Contract. + */ + function setUint(uint setId, uint val) virtual internal { + if (setId != 0) instaMemory.setUint(setId, val); + } + +} + + +// File contracts/polygon/common/basic.sol + +pragma solidity ^0.7.0; +abstract contract Basic is DSMath, Stores { + + function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = (_amt / 10 ** (18 - _dec)); + } + + function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { + amt = mul(_amt, 10 ** (18 - _dec)); + } + + function getTokenBal(TokenInterface token) internal view returns(uint _amt) { + _amt = address(token) == maticAddr ? address(this).balance : token.balanceOf(address(this)); + } + + function getTokensDec(TokenInterface buyAddr, TokenInterface sellAddr) internal view returns(uint buyDec, uint sellDec) { + buyDec = address(buyAddr) == maticAddr ? 18 : buyAddr.decimals(); + sellDec = address(sellAddr) == maticAddr ? 18 : sellAddr.decimals(); + } + + function encodeEvent(string memory eventName, bytes memory eventParam) internal pure returns (bytes memory) { + return abi.encode(eventName, eventParam); + } + + function changeMaticAddress(address buy, address sell) internal pure returns(TokenInterface _buy, TokenInterface _sell){ + _buy = buy == maticAddr ? TokenInterface(wmaticAddr) : TokenInterface(buy); + _sell = sell == maticAddr ? TokenInterface(wmaticAddr) : TokenInterface(sell); + } + + function approve(TokenInterface token, address spender, uint256 amount) internal { + try token.approve(spender, amount) { + + } catch { + token.approve(spender, 0); + token.approve(spender, amount); + } + } + + function convertMaticToWmatic(bool isMatic, TokenInterface token, uint amount) internal { + if(isMatic) token.deposit{value: amount}(); + } + + function convertWmaticToMatic(bool isMatic, TokenInterface token, uint amount) internal { + if(isMatic) { + approve(token, address(token), amount); + token.withdraw(amount); + } + } +} + + +// File @uniswap/v3-core/contracts/libraries/TickMath.sol@v1.0.0 + +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.5.0; + +/// @title Math library for computing sqrt prices from ticks and vice versa +/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports +/// prices between 2**-128 and 2**128 +library TickMath { + /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 + int24 internal constant MIN_TICK = -887272; + /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 + int24 internal constant MAX_TICK = -MIN_TICK; + + /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) + uint160 internal constant MIN_SQRT_RATIO = 4295128739; + /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) + uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; + + /// @notice Calculates sqrt(1.0001^tick) * 2^96 + /// @dev Throws if |tick| > max tick + /// @param tick The input tick for the above formula + /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) + /// at the given tick + function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { + uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); + require(absTick <= uint256(MAX_TICK), 'T'); + + uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; + if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128; + if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; + if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; + if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; + if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; + if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; + if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; + if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; + if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; + if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; + if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; + if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; + if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; + if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; + if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; + if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; + if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; + if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; + if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; + + if (tick > 0) ratio = type(uint256).max / ratio; + + // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. + // we then downcast because we know the result always fits within 160 bits due to our tick input constraint + // we round up in the division so getTickAtSqrtRatio of the output price is always consistent + sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); + } + + /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio + /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may + /// ever return. + /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96 + /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio + function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) { + // second inequality must be < because the price can never reach the price at the max tick + require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R'); + uint256 ratio = uint256(sqrtPriceX96) << 32; + + uint256 r = ratio; + uint256 msb = 0; + + assembly { + let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) + msb := or(msb, f) + r := shr(f, r) + } + assembly { + let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) + msb := or(msb, f) + r := shr(f, r) + } + assembly { + let f := shl(5, gt(r, 0xFFFFFFFF)) + msb := or(msb, f) + r := shr(f, r) + } + assembly { + let f := shl(4, gt(r, 0xFFFF)) + msb := or(msb, f) + r := shr(f, r) + } + assembly { + let f := shl(3, gt(r, 0xFF)) + msb := or(msb, f) + r := shr(f, r) + } + assembly { + let f := shl(2, gt(r, 0xF)) + msb := or(msb, f) + r := shr(f, r) + } + assembly { + let f := shl(1, gt(r, 0x3)) + msb := or(msb, f) + r := shr(f, r) + } + assembly { + let f := gt(r, 0x1) + msb := or(msb, f) + } + + if (msb >= 128) r = ratio >> (msb - 127); + else r = ratio << (127 - msb); + + int256 log_2 = (int256(msb) - 128) << 64; + + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(63, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(62, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(61, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(60, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(59, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(58, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(57, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(56, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(55, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(54, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(53, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(52, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(51, f)) + r := shr(f, r) + } + assembly { + r := shr(127, mul(r, r)) + let f := shr(128, r) + log_2 := or(log_2, shl(50, f)) + } + + int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number + + int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); + int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); + + tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; + } +} + + +// File @openzeppelin/contracts/token/ERC20/IERC20.sol@v3.4.2 + +// SPDX-License-Identifier: MIT + +pragma solidity >=0.6.0 <0.8.0; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); +} + + +// File @uniswap/v3-periphery/contracts/libraries/TransferHelper.sol@v1.3.0 + +pragma solidity >=0.6.0; + +library TransferHelper { + /// @notice Transfers tokens from the targeted address to the given destination + /// @notice Errors with 'STF' if transfer fails + /// @param token The contract address of the token to be transferred + /// @param from The originating address from which the tokens will be transferred + /// @param to The destination address of the transfer + /// @param value The amount to be transferred + function safeTransferFrom( + address token, + address from, + address to, + uint256 value + ) internal { + (bool success, bytes memory data) = + token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); + require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF'); + } + + /// @notice Transfers tokens from msg.sender to a recipient + /// @dev Errors with ST if transfer fails + /// @param token The contract address of the token which will be transferred + /// @param to The recipient of the transfer + /// @param value The value of the transfer + function safeTransfer( + address token, + address to, + uint256 value + ) internal { + (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); + require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST'); + } + + /// @notice Approves the stipulated contract to spend the given allowance in the given token + /// @dev Errors with 'SA' if transfer fails + /// @param token The contract address of the token to be approved + /// @param to The target of the approval + /// @param value The amount of the given token the target will be allowed to spend + function safeApprove( + address token, + address to, + uint256 value + ) internal { + (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); + require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA'); + } + + /// @notice Transfers ETH to the recipient address + /// @dev Fails with `STE` + /// @param to The destination of the transfer + /// @param value The value to be transferred + function safeTransferETH(address to, uint256 value) internal { + (bool success, ) = to.call{value: value}(new bytes(0)); + require(success, 'STE'); + } +} + + +// File contracts/polygon/connectors/uniswap/v3_staker/helpers.sol + +pragma solidity ^0.7.6; +pragma abicoder v2; +abstract contract Helpers is DSMath, Basic { + /** + * @dev uniswap v3 NFT Position Manager & Swap Router + */ + INonfungiblePositionManager constant nftManager = + INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); + IUniswapV3Staker constant staker = + IUniswapV3Staker(0x1f98407aaB862CdDeF78Ed252D6f557aA5b0f00d); + + /** + * @dev Get Last NFT Index + * @param user: User address + */ + function _getLastNftId(address user) + internal + view + returns (uint256 tokenId) + { + uint256 len = nftManager.balanceOf(user); + tokenId = nftManager.tokenOfOwnerByIndex(user, len - 1); + } + + function getPoolAddress(uint256 _tokenId) + internal + view + returns (address pool) + { + (bool success, bytes memory data) = address(nftManager).staticcall( + abi.encodeWithSelector(nftManager.positions.selector, _tokenId) + ); + require(success, "fetching positions failed"); + { + (, , address token0, address token1, uint24 fee, , , ) = abi.decode( + data, + ( + uint96, + address, + address, + address, + uint24, + int24, + int24, + uint128 + ) + ); + + pool = PoolAddress.computeAddress( + nftManager.factory(), + PoolAddress.PoolKey({token0: token0, token1: token1, fee: fee}) + ); + } + } + + function _stake( + uint256 _tokenId, + IUniswapV3Staker.IncentiveKey memory _incentiveId + ) internal { + staker.stakeToken(_incentiveId, _tokenId); + } + + function _unstake( + IUniswapV3Staker.IncentiveKey memory _key, + uint256 _tokenId + ) internal { + staker.unstakeToken(_key, _tokenId); + } + + function _claimRewards( + IERC20Minimal _rewardToken, + address _to, + uint256 _amountRequested + ) internal returns (uint256 rewards) { + rewards = staker.claimReward(_rewardToken, _to, _amountRequested); + } +} + + +// File contracts/polygon/connectors/uniswap/v3_staker/events.sol + +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit(uint256 tokenId); + + event LogDepositAndStake(uint256 tokenId, bytes32 incentiveId); + + event LogWithdraw(uint256 indexed tokenId); + + event LogDepositTransfer(uint256 indexed tokenId, address to); + + event LogStake(uint256 indexed tokenId, bytes32 incentiveId); + + event LogUnstake(uint256 indexed tokenId, bytes32 incentiveId); + + event LogRewardClaimed( + address indexed rewardToken, + uint256 amount + ); + + event LogIncentiveCreated( + bytes32 incentiveId, + address poolAddr, + address refundee, + uint256 startTime, + uint256 endTime, + uint256 reward + ); +} + + +// File contracts/polygon/connectors/uniswap/v3_staker/main.sol + +pragma solidity ^0.7.6; +pragma abicoder v2; + +/** + * @title Uniswap v3. + * @dev Decentralized Exchange. + */ +abstract contract UniswapResolver is Helpers, Events { + /** + * @dev Deposit NFT token + * @notice Transfer deposited NFT token + * @param _tokenId NFT LP Token ID + */ + function deposit(uint256 _tokenId) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + if (_tokenId == 0) _tokenId = _getLastNftId(address(this)); + nftManager.safeTransferFrom( + address(this), + address(staker), + _tokenId, + "" + ); + + _eventName = "LogDeposit(uint256)"; + _eventParam = abi.encode(_tokenId); + } + + /** + * @dev Deposit and Stake NFT token + * @notice To Deposit and Stake NFT for Staking + * @param _rewardToken _rewardToken address + * @param _startTime stake start time + * @param _endTime stake end time + * @param _refundee refundee address + * @param _tokenId NFT LP token id + */ + function depositAndStake ( + address _rewardToken, + uint256 _startTime, + uint256 _endTime, + address _refundee, + uint256 _tokenId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + if (_tokenId == 0) _tokenId = _getLastNftId(address(this)); + nftManager.safeTransferFrom( + address(this), + address(staker), + _tokenId, + "" + ); + + address poolAddr = getPoolAddress(_tokenId); + + IUniswapV3Pool pool = IUniswapV3Pool(poolAddr); + IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker + .IncentiveKey( + IERC20Minimal(_rewardToken), + pool, + _startTime, + _endTime, + _refundee + ); + _stake(_tokenId, _key); + + _eventName = "LogDepositAndStake(uint256,bytes32)"; + _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key))); + } + + /** + * @dev Deposit Transfer + * @notice Transfer deposited NFT token + * @param _tokenId NFT LP Token ID + * @param _to address to transfer + */ + function transferDeposit(uint256 _tokenId, address _to) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + staker.transferDeposit(_tokenId, _to); + + _eventName = "LogDepositTransfer(uint256,address)"; + _eventParam = abi.encode(_tokenId, _to); + } + + /** + * @dev Withdraw NFT LP token + * @notice Withdraw NFT LP token from staking pool + * @param _tokenId NFT LP Token ID + */ + function withdraw(uint256 _tokenId) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + staker.withdrawToken(_tokenId, address(this), ""); + + _eventName = "LogWithdraw(uint256)"; + _eventParam = abi.encode(_tokenId); + } + + /** + * @dev Stake NFT LP token + * @notice Stake NFT LP Position + * @param _rewardToken _rewardToken address + * @param _startTime stake start time + * @param _endTime stake end time + * @param _refundee refundee address + * @param _tokenId NFT LP token id + */ + function stake ( + address _rewardToken, + uint256 _startTime, + uint256 _endTime, + address _refundee, + uint256 _tokenId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + address poolAddr = getPoolAddress(_tokenId); + + IUniswapV3Pool pool = IUniswapV3Pool(poolAddr); + IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker + .IncentiveKey( + IERC20Minimal(_rewardToken), + pool, + _startTime, + _endTime, + _refundee + ); + _stake(_tokenId, _key); + + _eventName = "LogStake(uint256,bytes32)"; + _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key))); + } + + /** + * @dev Unstake NFT LP token + * @notice Unstake NFT LP Position + * @param _rewardToken _rewardToken address + * @param _startTime stake start time + * @param _endTime stake end time + * @param _refundee refundee address + * @param _tokenId NFT LP token id + */ + function unstake( + address _rewardToken, + uint256 _startTime, + uint256 _endTime, + address _refundee, + uint256 _tokenId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + address poolAddr = getPoolAddress(_tokenId); + + IUniswapV3Pool pool = IUniswapV3Pool(poolAddr); + IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker + .IncentiveKey( + IERC20Minimal(_rewardToken), + pool, + _startTime, + _endTime, + _refundee + ); + _unstake(_key, _tokenId); + _eventName = "LogUnstake(uint256,bytes32)"; + _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key))); + } + + /** + * @dev Claim rewards + * @notice Claim rewards + * @param _rewardToken _rewardToken address + * @param _amount requested amount + */ + function claimRewards( + address _rewardToken, + uint256 _amount + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 rewards = _claimRewards( + IERC20Minimal(_rewardToken), + address(this), + _amount + ); + + _eventName = "LogRewardClaimed(address,uint256)"; + _eventParam = abi.encode(_rewardToken, rewards); + } + + /** + * @dev Create incentive + * @notice Create incentive + * @param _rewardToken _rewardToken address + * @param _length incentive length + * @param _refundee refundee address + * @param _poolAddr Uniswap V3 Pool address + * @param _reward reward amount + */ + function createIncentive( + address _rewardToken, + uint256 _length, + address _refundee, + address _poolAddr, + uint256 _reward + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + IUniswapV3Pool pool = IUniswapV3Pool(_poolAddr); + uint256 _startTime = block.timestamp; + uint256 _endTime = _startTime + _length; + IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker + .IncentiveKey( + IERC20Minimal(_rewardToken), + pool, + _startTime, + _endTime, + _refundee + ); + if (_rewardToken != maticAddr) { + IERC20Minimal(_rewardToken).approve(address(staker), _reward); + } + staker.createIncentive(_key, _reward); + + _eventName = "LogIncentiveCreated(bytes32,address,address,uint256,uint256,uint256)"; + _eventParam = abi.encode(keccak256(abi.encode(_key)), _poolAddr, _refundee, _startTime, _endTime, _reward); + } +} + +contract ConnectV2UniswapV3StakerPolygon is UniswapResolver { + string public constant name = "Uniswap-V3-Staker-v1.1"; +} diff --git a/contracts/arbitrum/connectors/1inch/events.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/events.sol similarity index 100% rename from contracts/arbitrum/connectors/1inch/events.sol rename to contracts/arbitrum/connectors/1inch/1inch-v3/events.sol diff --git a/contracts/arbitrum/connectors/1inch/helpers.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/helpers.sol similarity index 100% rename from contracts/arbitrum/connectors/1inch/helpers.sol rename to contracts/arbitrum/connectors/1inch/1inch-v3/helpers.sol diff --git a/contracts/arbitrum/connectors/1inch/interface.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/interface.sol similarity index 100% rename from contracts/arbitrum/connectors/1inch/interface.sol rename to contracts/arbitrum/connectors/1inch/1inch-v3/interface.sol diff --git a/contracts/arbitrum/connectors/1inch/main.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/main.sol similarity index 100% rename from contracts/arbitrum/connectors/1inch/main.sol rename to contracts/arbitrum/connectors/1inch/1inch-v3/main.sol diff --git a/contracts/mainnet/connectors/1inch/events.sol b/contracts/arbitrum/connectors/1inch/1inch-v4/events.sol similarity index 100% rename from contracts/mainnet/connectors/1inch/events.sol rename to contracts/arbitrum/connectors/1inch/1inch-v4/events.sol diff --git a/contracts/arbitrum/connectors/1inch/1inch-v4/helpers.sol b/contracts/arbitrum/connectors/1inch/1inch-v4/helpers.sol new file mode 100644 index 00000000..41c55315 --- /dev/null +++ b/contracts/arbitrum/connectors/1inch/1inch-v4/helpers.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; + + +abstract contract Helpers is DSMath, Basic { + /** + * @dev 1Inch Address + */ +address internal constant oneInchAddr = 0x1111111254fb6c44bAC0beD2854e76F90643097d; +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/1inch/interface.sol b/contracts/arbitrum/connectors/1inch/1inch-v4/interface.sol similarity index 100% rename from contracts/mainnet/connectors/1inch/interface.sol rename to contracts/arbitrum/connectors/1inch/1inch-v4/interface.sol diff --git a/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol b/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol new file mode 100644 index 00000000..84c82ded --- /dev/null +++ b/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol @@ -0,0 +1,112 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title 1Inch. + * @dev On-chain DEX Aggregator. + */ + +// import files from common directory +import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { OneInchInterace, OneInchData } from "./interface.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract OneInchResolver is Helpers, Events { + + + /** + * @dev 1inch API swap handler + * @param oneInchData - contains data returned from 1inch API. Struct defined in interfaces.sol + * @param ethAmt - Eth to swap for .value() + */ + function oneInchSwap( + OneInchData memory oneInchData, + uint ethAmt + ) internal returns (uint buyAmt) { + TokenInterface buyToken = oneInchData.buyToken; + (uint _buyDec, uint _sellDec) = getTokensDec(buyToken, oneInchData.sellToken); + uint _sellAmt18 = convertTo18(_sellDec, oneInchData._sellAmt); + uint _slippageAmt = convert18ToDec(_buyDec, wmul(oneInchData.unitAmt, _sellAmt18)); + + uint initalBal = getTokenBal(buyToken); + + // solium-disable-next-line security/no-call-value + (bool success, ) = oneInchAddr.call{value: ethAmt}(oneInchData.callData); + if (!success) revert("1Inch-swap-failed"); + + uint finalBal = getTokenBal(buyToken); + + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } + +} + +abstract contract OneInchResolverHelpers is OneInchResolver { + + /** + * @dev Gets the swapping data from 1inch's API. + * @param oneInchData Struct with multiple swap data defined in interfaces.sol + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function _sell( + OneInchData memory oneInchData, + uint setId + ) internal returns (OneInchData memory) { + TokenInterface _sellAddr = oneInchData.sellToken; + + uint ethAmt; + if (address(_sellAddr) == ethAddr) { + ethAmt = oneInchData._sellAmt; + } else { + approve(TokenInterface(_sellAddr), oneInchAddr, oneInchData._sellAmt); + } + + oneInchData._buyAmt = oneInchSwap(oneInchData, ethAmt); + setUint(setId, oneInchData._buyAmt); + + return oneInchData; + } +} + +abstract contract OneInch is OneInchResolverHelpers { + /** + * @dev Sell ETH/ERC20_Token using 1Inch. + * @notice Swap tokens from exchanges like kyber, 0x etc, with calculation done off-chain. + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmt The amount of buyAmt/sellAmt with slippage. + * @param callData Data from 1inch API. + * @param setId ID stores the amount of token brought. + */ + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + bytes calldata callData, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + OneInchData memory oneInchData = OneInchData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + unitAmt: unitAmt, + callData: callData, + _sellAmt: sellAmt, + _buyAmt: 0 + }); + + oneInchData = _sell(oneInchData, setId); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, oneInchData._buyAmt, oneInchData._sellAmt, 0, setId); + } +} + +contract ConnectV2OneInchArbitrum is OneInch { + string public name = "1Inch-v4-v1.0"; +} diff --git a/contracts/polygon/connectors/1inch/events.sol b/contracts/mainnet/connectors/1inch/1inch-v3/events.sol similarity index 100% rename from contracts/polygon/connectors/1inch/events.sol rename to contracts/mainnet/connectors/1inch/1inch-v3/events.sol diff --git a/contracts/mainnet/connectors/1inch/helpers.sol b/contracts/mainnet/connectors/1inch/1inch-v3/helpers.sol similarity index 100% rename from contracts/mainnet/connectors/1inch/helpers.sol rename to contracts/mainnet/connectors/1inch/1inch-v3/helpers.sol diff --git a/contracts/polygon/connectors/1inch/interface.sol b/contracts/mainnet/connectors/1inch/1inch-v3/interface.sol similarity index 100% rename from contracts/polygon/connectors/1inch/interface.sol rename to contracts/mainnet/connectors/1inch/1inch-v3/interface.sol diff --git a/contracts/mainnet/connectors/1inch/main.sol b/contracts/mainnet/connectors/1inch/1inch-v3/main.sol similarity index 100% rename from contracts/mainnet/connectors/1inch/main.sol rename to contracts/mainnet/connectors/1inch/1inch-v3/main.sol diff --git a/contracts/mainnet/connectors/1inch/1inch-v4/events.sol b/contracts/mainnet/connectors/1inch/1inch-v4/events.sol new file mode 100644 index 00000000..bec3b27a --- /dev/null +++ b/contracts/mainnet/connectors/1inch/1inch-v4/events.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/1inch/1inch-v4/helpers.sol b/contracts/mainnet/connectors/1inch/1inch-v4/helpers.sol new file mode 100644 index 00000000..8582731c --- /dev/null +++ b/contracts/mainnet/connectors/1inch/1inch-v4/helpers.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; + + +abstract contract Helpers is DSMath, Basic { + /** + * @dev 1Inch Address + */ + address internal constant oneInchAddr = 0x1111111254fb6c44bAC0beD2854e76F90643097d; +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/1inch/1inch-v4/interface.sol b/contracts/mainnet/connectors/1inch/1inch-v4/interface.sol new file mode 100644 index 00000000..f35b9277 --- /dev/null +++ b/contracts/mainnet/connectors/1inch/1inch-v4/interface.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; + +interface OneInchInterace { + function swap( + TokenInterface fromToken, + TokenInterface toToken, + uint256 fromTokenAmount, + uint256 minReturnAmount, + uint256 guaranteedAmount, + address payable referrer, + address[] calldata callAddresses, + bytes calldata callDataConcat, + uint256[] calldata starts, + uint256[] calldata gasLimitsAndValues + ) + external + payable + returns (uint256 returnAmount); +} + +struct OneInchData { + TokenInterface sellToken; + TokenInterface buyToken; + uint _sellAmt; + uint _buyAmt; + uint unitAmt; + bytes callData; +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/1inch/1inch-v4/main.sol b/contracts/mainnet/connectors/1inch/1inch-v4/main.sol new file mode 100644 index 00000000..9d67847c --- /dev/null +++ b/contracts/mainnet/connectors/1inch/1inch-v4/main.sol @@ -0,0 +1,111 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title 1Inch. + * @dev On-chain DEX Aggregator. + */ + +// import files from common directory +import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { OneInchInterace, OneInchData } from "./interface.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract OneInchResolver is Helpers, Events { + /** + * @dev 1inch API swap handler + * @param oneInchData - contains data returned from 1inch API. Struct defined in interfaces.sol + * @param ethAmt - Eth to swap for .value() + */ + function oneInchSwap( + OneInchData memory oneInchData, + uint ethAmt + ) internal returns (uint buyAmt) { + TokenInterface buyToken = oneInchData.buyToken; + (uint _buyDec, uint _sellDec) = getTokensDec(buyToken, oneInchData.sellToken); + uint _sellAmt18 = convertTo18(_sellDec, oneInchData._sellAmt); + uint _slippageAmt = convert18ToDec(_buyDec, wmul(oneInchData.unitAmt, _sellAmt18)); + + uint initalBal = getTokenBal(buyToken); + + // solium-disable-next-line security/no-call-value + (bool success, ) = oneInchAddr.call{value: ethAmt}(oneInchData.callData); + if (!success) revert("1Inch-swap-failed"); + + uint finalBal = getTokenBal(buyToken); + + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } + +} + +abstract contract OneInchResolverHelpers is OneInchResolver { + + /** + * @dev Gets the swapping data from 1inch's API. + * @param oneInchData Struct with multiple swap data defined in interfaces.sol + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function _sell( + OneInchData memory oneInchData, + uint setId + ) internal returns (OneInchData memory) { + TokenInterface _sellAddr = oneInchData.sellToken; + + uint ethAmt; + if (address(_sellAddr) == ethAddr) { + ethAmt = oneInchData._sellAmt; + } else { + approve(TokenInterface(_sellAddr), oneInchAddr, oneInchData._sellAmt); + } + + oneInchData._buyAmt = oneInchSwap(oneInchData, ethAmt); + setUint(setId, oneInchData._buyAmt); + + return oneInchData; + + } +} + +abstract contract OneInch is OneInchResolverHelpers { + /** + * @dev Sell ETH/ERC20_Token using 1Inch. + * @notice Swap tokens from exchanges like kyber, 0x etc, with calculation done off-chain. + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmt The amount of buyAmt/sellAmt with slippage. + * @param callData Data from 1inch API. + * @param setId ID stores the amount of token brought. + */ + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + bytes calldata callData, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + OneInchData memory oneInchData = OneInchData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + unitAmt: unitAmt, + callData: callData, + _sellAmt: sellAmt, + _buyAmt: 0 + }); + + oneInchData = _sell(oneInchData, setId); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, oneInchData._buyAmt, oneInchData._sellAmt, 0, setId); + } +} + +contract ConnectV2OneInch is OneInch { + string public name = "1Inch-v4-v1.0"; +} diff --git a/contracts/polygon/connectors/1inch/1inch-v3/events.sol b/contracts/polygon/connectors/1inch/1inch-v3/events.sol new file mode 100644 index 00000000..bec3b27a --- /dev/null +++ b/contracts/polygon/connectors/1inch/1inch-v3/events.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} \ No newline at end of file diff --git a/contracts/polygon/connectors/1inch/helpers.sol b/contracts/polygon/connectors/1inch/1inch-v3/helpers.sol similarity index 100% rename from contracts/polygon/connectors/1inch/helpers.sol rename to contracts/polygon/connectors/1inch/1inch-v3/helpers.sol diff --git a/contracts/polygon/connectors/1inch/1inch-v3/interface.sol b/contracts/polygon/connectors/1inch/1inch-v3/interface.sol new file mode 100644 index 00000000..f35b9277 --- /dev/null +++ b/contracts/polygon/connectors/1inch/1inch-v3/interface.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; + +interface OneInchInterace { + function swap( + TokenInterface fromToken, + TokenInterface toToken, + uint256 fromTokenAmount, + uint256 minReturnAmount, + uint256 guaranteedAmount, + address payable referrer, + address[] calldata callAddresses, + bytes calldata callDataConcat, + uint256[] calldata starts, + uint256[] calldata gasLimitsAndValues + ) + external + payable + returns (uint256 returnAmount); +} + +struct OneInchData { + TokenInterface sellToken; + TokenInterface buyToken; + uint _sellAmt; + uint _buyAmt; + uint unitAmt; + bytes callData; +} \ No newline at end of file diff --git a/contracts/polygon/connectors/1inch/main.sol b/contracts/polygon/connectors/1inch/1inch-v3/main.sol similarity index 100% rename from contracts/polygon/connectors/1inch/main.sol rename to contracts/polygon/connectors/1inch/1inch-v3/main.sol diff --git a/contracts/polygon/connectors/1inch/1inch-v4/events.sol b/contracts/polygon/connectors/1inch/1inch-v4/events.sol new file mode 100644 index 00000000..bec3b27a --- /dev/null +++ b/contracts/polygon/connectors/1inch/1inch-v4/events.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogSell( + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} \ No newline at end of file diff --git a/contracts/polygon/connectors/1inch/1inch-v4/helpers.sol b/contracts/polygon/connectors/1inch/1inch-v4/helpers.sol new file mode 100644 index 00000000..8582731c --- /dev/null +++ b/contracts/polygon/connectors/1inch/1inch-v4/helpers.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; + + +abstract contract Helpers is DSMath, Basic { + /** + * @dev 1Inch Address + */ + address internal constant oneInchAddr = 0x1111111254fb6c44bAC0beD2854e76F90643097d; +} \ No newline at end of file diff --git a/contracts/polygon/connectors/1inch/1inch-v4/interface.sol b/contracts/polygon/connectors/1inch/1inch-v4/interface.sol new file mode 100644 index 00000000..f35b9277 --- /dev/null +++ b/contracts/polygon/connectors/1inch/1inch-v4/interface.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../common/interfaces.sol"; + +interface OneInchInterace { + function swap( + TokenInterface fromToken, + TokenInterface toToken, + uint256 fromTokenAmount, + uint256 minReturnAmount, + uint256 guaranteedAmount, + address payable referrer, + address[] calldata callAddresses, + bytes calldata callDataConcat, + uint256[] calldata starts, + uint256[] calldata gasLimitsAndValues + ) + external + payable + returns (uint256 returnAmount); +} + +struct OneInchData { + TokenInterface sellToken; + TokenInterface buyToken; + uint _sellAmt; + uint _buyAmt; + uint unitAmt; + bytes callData; +} \ No newline at end of file diff --git a/contracts/polygon/connectors/1inch/1inch-v4/main.sol b/contracts/polygon/connectors/1inch/1inch-v4/main.sol new file mode 100644 index 00000000..c4b35c79 --- /dev/null +++ b/contracts/polygon/connectors/1inch/1inch-v4/main.sol @@ -0,0 +1,115 @@ +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title 1Inch. + * @dev On-chain DEX Aggregator. + */ + +// import files from common directory +import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { OneInchInterace, OneInchData } from "./interface.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract OneInchResolver is Helpers, Events { + + + /** + * @dev 1inch API swap handler + * @param oneInchData - contains data returned from 1inch API. Struct defined in interfaces.sol + * @param ethAmt - Eth to swap for .value() + */ + function oneInchSwap( + OneInchData memory oneInchData, + uint ethAmt + ) internal returns (uint buyAmt) { + TokenInterface buyToken = oneInchData.buyToken; + (uint _buyDec, uint _sellDec) = getTokensDec(buyToken, oneInchData.sellToken); + uint _sellAmt18 = convertTo18(_sellDec, oneInchData._sellAmt); + uint _slippageAmt = convert18ToDec(_buyDec, wmul(oneInchData.unitAmt, _sellAmt18)); + + uint initalBal = getTokenBal(buyToken); + + // solium-disable-next-line security/no-call-value + (bool success, ) = oneInchAddr.call{value: ethAmt}(oneInchData.callData); + if (!success) revert("1Inch-swap-failed"); + + uint finalBal = getTokenBal(buyToken); + + buyAmt = sub(finalBal, initalBal); + + require(_slippageAmt <= buyAmt, "Too much slippage"); + } + +} + +abstract contract OneInchResolverHelpers is OneInchResolver { + + /** + * @dev Gets the swapping data from 1inch's API. + * @param oneInchData Struct with multiple swap data defined in interfaces.sol + * @param setId Set token amount at this ID in `InstaMemory` Contract. + */ + function _sell( + OneInchData memory oneInchData, + uint setId + ) internal returns (OneInchData memory) { + TokenInterface _sellAddr = oneInchData.sellToken; + + uint ethAmt; + if (address(_sellAddr) == maticAddr) { + ethAmt = oneInchData._sellAmt; + } else { + approve(TokenInterface(_sellAddr), oneInchAddr, oneInchData._sellAmt); + } + + + oneInchData._buyAmt = oneInchSwap(oneInchData, ethAmt); + setUint(setId, oneInchData._buyAmt); + + return oneInchData; + + + } +} + +abstract contract OneInch is OneInchResolverHelpers { + /** + * @dev Sell ETH/ERC20_Token using 1Inch. + * @notice Swap tokens from exchanges like kyber, 0x etc, with calculation done off-chain. + * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmt The amount of buyAmt/sellAmt with slippage. + * @param callData Data from 1inch API. + * @param setId ID stores the amount of token brought. + */ + function sell( + address buyAddr, + address sellAddr, + uint sellAmt, + uint unitAmt, + bytes calldata callData, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + OneInchData memory oneInchData = OneInchData({ + buyToken: TokenInterface(buyAddr), + sellToken: TokenInterface(sellAddr), + unitAmt: unitAmt, + callData: callData, + _sellAmt: sellAmt, + _buyAmt: 0 + }); + + oneInchData = _sell(oneInchData, setId); + + _eventName = "LogSell(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(buyAddr, sellAddr, oneInchData._buyAmt, oneInchData._sellAmt, 0, setId); + } +} + +contract ConnectV2OneInchPolygon is OneInch { + string public name = "1Inch-v4-v1"; +} diff --git a/hardhat.config.ts b/hardhat.config.ts index a8e617e1..bbb390a9 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -50,7 +50,7 @@ function createConfig(network: string) { return { url: getNetworkUrl(network), accounts: !!PRIVATE_KEY ? [`0x${PRIVATE_KEY}`] : { mnemonic }, - gasPrice: utils.parseUnits(networkGasPriceConfig[network], "gwei").toNumber(), + gasPrice:100000000000 }; } From 25519fc9c4f6a68f4da732043178ec84c3cd36c6 Mon Sep 17 00:00:00 2001 From: bhavik Date: Thu, 23 Dec 2021 00:40:36 +0530 Subject: [PATCH 26/31] changed hardhat.config.ts --- hardhat.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index bbb390a9..6158e1b5 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -118,8 +118,8 @@ const config: HardhatUserConfig = { sources: "./contracts", tests: "./test", }, - etherscan: { - apiKey: getScanApiKey(String(process.env.networkType)), + etherscan: { + apiKey: getScanApiKey(getNetworkUrl(String(process.env.networkType))), }, typechain: { outDir: "typechain", From 24e92595cecf644655536eb843608e942d54f0e2 Mon Sep 17 00:00:00 2001 From: bhavik Date: Thu, 23 Dec 2021 00:43:39 +0530 Subject: [PATCH 27/31] removed gasPrice in hardhat-config --- hardhat.config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 6158e1b5..8c10d28f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -50,7 +50,6 @@ function createConfig(network: string) { return { url: getNetworkUrl(network), accounts: !!PRIVATE_KEY ? [`0x${PRIVATE_KEY}`] : { mnemonic }, - gasPrice:100000000000 }; } From 610512ab3737e47b7444dc9ffc3bbe39ffca1c7b Mon Sep 17 00:00:00 2001 From: bhavik Date: Thu, 23 Dec 2021 00:53:30 +0530 Subject: [PATCH 28/31] removed connector.sol --- connector.sol | 2492 ------------------------------------------------- 1 file changed, 2492 deletions(-) delete mode 100644 connector.sol diff --git a/connector.sol b/connector.sol deleted file mode 100644 index bfcf70f8..00000000 --- a/connector.sol +++ /dev/null @@ -1,2492 +0,0 @@ -// Sources flattened with hardhat v2.7.0 https://hardhat.org - -// File contracts/polygon/common/interfaces.sol - -pragma solidity ^0.7.0; - -interface TokenInterface { - function approve(address, uint256) external; - function transfer(address, uint) external; - function transferFrom(address, address, uint) external; - function deposit() external payable; - function withdraw(uint) external; - function balanceOf(address) external view returns (uint); - function decimals() external view returns (uint); -} - -interface MemoryInterface { - function getUint(uint id) external returns (uint num); - function setUint(uint id, uint val) external; -} - -interface InstaMapping { - function cTokenMapping(address) external view returns (address); - function gemJoinMapping(bytes32) external view returns (address); -} - -interface AccountInterface { - function enable(address) external; - function disable(address) external; - function isAuth(address) external view returns (bool); -} - - -// File @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol@v3.4.2 - -pragma solidity >=0.6.0 <0.8.0; - -/** - * @title ERC721 token receiver interface - * @dev Interface for any contract that wants to support safeTransfers - * from ERC721 asset contracts. - */ -interface IERC721Receiver { - /** - * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} - * by `operator` from `from`, this function is called. - * - * It must return its Solidity selector to confirm the token transfer. - * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. - * - * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. - */ - function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); -} - - -// File @uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title The interface for the Uniswap V3 Factory -/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees -interface IUniswapV3Factory { - /// @notice Emitted when the owner of the factory is changed - /// @param oldOwner The owner before the owner was changed - /// @param newOwner The owner after the owner was changed - event OwnerChanged(address indexed oldOwner, address indexed newOwner); - - /// @notice Emitted when a pool is created - /// @param token0 The first token of the pool by address sort order - /// @param token1 The second token of the pool by address sort order - /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip - /// @param tickSpacing The minimum number of ticks between initialized ticks - /// @param pool The address of the created pool - event PoolCreated( - address indexed token0, - address indexed token1, - uint24 indexed fee, - int24 tickSpacing, - address pool - ); - - /// @notice Emitted when a new fee amount is enabled for pool creation via the factory - /// @param fee The enabled fee, denominated in hundredths of a bip - /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee - event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing); - - /// @notice Returns the current owner of the factory - /// @dev Can be changed by the current owner via setOwner - /// @return The address of the factory owner - function owner() external view returns (address); - - /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled - /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context - /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee - /// @return The tick spacing - function feeAmountTickSpacing(uint24 fee) external view returns (int24); - - /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist - /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order - /// @param tokenA The contract address of either token0 or token1 - /// @param tokenB The contract address of the other token - /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip - /// @return pool The pool address - function getPool( - address tokenA, - address tokenB, - uint24 fee - ) external view returns (address pool); - - /// @notice Creates a pool for the given two tokens and fee - /// @param tokenA One of the two tokens in the desired pool - /// @param tokenB The other of the two tokens in the desired pool - /// @param fee The desired fee for the pool - /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved - /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments - /// are invalid. - /// @return pool The address of the newly created pool - function createPool( - address tokenA, - address tokenB, - uint24 fee - ) external returns (address pool); - - /// @notice Updates the owner of the factory - /// @dev Must be called by the current owner - /// @param _owner The new owner of the factory - function setOwner(address _owner) external; - - /// @notice Enables a fee amount with the given tickSpacing - /// @dev Fee amounts may never be removed once enabled - /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6) - /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount - function enableFeeAmount(uint24 fee, int24 tickSpacing) external; -} - - -// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title Pool state that never changes -/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values -interface IUniswapV3PoolImmutables { - /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface - /// @return The contract address - function factory() external view returns (address); - - /// @notice The first of the two tokens of the pool, sorted by address - /// @return The token contract address - function token0() external view returns (address); - - /// @notice The second of the two tokens of the pool, sorted by address - /// @return The token contract address - function token1() external view returns (address); - - /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6 - /// @return The fee - function fee() external view returns (uint24); - - /// @notice The pool tick spacing - /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive - /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ... - /// This value is an int24 to avoid casting even though it is always positive. - /// @return The tick spacing - function tickSpacing() external view returns (int24); - - /// @notice The maximum amount of position liquidity that can use any tick in the range - /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and - /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool - /// @return The max amount of liquidity per tick - function maxLiquidityPerTick() external view returns (uint128); -} - - -// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title Pool state that can change -/// @notice These methods compose the pool's state, and can change with any frequency including multiple times -/// per transaction -interface IUniswapV3PoolState { - /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas - /// when accessed externally. - /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value - /// tick The current tick of the pool, i.e. according to the last tick transition that was run. - /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick - /// boundary. - /// observationIndex The index of the last oracle observation that was written, - /// observationCardinality The current maximum number of observations stored in the pool, - /// observationCardinalityNext The next maximum number of observations, to be updated when the observation. - /// feeProtocol The protocol fee for both tokens of the pool. - /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0 - /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee. - /// unlocked Whether the pool is currently locked to reentrancy - function slot0() - external - view - returns ( - uint160 sqrtPriceX96, - int24 tick, - uint16 observationIndex, - uint16 observationCardinality, - uint16 observationCardinalityNext, - uint8 feeProtocol, - bool unlocked - ); - - /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool - /// @dev This value can overflow the uint256 - function feeGrowthGlobal0X128() external view returns (uint256); - - /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool - /// @dev This value can overflow the uint256 - function feeGrowthGlobal1X128() external view returns (uint256); - - /// @notice The amounts of token0 and token1 that are owed to the protocol - /// @dev Protocol fees will never exceed uint128 max in either token - function protocolFees() external view returns (uint128 token0, uint128 token1); - - /// @notice The currently in range liquidity available to the pool - /// @dev This value has no relationship to the total liquidity across all ticks - function liquidity() external view returns (uint128); - - /// @notice Look up information about a specific tick in the pool - /// @param tick The tick to look up - /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or - /// tick upper, - /// liquidityNet how much liquidity changes when the pool price crosses the tick, - /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0, - /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1, - /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick - /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick, - /// secondsOutside the seconds spent on the other side of the tick from the current tick, - /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false. - /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0. - /// In addition, these values are only relative and must be used only in comparison to previous snapshots for - /// a specific position. - function ticks(int24 tick) - external - view - returns ( - uint128 liquidityGross, - int128 liquidityNet, - uint256 feeGrowthOutside0X128, - uint256 feeGrowthOutside1X128, - int56 tickCumulativeOutside, - uint160 secondsPerLiquidityOutsideX128, - uint32 secondsOutside, - bool initialized - ); - - /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information - function tickBitmap(int16 wordPosition) external view returns (uint256); - - /// @notice Returns the information about a position by the position's key - /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper - /// @return _liquidity The amount of liquidity in the position, - /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke, - /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke, - /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke, - /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke - function positions(bytes32 key) - external - view - returns ( - uint128 _liquidity, - uint256 feeGrowthInside0LastX128, - uint256 feeGrowthInside1LastX128, - uint128 tokensOwed0, - uint128 tokensOwed1 - ); - - /// @notice Returns data about a specific observation index - /// @param index The element of the observations array to fetch - /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time - /// ago, rather than at a specific index in the array. - /// @return blockTimestamp The timestamp of the observation, - /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp, - /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp, - /// Returns initialized whether the observation has been initialized and the values are safe to use - function observations(uint256 index) - external - view - returns ( - uint32 blockTimestamp, - int56 tickCumulative, - uint160 secondsPerLiquidityCumulativeX128, - bool initialized - ); -} - - -// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title Pool state that is not stored -/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the -/// blockchain. The functions here may have variable gas costs. -interface IUniswapV3PoolDerivedState { - /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp - /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing - /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick, - /// you must call it with secondsAgos = [3600, 0]. - /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in - /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio. - /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned - /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp - /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block - /// timestamp - function observe(uint32[] calldata secondsAgos) - external - view - returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s); - - /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range - /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed. - /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first - /// snapshot is taken and the second snapshot is taken. - /// @param tickLower The lower tick of the range - /// @param tickUpper The upper tick of the range - /// @return tickCumulativeInside The snapshot of the tick accumulator for the range - /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range - /// @return secondsInside The snapshot of seconds per liquidity for the range - function snapshotCumulativesInside(int24 tickLower, int24 tickUpper) - external - view - returns ( - int56 tickCumulativeInside, - uint160 secondsPerLiquidityInsideX128, - uint32 secondsInside - ); -} - - -// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title Permissionless pool actions -/// @notice Contains pool methods that can be called by anyone -interface IUniswapV3PoolActions { - /// @notice Sets the initial price for the pool - /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value - /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96 - function initialize(uint160 sqrtPriceX96) external; - - /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position - /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback - /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends - /// on tickLower, tickUpper, the amount of liquidity, and the current price. - /// @param recipient The address for which the liquidity will be created - /// @param tickLower The lower tick of the position in which to add liquidity - /// @param tickUpper The upper tick of the position in which to add liquidity - /// @param amount The amount of liquidity to mint - /// @param data Any data that should be passed through to the callback - /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback - /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback - function mint( - address recipient, - int24 tickLower, - int24 tickUpper, - uint128 amount, - bytes calldata data - ) external returns (uint256 amount0, uint256 amount1); - - /// @notice Collects tokens owed to a position - /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity. - /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or - /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the - /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity. - /// @param recipient The address which should receive the fees collected - /// @param tickLower The lower tick of the position for which to collect fees - /// @param tickUpper The upper tick of the position for which to collect fees - /// @param amount0Requested How much token0 should be withdrawn from the fees owed - /// @param amount1Requested How much token1 should be withdrawn from the fees owed - /// @return amount0 The amount of fees collected in token0 - /// @return amount1 The amount of fees collected in token1 - function collect( - address recipient, - int24 tickLower, - int24 tickUpper, - uint128 amount0Requested, - uint128 amount1Requested - ) external returns (uint128 amount0, uint128 amount1); - - /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position - /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0 - /// @dev Fees must be collected separately via a call to #collect - /// @param tickLower The lower tick of the position for which to burn liquidity - /// @param tickUpper The upper tick of the position for which to burn liquidity - /// @param amount How much liquidity to burn - /// @return amount0 The amount of token0 sent to the recipient - /// @return amount1 The amount of token1 sent to the recipient - function burn( - int24 tickLower, - int24 tickUpper, - uint128 amount - ) external returns (uint256 amount0, uint256 amount1); - - /// @notice Swap token0 for token1, or token1 for token0 - /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback - /// @param recipient The address to receive the output of the swap - /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0 - /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative) - /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this - /// value after the swap. If one for zero, the price cannot be greater than this value after the swap - /// @param data Any data to be passed through to the callback - /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive - /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive - function swap( - address recipient, - bool zeroForOne, - int256 amountSpecified, - uint160 sqrtPriceLimitX96, - bytes calldata data - ) external returns (int256 amount0, int256 amount1); - - /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback - /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback - /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling - /// with 0 amount{0,1} and sending the donation amount(s) from the callback - /// @param recipient The address which will receive the token0 and token1 amounts - /// @param amount0 The amount of token0 to send - /// @param amount1 The amount of token1 to send - /// @param data Any data to be passed through to the callback - function flash( - address recipient, - uint256 amount0, - uint256 amount1, - bytes calldata data - ) external; - - /// @notice Increase the maximum number of price and liquidity observations that this pool will store - /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to - /// the input observationCardinalityNext. - /// @param observationCardinalityNext The desired minimum number of observations for the pool to store - function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external; -} - - -// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title Permissioned pool actions -/// @notice Contains pool methods that may only be called by the factory owner -interface IUniswapV3PoolOwnerActions { - /// @notice Set the denominator of the protocol's % share of the fees - /// @param feeProtocol0 new protocol fee for token0 of the pool - /// @param feeProtocol1 new protocol fee for token1 of the pool - function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external; - - /// @notice Collect the protocol fee accrued to the pool - /// @param recipient The address to which collected protocol fees should be sent - /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1 - /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0 - /// @return amount0 The protocol fee collected in token0 - /// @return amount1 The protocol fee collected in token1 - function collectProtocol( - address recipient, - uint128 amount0Requested, - uint128 amount1Requested - ) external returns (uint128 amount0, uint128 amount1); -} - - -// File @uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title Events emitted by a pool -/// @notice Contains all events emitted by the pool -interface IUniswapV3PoolEvents { - /// @notice Emitted exactly once by a pool when #initialize is first called on the pool - /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize - /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96 - /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool - event Initialize(uint160 sqrtPriceX96, int24 tick); - - /// @notice Emitted when liquidity is minted for a given position - /// @param sender The address that minted the liquidity - /// @param owner The owner of the position and recipient of any minted liquidity - /// @param tickLower The lower tick of the position - /// @param tickUpper The upper tick of the position - /// @param amount The amount of liquidity minted to the position range - /// @param amount0 How much token0 was required for the minted liquidity - /// @param amount1 How much token1 was required for the minted liquidity - event Mint( - address sender, - address indexed owner, - int24 indexed tickLower, - int24 indexed tickUpper, - uint128 amount, - uint256 amount0, - uint256 amount1 - ); - - /// @notice Emitted when fees are collected by the owner of a position - /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees - /// @param owner The owner of the position for which fees are collected - /// @param tickLower The lower tick of the position - /// @param tickUpper The upper tick of the position - /// @param amount0 The amount of token0 fees collected - /// @param amount1 The amount of token1 fees collected - event Collect( - address indexed owner, - address recipient, - int24 indexed tickLower, - int24 indexed tickUpper, - uint128 amount0, - uint128 amount1 - ); - - /// @notice Emitted when a position's liquidity is removed - /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect - /// @param owner The owner of the position for which liquidity is removed - /// @param tickLower The lower tick of the position - /// @param tickUpper The upper tick of the position - /// @param amount The amount of liquidity to remove - /// @param amount0 The amount of token0 withdrawn - /// @param amount1 The amount of token1 withdrawn - event Burn( - address indexed owner, - int24 indexed tickLower, - int24 indexed tickUpper, - uint128 amount, - uint256 amount0, - uint256 amount1 - ); - - /// @notice Emitted by the pool for any swaps between token0 and token1 - /// @param sender The address that initiated the swap call, and that received the callback - /// @param recipient The address that received the output of the swap - /// @param amount0 The delta of the token0 balance of the pool - /// @param amount1 The delta of the token1 balance of the pool - /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96 - /// @param liquidity The liquidity of the pool after the swap - /// @param tick The log base 1.0001 of price of the pool after the swap - event Swap( - address indexed sender, - address indexed recipient, - int256 amount0, - int256 amount1, - uint160 sqrtPriceX96, - uint128 liquidity, - int24 tick - ); - - /// @notice Emitted by the pool for any flashes of token0/token1 - /// @param sender The address that initiated the swap call, and that received the callback - /// @param recipient The address that received the tokens from flash - /// @param amount0 The amount of token0 that was flashed - /// @param amount1 The amount of token1 that was flashed - /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee - /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee - event Flash( - address indexed sender, - address indexed recipient, - uint256 amount0, - uint256 amount1, - uint256 paid0, - uint256 paid1 - ); - - /// @notice Emitted by the pool for increases to the number of observations that can be stored - /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index - /// just before a mint/swap/burn. - /// @param observationCardinalityNextOld The previous value of the next observation cardinality - /// @param observationCardinalityNextNew The updated value of the next observation cardinality - event IncreaseObservationCardinalityNext( - uint16 observationCardinalityNextOld, - uint16 observationCardinalityNextNew - ); - - /// @notice Emitted when the protocol fee is changed by the pool - /// @param feeProtocol0Old The previous value of the token0 protocol fee - /// @param feeProtocol1Old The previous value of the token1 protocol fee - /// @param feeProtocol0New The updated value of the token0 protocol fee - /// @param feeProtocol1New The updated value of the token1 protocol fee - event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New); - - /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner - /// @param sender The address that collects the protocol fees - /// @param recipient The address that receives the collected protocol fees - /// @param amount0 The amount of token0 protocol fees that is withdrawn - /// @param amount0 The amount of token1 protocol fees that is withdrawn - event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1); -} - - -// File @uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol@v1.0.0 - -pragma solidity >=0.5.0; - - - - - - -/// @title The interface for a Uniswap V3 Pool -/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform -/// to the ERC20 specification -/// @dev The pool interface is broken up into many smaller pieces -interface IUniswapV3Pool is - IUniswapV3PoolImmutables, - IUniswapV3PoolState, - IUniswapV3PoolDerivedState, - IUniswapV3PoolActions, - IUniswapV3PoolOwnerActions, - IUniswapV3PoolEvents -{ - -} - - -// File @uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol@v1.0.0 - -pragma solidity >=0.5.0; - -/// @title Minimal ERC20 interface for Uniswap -/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 -interface IERC20Minimal { - /// @notice Returns the balance of a token - /// @param account The account for which to look up the number of tokens it has, i.e. its balance - /// @return The number of tokens held by the account - function balanceOf(address account) external view returns (uint256); - - /// @notice Transfers the amount of token from the `msg.sender` to the recipient - /// @param recipient The account that will receive the amount transferred - /// @param amount The number of tokens to send from the sender to the recipient - /// @return Returns true for a successful transfer, false for an unsuccessful transfer - function transfer(address recipient, uint256 amount) external returns (bool); - - /// @notice Returns the current allowance given to a spender by an owner - /// @param owner The account of the token owner - /// @param spender The account of the token spender - /// @return The current allowance granted by `owner` to `spender` - function allowance(address owner, address spender) external view returns (uint256); - - /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` - /// @param spender The account which will be allowed to spend a given amount of the owners tokens - /// @param amount The amount of tokens allowed to be used by `spender` - /// @return Returns true for a successful approval, false for unsuccessful - function approve(address spender, uint256 amount) external returns (bool); - - /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` - /// @param sender The account from which the transfer will be initiated - /// @param recipient The recipient of the transfer - /// @param amount The amount of the transfer - /// @return Returns true for a successful transfer, false for unsuccessful - function transferFrom( - address sender, - address recipient, - uint256 amount - ) external returns (bool); - - /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. - /// @param from The account from which the tokens were sent, i.e. the balance decreased - /// @param to The account to which the tokens were sent, i.e. the balance increased - /// @param value The amount of tokens that were transferred - event Transfer(address indexed from, address indexed to, uint256 value); - - /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. - /// @param owner The account that approved spending of its tokens - /// @param spender The account for which the spending allowance was modified - /// @param value The new allowance from the owner to the spender - event Approval(address indexed owner, address indexed spender, uint256 value); -} - - -// File @openzeppelin/contracts/introspection/IERC165.sol@v3.4.2 - - -pragma solidity >=0.6.0 <0.8.0; - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} - - -// File @openzeppelin/contracts/token/ERC721/IERC721.sol@v3.4.2 - - -pragma solidity >=0.6.2 <0.8.0; - -/** - * @dev Required interface of an ERC721 compliant contract. - */ -interface IERC721 is IERC165 { - /** - * @dev Emitted when `tokenId` token is transferred from `from` to `to`. - */ - event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); - - /** - * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. - */ - event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); - - /** - * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. - */ - event ApprovalForAll(address indexed owner, address indexed operator, bool approved); - - /** - * @dev Returns the number of tokens in ``owner``'s account. - */ - function balanceOf(address owner) external view returns (uint256 balance); - - /** - * @dev Returns the owner of the `tokenId` token. - * - * Requirements: - * - * - `tokenId` must exist. - */ - function ownerOf(uint256 tokenId) external view returns (address owner); - - /** - * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients - * are aware of the ERC721 protocol to prevent tokens from being forever locked. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `to` cannot be the zero address. - * - `tokenId` token must exist and be owned by `from`. - * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. - * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. - * - * Emits a {Transfer} event. - */ - function safeTransferFrom(address from, address to, uint256 tokenId) external; - - /** - * @dev Transfers `tokenId` token from `from` to `to`. - * - * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `to` cannot be the zero address. - * - `tokenId` token must be owned by `from`. - * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. - * - * Emits a {Transfer} event. - */ - function transferFrom(address from, address to, uint256 tokenId) external; - - /** - * @dev Gives permission to `to` to transfer `tokenId` token to another account. - * The approval is cleared when the token is transferred. - * - * Only a single account can be approved at a time, so approving the zero address clears previous approvals. - * - * Requirements: - * - * - The caller must own the token or be an approved operator. - * - `tokenId` must exist. - * - * Emits an {Approval} event. - */ - function approve(address to, uint256 tokenId) external; - - /** - * @dev Returns the account approved for `tokenId` token. - * - * Requirements: - * - * - `tokenId` must exist. - */ - function getApproved(uint256 tokenId) external view returns (address operator); - - /** - * @dev Approve or remove `operator` as an operator for the caller. - * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. - * - * Requirements: - * - * - The `operator` cannot be the caller. - * - * Emits an {ApprovalForAll} event. - */ - function setApprovalForAll(address operator, bool _approved) external; - - /** - * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. - * - * See {setApprovalForAll} - */ - function isApprovedForAll(address owner, address operator) external view returns (bool); - - /** - * @dev Safely transfers `tokenId` token from `from` to `to`. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `to` cannot be the zero address. - * - `tokenId` token must exist and be owned by `from`. - * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. - * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. - * - * Emits a {Transfer} event. - */ - function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; -} - - -// File @openzeppelin/contracts/token/ERC721/IERC721Metadata.sol@v3.4.2 - - -pragma solidity >=0.6.2 <0.8.0; - -/** - * @title ERC-721 Non-Fungible Token Standard, optional metadata extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -interface IERC721Metadata is IERC721 { - - /** - * @dev Returns the token collection name. - */ - function name() external view returns (string memory); - - /** - * @dev Returns the token collection symbol. - */ - function symbol() external view returns (string memory); - - /** - * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. - */ - function tokenURI(uint256 tokenId) external view returns (string memory); -} - - -// File @openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol@v3.4.2 - - - -pragma solidity >=0.6.2 <0.8.0; - -/** - * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension - * @dev See https://eips.ethereum.org/EIPS/eip-721 - */ -interface IERC721Enumerable is IERC721 { - - /** - * @dev Returns the total amount of tokens stored by the contract. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns a token ID owned by `owner` at a given `index` of its token list. - * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. - */ - function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); - - /** - * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. - * Use along with {totalSupply} to enumerate all tokens. - */ - function tokenByIndex(uint256 index) external view returns (uint256); -} - - -// File @uniswap/v3-periphery/contracts/interfaces/IPoolInitializer.sol@v1.3.0 - -pragma solidity >=0.7.5; -pragma abicoder v2; - -/// @title Creates and initializes V3 Pools -/// @notice Provides a method for creating and initializing a pool, if necessary, for bundling with other methods that -/// require the pool to exist. -interface IPoolInitializer { - /// @notice Creates a new pool if it does not exist, then initializes if not initialized - /// @dev This method can be bundled with others via IMulticall for the first action (e.g. mint) performed against a pool - /// @param token0 The contract address of token0 of the pool - /// @param token1 The contract address of token1 of the pool - /// @param fee The fee amount of the v3 pool for the specified token pair - /// @param sqrtPriceX96 The initial square root price of the pool as a Q64.96 value - /// @return pool Returns the pool address based on the pair of tokens and fee, will return the newly created pool address if necessary - function createAndInitializePoolIfNecessary( - address token0, - address token1, - uint24 fee, - uint160 sqrtPriceX96 - ) external payable returns (address pool); -} - - -// File @uniswap/v3-periphery/contracts/interfaces/IERC721Permit.sol@v1.3.0 - -pragma solidity >=0.7.5; - -/// @title ERC721 with permit -/// @notice Extension to ERC721 that includes a permit function for signature based approvals -interface IERC721Permit is IERC721 { - /// @notice The permit typehash used in the permit signature - /// @return The typehash for the permit - function PERMIT_TYPEHASH() external pure returns (bytes32); - - /// @notice The domain separator used in the permit signature - /// @return The domain seperator used in encoding of permit signature - function DOMAIN_SEPARATOR() external view returns (bytes32); - - /// @notice Approve of a specific token ID for spending by spender via signature - /// @param spender The account that is being approved - /// @param tokenId The ID of the token that is being approved for spending - /// @param deadline The deadline timestamp by which the call must be mined for the approve to work - /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` - /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` - /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` - function permit( - address spender, - uint256 tokenId, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external payable; -} - - -// File @uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol@v1.3.0 - -pragma solidity >=0.7.5; - -/// @title Periphery Payments -/// @notice Functions to ease deposits and withdrawals of ETH -interface IPeripheryPayments { - /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH. - /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users. - /// @param amountMinimum The minimum amount of WETH9 to unwrap - /// @param recipient The address receiving ETH - function unwrapWETH9(uint256 amountMinimum, address recipient) external payable; - - /// @notice Refunds any ETH balance held by this contract to the `msg.sender` - /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps - /// that use ether for the input amount - function refundETH() external payable; - - /// @notice Transfers the full amount of a token held by this contract to recipient - /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users - /// @param token The contract address of the token which will be transferred to `recipient` - /// @param amountMinimum The minimum amount of token required for a transfer - /// @param recipient The destination address of the token - function sweepToken( - address token, - uint256 amountMinimum, - address recipient - ) external payable; -} - - -// File @uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol@v1.3.0 - -pragma solidity >=0.5.0; - -/// @title Immutable state -/// @notice Functions that return immutable state of the router -interface IPeripheryImmutableState { - /// @return Returns the address of the Uniswap V3 factory - function factory() external view returns (address); - - /// @return Returns the address of WETH9 - function WETH9() external view returns (address); -} - - -// File @uniswap/v3-periphery/contracts/libraries/PoolAddress.sol@v1.3.0 - -pragma solidity >=0.5.0; - -/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee -library PoolAddress { - bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54; - - /// @notice The identifying key of the pool - struct PoolKey { - address token0; - address token1; - uint24 fee; - } - - /// @notice Returns PoolKey: the ordered tokens with the matched fee levels - /// @param tokenA The first token of a pool, unsorted - /// @param tokenB The second token of a pool, unsorted - /// @param fee The fee level of the pool - /// @return Poolkey The pool details with ordered token0 and token1 assignments - function getPoolKey( - address tokenA, - address tokenB, - uint24 fee - ) internal pure returns (PoolKey memory) { - if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); - return PoolKey({token0: tokenA, token1: tokenB, fee: fee}); - } - - /// @notice Deterministically computes the pool address given the factory and PoolKey - /// @param factory The Uniswap V3 factory contract address - /// @param key The PoolKey - /// @return pool The contract address of the V3 pool - function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) { - require(key.token0 < key.token1); - pool = address( - uint256( - keccak256( - abi.encodePacked( - hex'ff', - factory, - keccak256(abi.encode(key.token0, key.token1, key.fee)), - POOL_INIT_CODE_HASH - ) - ) - ) - ); - } -} - - -// File @uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol@v1.3.0 - -0x929376C77A2fB8152375a089a4Fccf84Ff481479pragma solidity >=0.7.5; -pragma abicoder v2; - - - - - - -/// @title Non-fungible token for positions -/// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred -/// and authorized. -interface INonfungiblePositionManager is - IPoolInitializer, - IPeripheryPayments, - IPeripheryImmutableState, - IERC721Metadata, - IERC721Enumerable, - IERC721Permit -{ - /// @notice Emitted when liquidity is increased for a position NFT - /// @dev Also emitted when a token is minted - /// @param tokenId The ID of the token for which liquidity was increased - /// @param liquidity The amount by which liquidity for the NFT position was increased - /// @param amount0 The amount of token0 that was paid for the increase in liquidity - /// @param amount1 The amount of token1 that was paid for the increase in liquidity - event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); - /// @notice Emitted when liquidity is decreased for a position NFT - /// @param tokenId The ID of the token for which liquidity was decreased - /// @param liquidity The amount by which liquidity for the NFT position was decreased - /// @param amount0 The amount of token0 that was accounted for the decrease in liquidity - /// @param amount1 The amount of token1 that was accounted for the decrease in liquidity - event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1); - /// @notice Emitted when tokens are collected for a position NFT - /// @dev The amounts reported may not be exactly equivalent to the amounts transferred, due to rounding behavior - /// @param tokenId The ID of the token for which underlying tokens were collected - /// @param recipient The address of the account that received the collected tokens - /// @param amount0 The amount of token0 owed to the position that was collected - /// @param amount1 The amount of token1 owed to the position that was collected - event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1); - - /// @notice Returns the position information associated with a given token ID. - /// @dev Throws if the token ID is not valid. - /// @param tokenId The ID of the token that represents the position - /// @return nonce The nonce for permits - /// @return operator The address that is approved for spending - /// @return token0 The address of the token0 for a specific pool - /// @return token1 The address of the token1 for a specific pool - /// @return fee The fee associated with the pool - /// @return tickLower The lower end of the tick range for the position - /// @return tickUpper The higher end of the tick range for the position - /// @return liquidity The liquidity of the position - /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position - /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position - /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation - /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation - function positions(uint256 tokenId) - external - view - returns ( - uint96 nonce, - address operator, - address token0, - address token1, - uint24 fee, - int24 tickLower, - int24 tickUpper, - uint128 liquidity, - uint256 feeGrowthInside0LastX128, - uint256 feeGrowthInside1LastX128, - uint128 tokensOwed0, - uint128 tokensOwed1 - ); - - struct MintParams { - address token0; - address token1; - uint24 fee; - int24 tickLower; - int24 tickUpper; - uint256 amount0Desired; - uint256 amount1Desired; - uint256 amount0Min; - uint256 amount1Min; - address recipient; - uint256 deadline; - } - - /// @notice Creates a new position wrapped in a NFT - /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized - /// a method does not exist, i.e. the pool is assumed to be initialized. - /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata - /// @return tokenId The ID of the token that represents the minted position - /// @return liquidity The amount of liquidity for this position - /// @return amount0 The amount of token0 - /// @return amount1 The amount of token1 - function mint(MintParams calldata params) - external - payable - returns ( - uint256 tokenId, - uint128 liquidity, - uint256 amount0, - uint256 amount1 - ); - - struct IncreaseLiquidityParams { - uint256 tokenId; - uint256 amount0Desired; - uint256 amount1Desired; - uint256 amount0Min; - uint256 amount1Min; - uint256 deadline; - } - - /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender` - /// @param params tokenId The ID of the token for which liquidity is being increased, - /// amount0Desired The desired amount of token0 to be spent, - /// amount1Desired The desired amount of token1 to be spent, - /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check, - /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check, - /// deadline The time by which the transaction must be included to effect the change - /// @return liquidity The new liquidity amount as a result of the increase - /// @return amount0 The amount of token0 to acheive resulting liquidity - /// @return amount1 The amount of token1 to acheive resulting liquidity - function increaseLiquidity(IncreaseLiquidityParams calldata params) - external - payable - returns ( - uint128 liquidity, - uint256 amount0, - uint256 amount1 - ); - - struct DecreaseLiquidityParams { - uint256 tokenId; - uint128 liquidity; - uint256 amount0Min; - uint256 amount1Min; - uint256 deadline; - } - - /// @notice Decreases the amount of liquidity in a position and accounts it to the position - /// @param params tokenId The ID of the token for which liquidity is being decreased, - /// amount The amount by which liquidity will be decreased, - /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity, - /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity, - /// deadline The time by which the transaction must be included to effect the change - /// @return amount0 The amount of token0 accounted to the position's tokens owed - /// @return amount1 The amount of token1 accounted to the position's tokens owed - function decreaseLiquidity(DecreaseLiquidityParams calldata params) - external - payable - returns (uint256 amount0, uint256 amount1); - - struct CollectParams { - uint256 tokenId; - address recipient; - uint128 amount0Max; - uint128 amount1Max; - } - - /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient - /// @param params tokenId The ID of the NFT for which tokens are being collected, - /// recipient The account that should receive the tokens, - /// amount0Max The maximum amount of token0 to collect, - /// amount1Max The maximum amount of token1 to collect - /// @return amount0 The amount of fees collected in token0 - /// @return amount1 The amount of fees collected in token1 - function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1); - - /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens - /// must be collected first. - /// @param tokenId The ID of the token that is being burned - function burn(uint256 tokenId) external payable; -} - - -// File @uniswap/v3-periphery/contracts/interfaces/IMulticall.sol@v1.3.0 - -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.7.5; -pragma abicoder v2; - -/// @title Multicall interface -/// @notice Enables calling multiple methods in a single call to the contract -interface IMulticall { - /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed - /// @dev The `msg.value` should not be trusted for any method callable from multicall. - /// @param data The encoded function data for each of the calls to make to this contract - /// @return results The results from each of the calls passed in via data - function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); -} - - -// File contracts/polygon/connectors/uniswap/v3_staker/interface.sol - -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity =0.7.6; -pragma abicoder v2; -/// @title Uniswap V3 Staker Interface -/// @notice Allows staking nonfungible liquidity tokens in exchange for reward tokens -interface IUniswapV3Staker is IERC721Receiver, IMulticall { - /// @param rewardToken The token being distributed as a reward - /// @param pool The Uniswap V3 pool - /// @param startTime The time when the incentive program begins - /// @param endTime The time when rewards stop accruing - /// @param refundee The address which receives any remaining reward tokens when the incentive is ended - struct IncentiveKey { - IERC20Minimal rewardToken; - IUniswapV3Pool pool; - uint256 startTime; - uint256 endTime; - address refundee; - } - - /// @notice The Uniswap V3 Factory - function factory() external view returns (IUniswapV3Factory); - - /// @notice The nonfungible position manager with which this staking contract is compatible - function nonfungiblePositionManager() external view returns (INonfungiblePositionManager); - - /// @notice The max duration of an incentive in seconds - function maxIncentiveDuration() external view returns (uint256); - - /// @notice The max amount of seconds into the future the incentive startTime can be set - function maxIncentiveStartLeadTime() external view returns (uint256); - - /// @notice Represents a staking incentive - /// @param incentiveId The ID of the incentive computed from its parameters - /// @return totalRewardUnclaimed The amount of reward token not yet claimed by users - /// @return totalSecondsClaimedX128 Total liquidity-seconds claimed, represented as a UQ32.128 - /// @return numberOfStakes The count of deposits that are currently staked for the incentive - function incentives(bytes32 incentiveId) - external - view - returns ( - uint256 totalRewardUnclaimed, - uint160 totalSecondsClaimedX128, - uint96 numberOfStakes - ); - - /// @notice Returns information about a deposited NFT - /// @return owner The owner of the deposited NFT - /// @return numberOfStakes Counter of how many incentives for which the liquidity is staked - /// @return tickLower The lower tick of the range - /// @return tickUpper The upper tick of the range - function deposits(uint256 tokenId) - external - view - returns ( - address owner, - uint48 numberOfStakes, - int24 tickLower, - int24 tickUpper - ); - - /// @notice Returns information about a staked liquidity NFT - /// @param tokenId The ID of the staked token - /// @param incentiveId The ID of the incentive for which the token is staked - /// @return secondsPerLiquidityInsideInitialX128 secondsPerLiquidity represented as a UQ32.128 - /// @return liquidity The amount of liquidity in the NFT as of the last time the rewards were computed - function stakes(uint256 tokenId, bytes32 incentiveId) - external - view - returns (uint160 secondsPerLiquidityInsideInitialX128, uint128 liquidity); - - /// @notice Returns amounts of reward tokens owed to a given address according to the last time all stakes were updated - /// @param rewardToken The token for which to check rewards - /// @param owner The owner for which the rewards owed are checked - /// @return rewardsOwed The amount of the reward token claimable by the owner - function rewards(IERC20Minimal rewardToken, address owner) external view returns (uint256 rewardsOwed); - - /// @notice Creates a new liquidity mining incentive program - /// @param key Details of the incentive to create - /// @param reward The amount of reward tokens to be distributed - function createIncentive(IncentiveKey memory key, uint256 reward) external; - - /// @notice Ends an incentive after the incentive end time has passed and all stakes have been withdrawn - /// @param key Details of the incentive to end - /// @return refund The remaining reward tokens when the incentive is ended - function endIncentive(IncentiveKey memory key) external returns (uint256 refund); - - /// @notice Transfers ownership of a deposit from the sender to the given recipient - /// @param tokenId The ID of the token (and the deposit) to transfer - /// @param to The new owner of the deposit - function transferDeposit(uint256 tokenId, address to) external; - - /// @notice Withdraws a Uniswap V3 LP token `tokenId` from this contract to the recipient `to` - /// @param tokenId The unique identifier of an Uniswap V3 LP token - /// @param to The address where the LP token will be sent - /// @param data An optional data array that will be passed along to the `to` address via the NFT safeTransferFrom - function withdrawToken( - uint256 tokenId, - address to, - bytes memory data - ) external; - - /// @notice Stakes a Uniswap V3 LP token - /// @param key The key of the incentive for which to stake the NFT - /// @param tokenId The ID of the token to stake - function stakeToken(IncentiveKey memory key, uint256 tokenId) external; - - /// @notice Unstakes a Uniswap V3 LP token - /// @param key The key of the incentive for which to unstake the NFT - /// @param tokenId The ID of the token to unstake - function unstakeToken(IncentiveKey memory key, uint256 tokenId) external; - - /// @notice Transfers `amountRequested` of accrued `rewardToken` rewards from the contract to the recipient `to` - /// @param rewardToken The token being distributed as a reward - /// @param to The address where claimed rewards will be sent to - /// @param amountRequested The amount of reward tokens to claim. Claims entire reward amount if set to 0. - /// @return reward The amount of reward tokens claimed - function claimReward( - IERC20Minimal rewardToken, - address to, - uint256 amountRequested - ) external returns (uint256 reward); - - /// @notice Calculates the reward amount that will be received for the given stake - /// @param key The key of the incentive - /// @param tokenId The ID of the token - /// @return reward The reward accrued to the NFT for the given incentive thus far - function getRewardInfo(IncentiveKey memory key, uint256 tokenId) - external - returns (uint256 reward, uint160 secondsInsideX128); - - /// @notice Event emitted when a liquidity mining incentive has been created - /// @param rewardToken The token being distributed as a reward - /// @param pool The Uniswap V3 pool - /// @param startTime The time when the incentive program begins - /// @param endTime The time when rewards stop accruing - /// @param refundee The address which receives any remaining reward tokens after the end time - /// @param reward The amount of reward tokens to be distributed - event IncentiveCreated( - IERC20Minimal indexed rewardToken, - IUniswapV3Pool indexed pool, - uint256 startTime, - uint256 endTime, - address refundee, - uint256 reward - ); - - /// @notice Event that can be emitted when a liquidity mining incentive has ended - /// @param incentiveId The incentive which is ending - /// @param refund The amount of reward tokens refunded - event IncentiveEnded(bytes32 indexed incentiveId, uint256 refund); - - /// @notice Emitted when ownership of a deposit changes - /// @param tokenId The ID of the deposit (and token) that is being transferred - /// @param oldOwner The owner before the deposit was transferred - /// @param newOwner The owner after the deposit was transferred - event DepositTransferred(uint256 indexed tokenId, address indexed oldOwner, address indexed newOwner); - - /// @notice Event emitted when a Uniswap V3 LP token has been staked - /// @param tokenId The unique identifier of an Uniswap V3 LP token - /// @param liquidity The amount of liquidity staked - /// @param incentiveId The incentive in which the token is staking - event TokenStaked(uint256 indexed tokenId, bytes32 indexed incentiveId, uint128 liquidity); - - /// @notice Event emitted when a Uniswap V3 LP token has been unstaked - /// @param tokenId The unique identifier of an Uniswap V3 LP token - /// @param incentiveId The incentive in which the token is staking - event TokenUnstaked(uint256 indexed tokenId, bytes32 indexed incentiveId); - - /// @notice Event emitted when a reward token has been claimed - /// @param to The address where claimed rewards were sent to - /// @param reward The amount of reward tokens claimed - event RewardClaimed(address indexed to, uint256 reward); -} - - -// File @openzeppelin/contracts/math/SafeMath.sol@v3.4.2 - -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.0 <0.8.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - - /** - * @dev Returns the substraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - if (b > a) return (false, 0); - return (true, a - b); - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - if (b == 0) return (false, 0); - return (true, a / b); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - if (b == 0) return (false, 0); - return (true, a % b); - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a, "SafeMath: subtraction overflow"); - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - if (a == 0) return 0; - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - require(b > 0, "SafeMath: division by zero"); - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b > 0, "SafeMath: modulo by zero"); - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b <= a, errorMessage); - return a - b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryDiv}. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b > 0, errorMessage); - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { - require(b > 0, errorMessage); - return a % b; - } -} - - -// File contracts/polygon/common/math.sol - -pragma solidity ^0.7.0; -contract DSMath { - uint constant WAD = 10 ** 18; - uint constant RAY = 10 ** 27; - - function add(uint x, uint y) internal pure returns (uint z) { - z = SafeMath.add(x, y); - } - - function sub(uint x, uint y) internal virtual pure returns (uint z) { - z = SafeMath.sub(x, y); - } - - function mul(uint x, uint y) internal pure returns (uint z) { - z = SafeMath.mul(x, y); - } - - function div(uint x, uint y) internal pure returns (uint z) { - z = SafeMath.div(x, y); - } - - function wmul(uint x, uint y) internal pure returns (uint z) { - z = SafeMath.add(SafeMath.mul(x, y), WAD / 2) / WAD; - } - - function wdiv(uint x, uint y) internal pure returns (uint z) { - z = SafeMath.add(SafeMath.mul(x, WAD), y / 2) / y; - } - - function rdiv(uint x, uint y) internal pure returns (uint z) { - z = SafeMath.add(SafeMath.mul(x, RAY), y / 2) / y; - } - - function rmul(uint x, uint y) internal pure returns (uint z) { - z = SafeMath.add(SafeMath.mul(x, y), RAY / 2) / RAY; - } - - function toInt(uint x) internal pure returns (int y) { - y = int(x); - require(y >= 0, "int-overflow"); - } - - function toRad(uint wad) internal pure returns (uint rad) { - rad = mul(wad, 10 ** 27); - } - -} - - -// File contracts/polygon/common/stores.sol - -pragma solidity ^0.7.0; -abstract contract Stores { - - /** - * @dev Return ethereum address - */ - address constant internal maticAddr = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - - /** - * @dev Return Wrapped ETH address - */ - address constant internal wmaticAddr = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270; - - /** - * @dev Return memory variable address - */ - MemoryInterface constant internal instaMemory = MemoryInterface(0x6C7256cf7C003dD85683339F75DdE9971f98f2FD); - - /** - * @dev Get Uint value from InstaMemory Contract. - */ - function getUint(uint getId, uint val) internal returns (uint returnVal) { - returnVal = getId == 0 ? val : instaMemory.getUint(getId); - } - - /** - * @dev Set Uint value in InstaMemory Contract. - */ - function setUint(uint setId, uint val) virtual internal { - if (setId != 0) instaMemory.setUint(setId, val); - } - -} - - -// File contracts/polygon/common/basic.sol - -pragma solidity ^0.7.0; -abstract contract Basic is DSMath, Stores { - - function convert18ToDec(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { - amt = (_amt / 10 ** (18 - _dec)); - } - - function convertTo18(uint _dec, uint256 _amt) internal pure returns (uint256 amt) { - amt = mul(_amt, 10 ** (18 - _dec)); - } - - function getTokenBal(TokenInterface token) internal view returns(uint _amt) { - _amt = address(token) == maticAddr ? address(this).balance : token.balanceOf(address(this)); - } - - function getTokensDec(TokenInterface buyAddr, TokenInterface sellAddr) internal view returns(uint buyDec, uint sellDec) { - buyDec = address(buyAddr) == maticAddr ? 18 : buyAddr.decimals(); - sellDec = address(sellAddr) == maticAddr ? 18 : sellAddr.decimals(); - } - - function encodeEvent(string memory eventName, bytes memory eventParam) internal pure returns (bytes memory) { - return abi.encode(eventName, eventParam); - } - - function changeMaticAddress(address buy, address sell) internal pure returns(TokenInterface _buy, TokenInterface _sell){ - _buy = buy == maticAddr ? TokenInterface(wmaticAddr) : TokenInterface(buy); - _sell = sell == maticAddr ? TokenInterface(wmaticAddr) : TokenInterface(sell); - } - - function approve(TokenInterface token, address spender, uint256 amount) internal { - try token.approve(spender, amount) { - - } catch { - token.approve(spender, 0); - token.approve(spender, amount); - } - } - - function convertMaticToWmatic(bool isMatic, TokenInterface token, uint amount) internal { - if(isMatic) token.deposit{value: amount}(); - } - - function convertWmaticToMatic(bool isMatic, TokenInterface token, uint amount) internal { - if(isMatic) { - approve(token, address(token), amount); - token.withdraw(amount); - } - } -} - - -// File @uniswap/v3-core/contracts/libraries/TickMath.sol@v1.0.0 - -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity >=0.5.0; - -/// @title Math library for computing sqrt prices from ticks and vice versa -/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports -/// prices between 2**-128 and 2**128 -library TickMath { - /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128 - int24 internal constant MIN_TICK = -887272; - /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 - int24 internal constant MAX_TICK = -MIN_TICK; - - /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK) - uint160 internal constant MIN_SQRT_RATIO = 4295128739; - /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK) - uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342; - - /// @notice Calculates sqrt(1.0001^tick) * 2^96 - /// @dev Throws if |tick| > max tick - /// @param tick The input tick for the above formula - /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0) - /// at the given tick - function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) { - uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick)); - require(absTick <= uint256(MAX_TICK), 'T'); - - uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000; - if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128; - if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128; - if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128; - if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128; - if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128; - if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128; - if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128; - if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128; - if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128; - if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128; - if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128; - if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128; - if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128; - if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128; - if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128; - if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128; - if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128; - if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128; - if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128; - - if (tick > 0) ratio = type(uint256).max / ratio; - - // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96. - // we then downcast because we know the result always fits within 160 bits due to our tick input constraint - // we round up in the division so getTickAtSqrtRatio of the output price is always consistent - sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)); - } - - /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio - /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may - /// ever return. - /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96 - /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio - function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) { - // second inequality must be < because the price can never reach the price at the max tick - require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R'); - uint256 ratio = uint256(sqrtPriceX96) << 32; - - uint256 r = ratio; - uint256 msb = 0; - - assembly { - let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) - msb := or(msb, f) - r := shr(f, r) - } - assembly { - let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF)) - msb := or(msb, f) - r := shr(f, r) - } - assembly { - let f := shl(5, gt(r, 0xFFFFFFFF)) - msb := or(msb, f) - r := shr(f, r) - } - assembly { - let f := shl(4, gt(r, 0xFFFF)) - msb := or(msb, f) - r := shr(f, r) - } - assembly { - let f := shl(3, gt(r, 0xFF)) - msb := or(msb, f) - r := shr(f, r) - } - assembly { - let f := shl(2, gt(r, 0xF)) - msb := or(msb, f) - r := shr(f, r) - } - assembly { - let f := shl(1, gt(r, 0x3)) - msb := or(msb, f) - r := shr(f, r) - } - assembly { - let f := gt(r, 0x1) - msb := or(msb, f) - } - - if (msb >= 128) r = ratio >> (msb - 127); - else r = ratio << (127 - msb); - - int256 log_2 = (int256(msb) - 128) << 64; - - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(63, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(62, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(61, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(60, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(59, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(58, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(57, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(56, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(55, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(54, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(53, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(52, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(51, f)) - r := shr(f, r) - } - assembly { - r := shr(127, mul(r, r)) - let f := shr(128, r) - log_2 := or(log_2, shl(50, f)) - } - - int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number - - int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128); - int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128); - - tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow; - } -} - - -// File @openzeppelin/contracts/token/ERC20/IERC20.sol@v3.4.2 - -// SPDX-License-Identifier: MIT - -pragma solidity >=0.6.0 <0.8.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `sender` to `recipient` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); - - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); -} - - -// File @uniswap/v3-periphery/contracts/libraries/TransferHelper.sol@v1.3.0 - -pragma solidity >=0.6.0; - -library TransferHelper { - /// @notice Transfers tokens from the targeted address to the given destination - /// @notice Errors with 'STF' if transfer fails - /// @param token The contract address of the token to be transferred - /// @param from The originating address from which the tokens will be transferred - /// @param to The destination address of the transfer - /// @param value The amount to be transferred - function safeTransferFrom( - address token, - address from, - address to, - uint256 value - ) internal { - (bool success, bytes memory data) = - token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF'); - } - - /// @notice Transfers tokens from msg.sender to a recipient - /// @dev Errors with ST if transfer fails - /// @param token The contract address of the token which will be transferred - /// @param to The recipient of the transfer - /// @param value The value of the transfer - function safeTransfer( - address token, - address to, - uint256 value - ) internal { - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST'); - } - - /// @notice Approves the stipulated contract to spend the given allowance in the given token - /// @dev Errors with 'SA' if transfer fails - /// @param token The contract address of the token to be approved - /// @param to The target of the approval - /// @param value The amount of the given token the target will be allowed to spend - function safeApprove( - address token, - address to, - uint256 value - ) internal { - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA'); - } - - /// @notice Transfers ETH to the recipient address - /// @dev Fails with `STE` - /// @param to The destination of the transfer - /// @param value The value to be transferred - function safeTransferETH(address to, uint256 value) internal { - (bool success, ) = to.call{value: value}(new bytes(0)); - require(success, 'STE'); - } -} - - -// File contracts/polygon/connectors/uniswap/v3_staker/helpers.sol - -pragma solidity ^0.7.6; -pragma abicoder v2; -abstract contract Helpers is DSMath, Basic { - /** - * @dev uniswap v3 NFT Position Manager & Swap Router - */ - INonfungiblePositionManager constant nftManager = - INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88); - IUniswapV3Staker constant staker = - IUniswapV3Staker(0x1f98407aaB862CdDeF78Ed252D6f557aA5b0f00d); - - /** - * @dev Get Last NFT Index - * @param user: User address - */ - function _getLastNftId(address user) - internal - view - returns (uint256 tokenId) - { - uint256 len = nftManager.balanceOf(user); - tokenId = nftManager.tokenOfOwnerByIndex(user, len - 1); - } - - function getPoolAddress(uint256 _tokenId) - internal - view - returns (address pool) - { - (bool success, bytes memory data) = address(nftManager).staticcall( - abi.encodeWithSelector(nftManager.positions.selector, _tokenId) - ); - require(success, "fetching positions failed"); - { - (, , address token0, address token1, uint24 fee, , , ) = abi.decode( - data, - ( - uint96, - address, - address, - address, - uint24, - int24, - int24, - uint128 - ) - ); - - pool = PoolAddress.computeAddress( - nftManager.factory(), - PoolAddress.PoolKey({token0: token0, token1: token1, fee: fee}) - ); - } - } - - function _stake( - uint256 _tokenId, - IUniswapV3Staker.IncentiveKey memory _incentiveId - ) internal { - staker.stakeToken(_incentiveId, _tokenId); - } - - function _unstake( - IUniswapV3Staker.IncentiveKey memory _key, - uint256 _tokenId - ) internal { - staker.unstakeToken(_key, _tokenId); - } - - function _claimRewards( - IERC20Minimal _rewardToken, - address _to, - uint256 _amountRequested - ) internal returns (uint256 rewards) { - rewards = staker.claimReward(_rewardToken, _to, _amountRequested); - } -} - - -// File contracts/polygon/connectors/uniswap/v3_staker/events.sol - -pragma solidity ^0.7.0; - -contract Events { - event LogDeposit(uint256 tokenId); - - event LogDepositAndStake(uint256 tokenId, bytes32 incentiveId); - - event LogWithdraw(uint256 indexed tokenId); - - event LogDepositTransfer(uint256 indexed tokenId, address to); - - event LogStake(uint256 indexed tokenId, bytes32 incentiveId); - - event LogUnstake(uint256 indexed tokenId, bytes32 incentiveId); - - event LogRewardClaimed( - address indexed rewardToken, - uint256 amount - ); - - event LogIncentiveCreated( - bytes32 incentiveId, - address poolAddr, - address refundee, - uint256 startTime, - uint256 endTime, - uint256 reward - ); -} - - -// File contracts/polygon/connectors/uniswap/v3_staker/main.sol - -pragma solidity ^0.7.6; -pragma abicoder v2; - -/** - * @title Uniswap v3. - * @dev Decentralized Exchange. - */ -abstract contract UniswapResolver is Helpers, Events { - /** - * @dev Deposit NFT token - * @notice Transfer deposited NFT token - * @param _tokenId NFT LP Token ID - */ - function deposit(uint256 _tokenId) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - if (_tokenId == 0) _tokenId = _getLastNftId(address(this)); - nftManager.safeTransferFrom( - address(this), - address(staker), - _tokenId, - "" - ); - - _eventName = "LogDeposit(uint256)"; - _eventParam = abi.encode(_tokenId); - } - - /** - * @dev Deposit and Stake NFT token - * @notice To Deposit and Stake NFT for Staking - * @param _rewardToken _rewardToken address - * @param _startTime stake start time - * @param _endTime stake end time - * @param _refundee refundee address - * @param _tokenId NFT LP token id - */ - function depositAndStake ( - address _rewardToken, - uint256 _startTime, - uint256 _endTime, - address _refundee, - uint256 _tokenId - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - if (_tokenId == 0) _tokenId = _getLastNftId(address(this)); - nftManager.safeTransferFrom( - address(this), - address(staker), - _tokenId, - "" - ); - - address poolAddr = getPoolAddress(_tokenId); - - IUniswapV3Pool pool = IUniswapV3Pool(poolAddr); - IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker - .IncentiveKey( - IERC20Minimal(_rewardToken), - pool, - _startTime, - _endTime, - _refundee - ); - _stake(_tokenId, _key); - - _eventName = "LogDepositAndStake(uint256,bytes32)"; - _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key))); - } - - /** - * @dev Deposit Transfer - * @notice Transfer deposited NFT token - * @param _tokenId NFT LP Token ID - * @param _to address to transfer - */ - function transferDeposit(uint256 _tokenId, address _to) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - staker.transferDeposit(_tokenId, _to); - - _eventName = "LogDepositTransfer(uint256,address)"; - _eventParam = abi.encode(_tokenId, _to); - } - - /** - * @dev Withdraw NFT LP token - * @notice Withdraw NFT LP token from staking pool - * @param _tokenId NFT LP Token ID - */ - function withdraw(uint256 _tokenId) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - staker.withdrawToken(_tokenId, address(this), ""); - - _eventName = "LogWithdraw(uint256)"; - _eventParam = abi.encode(_tokenId); - } - - /** - * @dev Stake NFT LP token - * @notice Stake NFT LP Position - * @param _rewardToken _rewardToken address - * @param _startTime stake start time - * @param _endTime stake end time - * @param _refundee refundee address - * @param _tokenId NFT LP token id - */ - function stake ( - address _rewardToken, - uint256 _startTime, - uint256 _endTime, - address _refundee, - uint256 _tokenId - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - address poolAddr = getPoolAddress(_tokenId); - - IUniswapV3Pool pool = IUniswapV3Pool(poolAddr); - IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker - .IncentiveKey( - IERC20Minimal(_rewardToken), - pool, - _startTime, - _endTime, - _refundee - ); - _stake(_tokenId, _key); - - _eventName = "LogStake(uint256,bytes32)"; - _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key))); - } - - /** - * @dev Unstake NFT LP token - * @notice Unstake NFT LP Position - * @param _rewardToken _rewardToken address - * @param _startTime stake start time - * @param _endTime stake end time - * @param _refundee refundee address - * @param _tokenId NFT LP token id - */ - function unstake( - address _rewardToken, - uint256 _startTime, - uint256 _endTime, - address _refundee, - uint256 _tokenId - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - address poolAddr = getPoolAddress(_tokenId); - - IUniswapV3Pool pool = IUniswapV3Pool(poolAddr); - IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker - .IncentiveKey( - IERC20Minimal(_rewardToken), - pool, - _startTime, - _endTime, - _refundee - ); - _unstake(_key, _tokenId); - _eventName = "LogUnstake(uint256,bytes32)"; - _eventParam = abi.encode(_tokenId, keccak256(abi.encode(_key))); - } - - /** - * @dev Claim rewards - * @notice Claim rewards - * @param _rewardToken _rewardToken address - * @param _amount requested amount - */ - function claimRewards( - address _rewardToken, - uint256 _amount - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - uint256 rewards = _claimRewards( - IERC20Minimal(_rewardToken), - address(this), - _amount - ); - - _eventName = "LogRewardClaimed(address,uint256)"; - _eventParam = abi.encode(_rewardToken, rewards); - } - - /** - * @dev Create incentive - * @notice Create incentive - * @param _rewardToken _rewardToken address - * @param _length incentive length - * @param _refundee refundee address - * @param _poolAddr Uniswap V3 Pool address - * @param _reward reward amount - */ - function createIncentive( - address _rewardToken, - uint256 _length, - address _refundee, - address _poolAddr, - uint256 _reward - ) - external - payable - returns (string memory _eventName, bytes memory _eventParam) - { - IUniswapV3Pool pool = IUniswapV3Pool(_poolAddr); - uint256 _startTime = block.timestamp; - uint256 _endTime = _startTime + _length; - IUniswapV3Staker.IncentiveKey memory _key = IUniswapV3Staker - .IncentiveKey( - IERC20Minimal(_rewardToken), - pool, - _startTime, - _endTime, - _refundee - ); - if (_rewardToken != maticAddr) { - IERC20Minimal(_rewardToken).approve(address(staker), _reward); - } - staker.createIncentive(_key, _reward); - - _eventName = "LogIncentiveCreated(bytes32,address,address,uint256,uint256,uint256)"; - _eventParam = abi.encode(keccak256(abi.encode(_key)), _poolAddr, _refundee, _startTime, _endTime, _reward); - } -} - -contract ConnectV2UniswapV3StakerPolygon is UniswapResolver { - string public constant name = "Uniswap-V3-Staker-v1.1"; -} From db1daad2f2109051014a26543be9191f49417aad Mon Sep 17 00:00:00 2001 From: bhavik Date: Thu, 23 Dec 2021 01:04:05 +0530 Subject: [PATCH 29/31] changed contract name --- contracts/arbitrum/connectors/1inch/1inch-v4/main.sol | 2 +- contracts/mainnet/connectors/1inch/1inch-v4/main.sol | 2 +- contracts/polygon/connectors/1inch/1inch-v4/main.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol b/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol index 84c82ded..da9805e8 100644 --- a/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol +++ b/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol @@ -107,6 +107,6 @@ abstract contract OneInch is OneInchResolverHelpers { } } -contract ConnectV2OneInchArbitrum is OneInch { +contract ConnectV2OneInchV4Arbitrum is OneInch { string public name = "1Inch-v4-v1.0"; } diff --git a/contracts/mainnet/connectors/1inch/1inch-v4/main.sol b/contracts/mainnet/connectors/1inch/1inch-v4/main.sol index 9d67847c..27d4ef49 100644 --- a/contracts/mainnet/connectors/1inch/1inch-v4/main.sol +++ b/contracts/mainnet/connectors/1inch/1inch-v4/main.sol @@ -106,6 +106,6 @@ abstract contract OneInch is OneInchResolverHelpers { } } -contract ConnectV2OneInch is OneInch { +contract ConnectV2OneInchV4 is OneInch { string public name = "1Inch-v4-v1.0"; } diff --git a/contracts/polygon/connectors/1inch/1inch-v4/main.sol b/contracts/polygon/connectors/1inch/1inch-v4/main.sol index c4b35c79..ca33f669 100644 --- a/contracts/polygon/connectors/1inch/1inch-v4/main.sol +++ b/contracts/polygon/connectors/1inch/1inch-v4/main.sol @@ -110,6 +110,6 @@ abstract contract OneInch is OneInchResolverHelpers { } } -contract ConnectV2OneInchPolygon is OneInch { +contract ConnectV2OneInchV4Polygon is OneInch { string public name = "1Inch-v4-v1"; } From 4a1dd038e00e6422eb58945b9cedb9c86b48a799 Mon Sep 17 00:00:00 2001 From: 0xBhavik <62445791+bhavik-m@users.noreply.github.com> Date: Thu, 23 Dec 2021 00:55:40 +0530 Subject: [PATCH 30/31] Update contracts/polygon/connectors/1inch/1inch-v4/main.sol Co-authored-by: Thrilok kumar --- contracts/polygon/connectors/1inch/1inch-v4/main.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/polygon/connectors/1inch/1inch-v4/main.sol b/contracts/polygon/connectors/1inch/1inch-v4/main.sol index ca33f669..0936dfb7 100644 --- a/contracts/polygon/connectors/1inch/1inch-v4/main.sol +++ b/contracts/polygon/connectors/1inch/1inch-v4/main.sol @@ -79,8 +79,8 @@ abstract contract OneInch is OneInchResolverHelpers { /** * @dev Sell ETH/ERC20_Token using 1Inch. * @notice Swap tokens from exchanges like kyber, 0x etc, with calculation done off-chain. - * @param buyAddr The address of the token to buy.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr The address of the token to sell.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmt The amount of buyAmt/sellAmt with slippage. * @param callData Data from 1inch API. From e8124f434a3030bf4152b5c94547b260d751e7cd Mon Sep 17 00:00:00 2001 From: bhavik Date: Thu, 23 Dec 2021 01:29:20 +0530 Subject: [PATCH 31/31] updated @title and contract name --- contracts/arbitrum/connectors/1inch/1inch-v3/main.sol | 4 ++-- contracts/arbitrum/connectors/1inch/1inch-v4/main.sol | 2 +- contracts/mainnet/connectors/1inch/1inch-v3/main.sol | 4 ++-- contracts/mainnet/connectors/1inch/1inch-v4/main.sol | 2 +- contracts/polygon/connectors/1inch/1inch-v3/main.sol | 4 ++-- contracts/polygon/connectors/1inch/1inch-v4/main.sol | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/arbitrum/connectors/1inch/1inch-v3/main.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/main.sol index 7adef93c..fb8865d6 100644 --- a/contracts/arbitrum/connectors/1inch/1inch-v3/main.sol +++ b/contracts/arbitrum/connectors/1inch/1inch-v3/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; /** - * @title 1Inch. + * @title 1InchV3. * @dev On-chain DEX Aggregator. */ @@ -123,6 +123,6 @@ abstract contract OneInch is OneInchResolverHelpers { } } -contract ConnectV2OneInchArbitrum is OneInch { +contract ConnectV2OneInchV3Arbitrum is OneInch { string public name = "1Inch-v1.0"; } diff --git a/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol b/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol index da9805e8..8b31a8be 100644 --- a/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol +++ b/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; /** - * @title 1Inch. + * @title 1InchV4. * @dev On-chain DEX Aggregator. */ diff --git a/contracts/mainnet/connectors/1inch/1inch-v3/main.sol b/contracts/mainnet/connectors/1inch/1inch-v3/main.sol index 7f1622b6..bbe3bb8e 100644 --- a/contracts/mainnet/connectors/1inch/1inch-v3/main.sol +++ b/contracts/mainnet/connectors/1inch/1inch-v3/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; /** - * @title 1Inch. + * @title 1InchV3. * @dev On-chain DEX Aggregator. */ @@ -123,6 +123,6 @@ abstract contract OneInch is OneInchResolverHelpers { } } -contract ConnectV2OneInch is OneInch { +contract ConnectV2OneInchV3 is OneInch { string public name = "1Inch-v1.2"; } diff --git a/contracts/mainnet/connectors/1inch/1inch-v4/main.sol b/contracts/mainnet/connectors/1inch/1inch-v4/main.sol index 27d4ef49..da250e23 100644 --- a/contracts/mainnet/connectors/1inch/1inch-v4/main.sol +++ b/contracts/mainnet/connectors/1inch/1inch-v4/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; /** - * @title 1Inch. + * @title 1InchV4. * @dev On-chain DEX Aggregator. */ diff --git a/contracts/polygon/connectors/1inch/1inch-v3/main.sol b/contracts/polygon/connectors/1inch/1inch-v3/main.sol index 38a720c0..4cc9084d 100644 --- a/contracts/polygon/connectors/1inch/1inch-v3/main.sol +++ b/contracts/polygon/connectors/1inch/1inch-v3/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; /** - * @title 1Inch. + * @title 1InchV3. * @dev On-chain DEX Aggregator. */ @@ -123,6 +123,6 @@ abstract contract OneInch is OneInchResolverHelpers { } } -contract ConnectV2OneInchPolygon is OneInch { +contract ConnectV2OneInchV3Polygon is OneInch { string public name = "1Inch-v1"; } diff --git a/contracts/polygon/connectors/1inch/1inch-v4/main.sol b/contracts/polygon/connectors/1inch/1inch-v4/main.sol index 0936dfb7..84265716 100644 --- a/contracts/polygon/connectors/1inch/1inch-v4/main.sol +++ b/contracts/polygon/connectors/1inch/1inch-v4/main.sol @@ -2,7 +2,7 @@ pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; /** - * @title 1Inch. + * @title 1InchV4. * @dev On-chain DEX Aggregator. */