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/mainnet/connectors/1inch/helpers.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/helpers.sol
similarity index 71%
rename from contracts/mainnet/connectors/1inch/helpers.sol
rename to contracts/arbitrum/connectors/1inch/1inch-v3/helpers.sol
index 41cc4b0d..f52848e6 100644
--- a/contracts/mainnet/connectors/1inch/helpers.sol
+++ b/contracts/arbitrum/connectors/1inch/1inch-v3/helpers.sol
@@ -1,8 +1,8 @@
pragma solidity ^0.7.0;
-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";
abstract contract Helpers is DSMath, Basic {
diff --git a/contracts/polygon/connectors/1inch/interface.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/interface.sol
similarity index 90%
rename from contracts/polygon/connectors/1inch/interface.sol
rename to contracts/arbitrum/connectors/1inch/1inch-v3/interface.sol
index f35b9277..d2d790b7 100644
--- a/contracts/polygon/connectors/1inch/interface.sol
+++ b/contracts/arbitrum/connectors/1inch/1inch-v3/interface.sol
@@ -1,6 +1,6 @@
pragma solidity ^0.7.0;
-import { TokenInterface } from "../../common/interfaces.sol";
+import { TokenInterface } from "../../../common/interfaces.sol";
interface OneInchInterace {
function swap(
diff --git a/contracts/arbitrum/connectors/1inch/main.sol b/contracts/arbitrum/connectors/1inch/1inch-v3/main.sol
similarity index 95%
rename from contracts/arbitrum/connectors/1inch/main.sol
rename to contracts/arbitrum/connectors/1inch/1inch-v3/main.sol
index 7adef93c..4db92ebe 100644
--- a/contracts/arbitrum/connectors/1inch/main.sol
+++ b/contracts/arbitrum/connectors/1inch/1inch-v3/main.sol
@@ -2,13 +2,13 @@ pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
- * @title 1Inch.
+ * @title 1InchV3.
* @dev On-chain DEX Aggregator.
*/
// import files from common directory
-import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol";
-import { Stores } from "../../common/stores.sol";
+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";
@@ -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/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..0a8f1fda
--- /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/arbitrum/connectors/1inch/interface.sol b/contracts/arbitrum/connectors/1inch/1inch-v4/interface.sol
similarity index 90%
rename from contracts/arbitrum/connectors/1inch/interface.sol
rename to contracts/arbitrum/connectors/1inch/1inch-v4/interface.sol
index f35b9277..d2d790b7 100644
--- a/contracts/arbitrum/connectors/1inch/interface.sol
+++ b/contracts/arbitrum/connectors/1inch/1inch-v4/interface.sol
@@ -1,6 +1,6 @@
pragma solidity ^0.7.0;
-import { TokenInterface } from "../../common/interfaces.sol";
+import { TokenInterface } from "../../../common/interfaces.sol";
interface OneInchInterace {
function swap(
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..65e733a8
--- /dev/null
+++ b/contracts/arbitrum/connectors/1inch/1inch-v4/main.sol
@@ -0,0 +1,112 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+/**
+ * @title 1InchV4.
+ * @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 ConnectV2OneInchV4Arbitrum is OneInch {
+ string public name = "1Inch-v4";
+}
diff --git a/contracts/avalanche/connectors/paraswap/helpers.sol b/contracts/avalanche/connectors/paraswap/helpers.sol
index 861f3760..7e7032a3 100644
--- a/contracts/avalanche/connectors/paraswap/helpers.sol
+++ b/contracts/avalanche/connectors/paraswap/helpers.sol
@@ -17,7 +17,7 @@ abstract contract Helpers is DSMath, Basic {
address internal constant paraswap =
0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57;
-
+
function _swapHelper(SwapData memory swapData, uint256 wavaxAmt)
internal
returns (uint256 buyAmt)
diff --git a/contracts/avalanche/connectors/paraswap/main.sol b/contracts/avalanche/connectors/paraswap/main.sol
index 216e9c7c..1f1b163f 100644
--- a/contracts/avalanche/connectors/paraswap/main.sol
+++ b/contracts/avalanche/connectors/paraswap/main.sol
@@ -50,6 +50,6 @@ abstract contract ParaswapResolver is Helpers {
}
}
-contract ConnectV2ParaswapAvalanche is ParaswapResolver {
- string public constant name = "Paraswap-v1";
+contract ConnectV2ParaswapV5Avalanche is ParaswapResolver {
+ string public constant name = "Paraswap-v5";
}
\ No newline at end of file
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/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/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/arbitrum/connectors/1inch/helpers.sol b/contracts/mainnet/connectors/1inch/1inch-v3/helpers.sol
similarity index 71%
rename from contracts/arbitrum/connectors/1inch/helpers.sol
rename to contracts/mainnet/connectors/1inch/1inch-v3/helpers.sol
index 41cc4b0d..f52848e6 100644
--- a/contracts/arbitrum/connectors/1inch/helpers.sol
+++ b/contracts/mainnet/connectors/1inch/1inch-v3/helpers.sol
@@ -1,8 +1,8 @@
pragma solidity ^0.7.0;
-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";
abstract contract Helpers is DSMath, Basic {
diff --git a/contracts/mainnet/connectors/1inch/interface.sol b/contracts/mainnet/connectors/1inch/1inch-v3/interface.sol
similarity index 90%
rename from contracts/mainnet/connectors/1inch/interface.sol
rename to contracts/mainnet/connectors/1inch/1inch-v3/interface.sol
index f35b9277..d2d790b7 100644
--- a/contracts/mainnet/connectors/1inch/interface.sol
+++ b/contracts/mainnet/connectors/1inch/1inch-v3/interface.sol
@@ -1,6 +1,6 @@
pragma solidity ^0.7.0;
-import { TokenInterface } from "../../common/interfaces.sol";
+import { TokenInterface } from "../../../common/interfaces.sol";
interface OneInchInterace {
function swap(
diff --git a/contracts/mainnet/connectors/1inch/main.sol b/contracts/mainnet/connectors/1inch/1inch-v3/main.sol
similarity index 91%
rename from contracts/mainnet/connectors/1inch/main.sol
rename to contracts/mainnet/connectors/1inch/1inch-v3/main.sol
index bf215788..c4a95203 100644
--- a/contracts/mainnet/connectors/1inch/main.sol
+++ b/contracts/mainnet/connectors/1inch/1inch-v3/main.sol
@@ -2,13 +2,13 @@ pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
- * @title 1Inch.
+ * @title 1InchV3.
* @dev On-chain DEX Aggregator.
*/
// import files from common directory
-import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol";
-import { Stores } from "../../common/stores.sol";
+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";
@@ -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
* @param setId ID stores the amount of token brought.
*/
function sell(
@@ -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/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..b569d2d6
--- /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..d2d790b7
--- /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..a7b1d929
--- /dev/null
+++ b/contracts/mainnet/connectors/1inch/1inch-v4/main.sol
@@ -0,0 +1,111 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+/**
+ * @title 1InchV4.
+ * @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 ConnectV2OneInchV4 is OneInch {
+ string public name = "1Inch-v4";
+}
diff --git a/contracts/mainnet/connectors/sushi-incentive/events.sol b/contracts/mainnet/connectors/sushi-incentive/events.sol
new file mode 100644
index 00000000..aa1c890d
--- /dev/null
+++ b/contracts/mainnet/connectors/sushi-incentive/events.sol
@@ -0,0 +1,31 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+ event LogDeposit(
+ uint256 indexed pid,
+ uint256 indexed version,
+ uint256 amount
+ );
+ event LogWithdraw(
+ uint256 indexed pid,
+ uint256 indexed version,
+ uint256 amount
+ );
+ event LogEmergencyWithdraw(
+ uint256 indexed pid,
+ uint256 indexed version,
+ uint256 lpAmount,
+ uint256 rewardsAmount
+ );
+ event LogHarvest(
+ uint256 indexed pid,
+ uint256 indexed version,
+ uint256 amount
+ );
+ event LogWithdrawAndHarvest(
+ 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..ba3b1c6c
--- /dev/null
+++ b/contracts/mainnet/connectors/sushi-incentive/interface.sol
@@ -0,0 +1,117 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+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 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);
+
+ 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..cc448434
--- /dev/null
+++ b/contracts/mainnet/connectors/sushi-incentive/main.sol
@@ -0,0 +1,174 @@
+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
+ * @notice 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
+ 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,
+ 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);
+ _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
+ * @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
+ 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);
+ _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
+ */
+ function harvest(
+ address token1,
+ address token2,
+ uint256 setId
+ )
+ 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);
+ _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
+ * @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
+ 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);
+ _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
+ */
+ function emergencyWithdraw(
+ address token1,
+ address token2,
+ uint256 setId
+ )
+ 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 lpAmount, uint256 rewardsAmount) = _getUserInfo(
+ _pid,
+ _version
+ );
+ _emergencyWithdraw(_pid, _version);
+ _eventName = "LogEmergencyWithdraw(uint256,uint256,uint256,uint256)";
+ _eventParam = abi.encode(_pid, _version, lpAmount, rewardsAmount);
+ }
+}
+
+contract ConnectV2SushiswapIncentive is SushipswapIncentiveResolver {
+ string public constant name = "SushipswapIncentive-v1.1";
+}
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..ea29a03f
--- /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,
+ 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 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/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 71%
rename from contracts/polygon/connectors/1inch/helpers.sol
rename to contracts/polygon/connectors/1inch/1inch-v3/helpers.sol
index 41cc4b0d..f52848e6 100644
--- a/contracts/polygon/connectors/1inch/helpers.sol
+++ b/contracts/polygon/connectors/1inch/1inch-v3/helpers.sol
@@ -1,8 +1,8 @@
pragma solidity ^0.7.0;
-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";
abstract contract Helpers is DSMath, Basic {
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..d2d790b7
--- /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 95%
rename from contracts/polygon/connectors/1inch/main.sol
rename to contracts/polygon/connectors/1inch/1inch-v3/main.sol
index 38a720c0..086bb191 100644
--- a/contracts/polygon/connectors/1inch/main.sol
+++ b/contracts/polygon/connectors/1inch/1inch-v3/main.sol
@@ -2,13 +2,13 @@ pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/**
- * @title 1Inch.
+ * @title 1InchV3.
* @dev On-chain DEX Aggregator.
*/
// import files from common directory
-import { TokenInterface , MemoryInterface } from "../../common/interfaces.sol";
-import { Stores } from "../../common/stores.sol";
+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";
@@ -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/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..b569d2d6
--- /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..d2d790b7
--- /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..40db7077
--- /dev/null
+++ b/contracts/polygon/connectors/1inch/1inch-v4/main.sol
@@ -0,0 +1,115 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+/**
+ * @title 1InchV4.
+ * @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 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.
+ * @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 ConnectV2OneInchV4Polygon is OneInch {
+ string public name = "1Inch-v4-v1";
+}
diff --git a/contracts/polygon/connectors/paraswap/helpers.sol b/contracts/polygon/connectors/paraswap/helpers.sol
index 0f0bc803..9da20913 100644
--- a/contracts/polygon/connectors/paraswap/helpers.sol
+++ b/contracts/polygon/connectors/paraswap/helpers.sol
@@ -16,7 +16,7 @@ abstract contract Helpers is DSMath, Basic {
bytes callData;
}
- address internal constant paraswap = 0x90249ed4d69D70E709fFCd8beE2c5A566f65dADE;
+ address internal constant paraswap = 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57;
function _swapHelper(SwapData memory swapData, uint256 wmaticAmt) internal returns (uint256 buyAmt) {
TokenInterface buyToken = swapData.buyToken;
diff --git a/contracts/polygon/connectors/paraswap/main.sol b/contracts/polygon/connectors/paraswap/main.sol
index 2041c11c..76add82a 100644
--- a/contracts/polygon/connectors/paraswap/main.sol
+++ b/contracts/polygon/connectors/paraswap/main.sol
@@ -50,6 +50,6 @@ abstract contract ParaswapResolver is Helpers {
}
}
-contract ConnectV2Paraswap is ParaswapResolver {
- string public name = "Paraswap-v1";
+contract ConnectV2ParaswapV5Polygon is ParaswapResolver {
+ string public name = "Paraswap-v5";
}
\ No newline at end of file
diff --git a/contracts/polygon/connectors/quickswap/events.sol b/contracts/polygon/connectors/quickswap/events.sol
new file mode 100644
index 00000000..9e01ef9d
--- /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
+ );
+}
diff --git a/contracts/polygon/connectors/quickswap/helpers.sol b/contracts/polygon/connectors/quickswap/helpers.sol
new file mode 100644
index 00000000..594b56e1
--- /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(0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff);
+
+ 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,
+ 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);
+
+ 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..bd210215
--- /dev/null
+++ b/contracts/polygon/connectors/quickswap/interface.sol
@@ -0,0 +1,97 @@
+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,
+ 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 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(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/polygon/connectors/quickswap/main.sol b/contracts/polygon/connectors/quickswap/main.sol
new file mode 100644
index 00000000..404b6be0
--- /dev/null
+++ b/contracts/polygon/connectors/quickswap/main.sol
@@ -0,0 +1,256 @@
+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)
+ {
+ uint256 _amt = getUint(getId, amtA);
+
+ (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
+ );
+ }
+
+ /**
+ * @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
+ );
+
+ 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)
+ {
+ 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))
+ );
+
+ 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);
+
+ uint256 _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)
+ {
+ 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));
+ }
+
+ uint256 _slippageAmt = convert18ToDec(
+ _buyAddr.decimals(),
+ wmul(unitAmt, convertTo18(_sellAddr.decimals(), _sellAmt))
+ );
+
+ 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);
+
+ uint256 _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 ConnectV2QuickswapPolygon is QuickpswapResolver {
+ string public constant name = "Quickpswap-v1.1";
+}
diff --git a/contracts/polygon/connectors/uniswap/v3/events.sol b/contracts/polygon/connectors/uniswap/v3/events.sol
new file mode 100644
index 00000000..b464e28e
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3/events.sol
@@ -0,0 +1,42 @@
+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,
+ uint256 amtA,
+ uint256 amtB,
+ int24 tickLower,
+ int24 tickUpper
+ );
+
+ event LogDeposit(
+ uint256 indexed tokenId,
+ uint256 liquidity,
+ uint256 amountA,
+ uint256 amountB
+ );
+
+ event LogWithdraw(
+ uint256 indexed tokenId,
+ uint256 liquidity,
+ uint256 amountA,
+ uint256 amountB
+ );
+
+ event LogCollect(
+ uint256 tokenId,
+ uint256 amountA,
+ uint256 amountB
+ );
+
+ event LogBurnPosition(uint256 tokenId);
+}
diff --git a/contracts/polygon/connectors/uniswap/v3/helpers.sol b/contracts/polygon/connectors/uniswap/v3/helpers.sol
new file mode 100644
index 00000000..f1ae3324
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3/helpers.sol
@@ -0,0 +1,308 @@
+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 "./interface.sol";
+import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
+import "@uniswap/v3-core/contracts/libraries/TickMath.sol";
+import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
+import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
+
+abstract contract Helpers is DSMath, Basic {
+ /**
+ * @dev uniswap v3 NFT Position Manager & Swap Router
+ */
+ INonfungiblePositionManager constant nftManager =
+ INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
+ ISwapRouter constant swapRouter =
+ ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
+
+ struct MintParams {
+ address tokenA;
+ address tokenB;
+ uint24 fee;
+ int24 tickLower;
+ int24 tickUpper;
+ uint256 amtA;
+ uint256 amtB;
+ uint256 slippage;
+ }
+
+ /**
+ * @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 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 sortTokenAddress(address _token0, address _token1)
+ internal
+ view
+ returns (address token0, address token1)
+ {
+ if (_token0 > _token1) {
+ (token0, token1) = (_token1, _token0);
+ } else {
+ (token0, token1) = (_token0, _token1);
+ }
+ }
+
+ function _createAndInitializePoolIfNecessary (
+ address tokenA,
+ address tokenB,
+ uint24 fee,
+ int24 initialTick
+ ) internal returns (address pool) {
+ (TokenInterface token0Contract_, TokenInterface token1Contract_) = changeMaticAddress(
+ tokenA,
+ tokenB
+ );
+
+ (address token0_, address token1_) = sortTokenAddress(address(token0Contract_), address(token1Contract_));
+
+ return nftManager.createAndInitializePoolIfNecessary(
+ token0_,
+ token1_,
+ fee,
+ TickMath.getSqrtRatioAtTick(initialTick)
+ );
+ }
+
+ /**
+ * @dev Mint function which interact with Uniswap v3
+ */
+ function _mint(MintParams memory params)
+ internal
+ returns (
+ uint256 tokenId,
+ uint128 liquidity,
+ uint256 amountA,
+ uint256 amountB
+ )
+ {
+ (TokenInterface _token0, TokenInterface _token1) = changeMaticAddress(
+ params.tokenA,
+ params.tokenB
+ );
+
+ uint256 _amount0 = params.amtA == uint256(-1)
+ ? getTokenBal(TokenInterface(params.tokenA))
+ : params.amtA;
+ uint256 _amount1 = params.amtB == uint256(-1)
+ ? getTokenBal(TokenInterface(params.tokenB))
+ : params.amtB;
+
+ convertMaticToWmatic(address(_token0) == wmaticAddr, _token0, _amount0);
+ convertMaticToWmatic(address(_token1) == wmaticAddr, _token1, _amount1);
+
+ approve(_token0, address(nftManager), _amount0);
+ approve(_token1, address(nftManager), _amount1);
+
+ {
+ (address token0, ) = sortTokenAddress(
+ address(_token0),
+ address(_token1)
+ );
+
+ if (token0 != address(_token0)) {
+ (_token0, _token1) = (_token1, _token0);
+ (_amount0, _amount1) = (_amount1, _amount0);
+ }
+ }
+ uint256 _minAmt0 = getMinAmount(_token0, _amount0, params.slippage);
+ uint256 _minAmt1 = getMinAmount(_token1, _amount1, params.slippage);
+
+ INonfungiblePositionManager.MintParams
+ memory params = INonfungiblePositionManager.MintParams(
+ address(_token0),
+ address(_token1),
+ params.fee,
+ params.tickLower,
+ params.tickUpper,
+ _amount0,
+ _amount1,
+ _minAmt0,
+ _minAmt1,
+ address(this),
+ block.timestamp
+ );
+
+ (tokenId, liquidity, amountA, amountB) = nftManager.mint(params);
+ }
+
+ function getNftTokenPairAddresses(uint256 _tokenId)
+ internal
+ view
+ returns (address token0, address token1)
+ {
+ (bool success, bytes memory data) = address(nftManager).staticcall(
+ abi.encodeWithSelector(nftManager.positions.selector, _tokenId)
+ );
+ require(success, "fetching positions failed");
+ {
+ (, , token0, token1, , , , ) = abi.decode(
+ data,
+ (
+ uint96,
+ address,
+ address,
+ address,
+ uint24,
+ int24,
+ int24,
+ uint128
+ )
+ );
+ }
+ }
+
+ /**
+ * @dev Check if token address is maticAddr and convert it to wmatic
+ */
+ function _checkMATIC(
+ address _token0,
+ address _token1,
+ uint256 _amount0,
+ uint256 _amount1
+ ) internal {
+ bool isMatic0 = _token0 == wmaticAddr;
+ bool isMatic1 = _token1 == wmaticAddr;
+ convertMaticToWmatic(isMatic0, TokenInterface(_token0), _amount0);
+ convertMaticToWmatic(isMatic1, TokenInterface(_token1), _amount1);
+ approve(TokenInterface(_token0), address(nftManager), _amount0);
+ approve(TokenInterface(_token1), address(nftManager), _amount1);
+ }
+
+ /**
+ * @dev addLiquidityWrapper function wrapper of _addLiquidity
+ */
+ function _addLiquidityWrapper(
+ uint256 tokenId,
+ uint256 amountA,
+ uint256 amountB,
+ uint256 slippage
+ )
+ internal
+ returns (
+ uint256 liquidity,
+ uint256 amtA,
+ uint256 amtB
+ )
+ {
+ (address token0, address token1) = getNftTokenPairAddresses(tokenId);
+
+ (liquidity, amtA, amtB) = _addLiquidity(
+ tokenId,
+ token0,
+ token1,
+ amountA,
+ amountB,
+ slippage
+ );
+ }
+
+ /**
+ * @dev addLiquidity function which interact with Uniswap v3
+ */
+ function _addLiquidity(
+ uint256 _tokenId,
+ address _token0,
+ address _token1,
+ uint256 _amount0,
+ uint256 _amount1,
+ uint256 _slippage
+ )
+ internal
+ returns (
+ uint128 liquidity,
+ uint256 amount0,
+ uint256 amount1
+ )
+ {
+ _checkMATIC(_token0, _token1, _amount0, _amount1);
+ uint256 _amount0Min = getMinAmount(
+ TokenInterface(_token0),
+ _amount0,
+ _slippage
+ );
+ uint256 _amount1Min = getMinAmount(
+ TokenInterface(_token1),
+ _amount1,
+ _slippage
+ );
+ INonfungiblePositionManager.IncreaseLiquidityParams
+ memory params = INonfungiblePositionManager.IncreaseLiquidityParams(
+ _tokenId,
+ _amount0,
+ _amount1,
+ _amount0Min,
+ _amount1Min,
+ block.timestamp
+ );
+
+ (liquidity, amount0, amount1) = nftManager.increaseLiquidity(params);
+ }
+
+ /**
+ * @dev decreaseLiquidity function which interact with Uniswap v3
+ */
+ function _decreaseLiquidity(
+ uint256 _tokenId,
+ uint128 _liquidity,
+ uint256 _amount0Min,
+ uint256 _amount1Min
+ ) internal returns (uint256 amount0, uint256 amount1) {
+ INonfungiblePositionManager.DecreaseLiquidityParams
+ memory params = INonfungiblePositionManager.DecreaseLiquidityParams(
+ _tokenId,
+ _liquidity,
+ _amount0Min,
+ _amount1Min,
+ block.timestamp
+ );
+ (amount0, amount1) = nftManager.decreaseLiquidity(params);
+ }
+
+ /**
+ * @dev collect function which interact with Uniswap v3
+ */
+ function _collect(
+ uint256 _tokenId,
+ uint128 _amount0Max,
+ uint128 _amount1Max
+ ) internal returns (uint256 amount0, uint256 amount1) {
+ INonfungiblePositionManager.CollectParams
+ memory params = INonfungiblePositionManager.CollectParams(
+ _tokenId,
+ address(this),
+ _amount0Max,
+ _amount1Max
+ );
+ (amount0, amount1) = nftManager.collect(params);
+ }
+
+ /**
+ * @dev Burn Function
+ */
+ function _burn(uint256 _tokenId) internal {
+ nftManager.burn(_tokenId);
+ }
+}
diff --git a/contracts/polygon/connectors/uniswap/v3/interface.sol b/contracts/polygon/connectors/uniswap/v3/interface.sol
new file mode 100644
index 00000000..f8bc6e84
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3/interface.sol
@@ -0,0 +1,368 @@
+pragma solidity ^0.7.6;
+pragma abicoder v2;
+
+import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
+import "@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol";
+import "@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol";
+
+/// @title Callback for IUniswapV3PoolActions#swap
+/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
+interface IUniswapV3SwapCallback {
+ /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
+ /// @dev In the implementation you must pay the pool tokens owed for the swap.
+ /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
+ /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
+ /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
+ /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
+ /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
+ /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
+ /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
+ function uniswapV3SwapCallback(
+ int256 amount0Delta,
+ int256 amount1Delta,
+ bytes calldata data
+ ) external;
+}
+
+interface ISwapRouter is IUniswapV3SwapCallback {
+ struct ExactInputSingleParams {
+ address tokenIn;
+ address tokenOut;
+ uint24 fee;
+ address recipient;
+ uint256 deadline;
+ uint256 amountIn;
+ uint256 amountOutMinimum;
+ uint160 sqrtPriceLimitX96;
+ }
+
+ /// @notice Swaps `amountIn` of one token for as much as possible of another token
+ /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
+ /// @return amountOut The amount of the received token
+ function exactInputSingle(ExactInputSingleParams calldata params)
+ external
+ payable
+ returns (uint256 amountOut);
+
+ struct ExactInputParams {
+ bytes path;
+ address recipient;
+ uint256 deadline;
+ uint256 amountIn;
+ uint256 amountOutMinimum;
+ }
+
+ /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
+ /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
+ /// @return amountOut The amount of the received token
+ function exactInput(ExactInputParams calldata params)
+ external
+ payable
+ returns (uint256 amountOut);
+
+ struct ExactOutputSingleParams {
+ address tokenIn;
+ address tokenOut;
+ uint24 fee;
+ address recipient;
+ uint256 deadline;
+ uint256 amountOut;
+ uint256 amountInMaximum;
+ uint160 sqrtPriceLimitX96;
+ }
+
+ /// @notice Swaps as little as possible of one token for `amountOut` of another token
+ /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
+ /// @return amountIn The amount of the input token
+ function exactOutputSingle(ExactOutputSingleParams calldata params)
+ external
+ payable
+ returns (uint256 amountIn);
+
+ struct ExactOutputParams {
+ bytes path;
+ address recipient;
+ uint256 deadline;
+ uint256 amountOut;
+ uint256 amountInMaximum;
+ }
+
+ /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
+ /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
+ /// @return amountIn The amount of the input token
+ function exactOutput(ExactOutputParams calldata params)
+ external
+ payable
+ returns (uint256 amountIn);
+}
+
+/// @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);
+}
+
+/// @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);
+}
+
+/// @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;
+}
+
+/// @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;
+}
+
+/// @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;
+}
diff --git a/contracts/polygon/connectors/uniswap/v3/main.sol b/contracts/polygon/connectors/uniswap/v3/main.sol
new file mode 100644
index 00000000..4cb74195
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3/main.sol
@@ -0,0 +1,247 @@
+pragma solidity ^0.7.6;
+pragma abicoder v2;
+
+/**
+ * @title Uniswap v3.
+ * @dev Decentralized Exchange.
+ */
+
+import {TokenInterface} from "../../../common/interfaces.sol";
+import {Helpers} from "./helpers.sol";
+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,
+ uint24 fee,
+ int24 initialTick
+ )
+ external
+ payable
+ returns (string memory _eventName, bytes memory _eventParam)
+ {
+
+ 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
+ * @param tokenA tokenA addreess
+ * @param tokenB tokenB addreess
+ * @param fee fee percentage
+ * @param tickLower Lower tick
+ * @param tickUpper Upper tick
+ * @param amtA amount of tokenA
+ * @param amtB amount of tokenB
+ * @param slippage slippage percentage
+ * @param getIds ID to retrieve amtA
+ * @param setId ID stores the amount of LP token
+ */
+ function mint(
+ address tokenA,
+ address tokenB,
+ uint24 fee,
+ int24 tickLower,
+ int24 tickUpper,
+ uint256 amtA,
+ uint256 amtB,
+ uint256 slippage,
+ uint256[] calldata getIds,
+ uint256 setId
+ )
+ external
+ payable
+ returns (string memory _eventName, bytes memory _eventParam)
+ {
+
+ MintParams memory params;
+ {
+ params = MintParams(
+ tokenA,
+ tokenB,
+ fee,
+ tickLower,
+ tickUpper,
+ amtA,
+ amtB,
+ slippage
+ );
+ }
+ params.amtA = getUint(getIds[0], params.amtA);
+ params.amtB = getUint(getIds[1], params.amtB);
+
+ (
+ uint256 _tokenId,
+ uint256 liquidity,
+ uint256 amountA,
+ uint256 amountB
+ ) = _mint(params);
+
+ setUint(setId, liquidity);
+
+ _eventName = "LogMint(uint256,uint256,uint256,uint256,int24,int24)";
+ _eventParam = abi.encode(
+ _tokenId,
+ liquidity,
+ amountA,
+ amountB,
+ params.tickLower,
+ params.tickUpper
+ );
+ }
+
+ /**
+ * @dev Increase Liquidity
+ * @notice Increase Liquidity of NFT Position
+ * @param tokenId NFT LP Token ID.
+ * @param amountA tokenA amounts.
+ * @param amountB tokenB amounts.
+ * @param slippage slippage.
+ * @param getIds IDs to retrieve token amounts
+ * @param setId stores the liquidity amount
+ */
+ function deposit(
+ uint256 tokenId,
+ uint256 amountA,
+ uint256 amountB,
+ uint256 slippage,
+ uint256[] calldata getIds,
+ uint256 setId
+ )
+ external
+ payable
+ returns (string memory _eventName, bytes memory _eventParam)
+ {
+ if (tokenId == 0) tokenId = _getLastNftId(address(this));
+ amountA = getUint(getIds[0], amountA);
+ amountB = getUint(getIds[1], amountB);
+ (
+ uint256 _liquidity,
+ uint256 _amtA,
+ uint256 _amtB
+ ) = _addLiquidityWrapper(tokenId, amountA, amountB, slippage);
+ setUint(setId, _liquidity);
+
+ _eventName = "LogDeposit(uint256,uint256,uint256,uint256)";
+ _eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
+ }
+
+ /**
+ * @dev Decrease Liquidity
+ * @notice Decrease Liquidity of NFT Position
+ * @param tokenId NFT LP Token ID.
+ * @param liquidity LP Token amount.
+ * @param amountAMin Min amount of tokenA.
+ * @param amountBMin Min amount of tokenB.
+ * @param getId ID to retrieve LP token amounts
+ * @param setIds stores the amount of output tokens
+ */
+ function withdraw(
+ uint256 tokenId,
+ uint256 liquidity,
+ uint256 amountAMin,
+ uint256 amountBMin,
+ uint256 getId,
+ uint256[] calldata setIds
+ )
+ external
+ payable
+ returns (string memory _eventName, bytes memory _eventParam)
+ {
+ if (tokenId == 0) tokenId = _getLastNftId(address(this));
+ uint128 _liquidity = uint128(getUint(getId, liquidity));
+
+ (uint256 _amtA, uint256 _amtB) = _decreaseLiquidity(
+ tokenId,
+ _liquidity,
+ amountAMin,
+ amountBMin
+ );
+
+ setUint(setIds[0], _amtA);
+ setUint(setIds[1], _amtB);
+
+ _eventName = "LogWithdraw(uint256,uint256,uint256,uint256)";
+ _eventParam = abi.encode(tokenId, _liquidity, _amtA, _amtB);
+ }
+
+ /**
+ * @dev Collect function
+ * @notice Collect from NFT Position
+ * @param tokenId NFT LP Token ID.
+ * @param amount0Max Max amount of token0.
+ * @param amount1Max Max amount of token1.
+ * @param getIds IDs to retrieve amounts
+ * @param setIds stores the amount of output tokens
+ */
+ function collect(
+ uint256 tokenId,
+ uint256 amount0Max,
+ uint256 amount1Max,
+ uint256[] calldata getIds,
+ uint256[] calldata setIds
+ )
+ external
+ payable
+ returns (string memory _eventName, bytes memory _eventParam)
+ {
+ if (tokenId == 0) tokenId = _getLastNftId(address(this));
+ uint128 _amount0Max = uint128(getUint(getIds[0], amount0Max));
+ uint128 _amount1Max = uint128(getUint(getIds[1], amount1Max));
+ (uint256 amount0, uint256 amount1) = _collect(
+ tokenId,
+ _amount0Max,
+ _amount1Max
+ );
+
+ setUint(setIds[0], amount0);
+ setUint(setIds[1], amount1);
+ _eventName = "LogCollect(uint256,uint256,uint256)";
+ _eventParam = abi.encode(tokenId, amount0, amount1);
+ }
+
+ /**
+ * @dev Burn Function
+ * @notice Burn NFT LP Position
+ * @param tokenId NFT LP Token ID
+ */
+ function burn(uint256 tokenId)
+ external
+ payable
+ returns (string memory _eventName, bytes memory _eventParam)
+ {
+ if (tokenId == 0) tokenId = _getLastNftId(address(this));
+ _burn(tokenId);
+ _eventName = "LogBurnPosition(uint256)";
+ _eventParam = abi.encode(tokenId);
+ }
+}
+
+contract ConnectV2UniswapV3Polygon is UniswapResolver {
+ string public constant name = "UniswapV3-v1";
+}
diff --git a/contracts/polygon/connectors/uniswap/v3_staker/events.sol b/contracts/polygon/connectors/uniswap/v3_staker/events.sol
new file mode 100644
index 00000000..99b98a61
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3_staker/events.sol
@@ -0,0 +1,29 @@
+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
+ );
+}
diff --git a/contracts/polygon/connectors/uniswap/v3_staker/helpers.sol b/contracts/polygon/connectors/uniswap/v3_staker/helpers.sol
new file mode 100644
index 00000000..258d0961
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3_staker/helpers.sol
@@ -0,0 +1,87 @@
+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 "./interface.sol";
+import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
+import "@uniswap/v3-core/contracts/libraries/TickMath.sol";
+import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
+import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
+
+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);
+ }
+}
diff --git a/contracts/polygon/connectors/uniswap/v3_staker/interface.sol b/contracts/polygon/connectors/uniswap/v3_staker/interface.sol
new file mode 100644
index 00000000..5c537e43
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3_staker/interface.sol
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+pragma solidity =0.7.6;
+pragma abicoder v2;
+
+import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
+
+import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';
+import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
+import '@uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol';
+
+import '@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol';
+import '@uniswap/v3-periphery/contracts/interfaces/IMulticall.sol';
+
+/// @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);
+}
diff --git a/contracts/polygon/connectors/uniswap/v3_staker/main.sol b/contracts/polygon/connectors/uniswap/v3_staker/main.sol
new file mode 100644
index 00000000..36e79772
--- /dev/null
+++ b/contracts/polygon/connectors/uniswap/v3_staker/main.sol
@@ -0,0 +1,255 @@
+pragma solidity ^0.7.6;
+pragma abicoder v2;
+
+/**
+ * @title Uniswap v3.
+ * @dev Decentralized Exchange.
+ */
+
+import {TokenInterface} from "../../../common/interfaces.sol";
+import "./interface.sol";
+import {Helpers} from "./helpers.sol";
+import {Events} from "./events.sol";
+
+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/hardhat.config.ts b/hardhat.config.ts
index 1c102759..8c10d28f 100644
--- a/hardhat.config.ts
+++ b/hardhat.config.ts
@@ -39,6 +39,13 @@ 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),
@@ -47,7 +54,6 @@ function createConfig(network: string) {
}
function getNetworkUrl(networkType: string) {
- //console.log(process.env);
if (networkType === "avalanche")
return "https://api.avax.network/ext/bc/C/rpc";
else if (networkType === "polygon")
@@ -111,8 +117,8 @@ const config: HardhatUserConfig = {
sources: "./contracts",
tests: "./test",
},
- etherscan: {
- apiKey: getScanApiKey(getNetworkUrl(String(process.env.networkType))),
+ etherscan: {
+ apiKey: getScanApiKey(getNetworkUrl(String(process.env.networkType))),
},
typechain: {
outDir: "typechain",
diff --git a/scripts/deployment/deploy.ts b/scripts/deployment/deploy.ts
index 381fe091..a7eace0c 100644
--- a/scripts/deployment/deploy.ts
+++ b/scripts/deployment/deploy.ts
@@ -18,6 +18,11 @@ async function main() {
"GELATO-A": "ConnectV2Gelato",
"MAKERDAO-A": "ConnectV2Maker",
"UNISWAP-A": "ConnectV2UniswapV2",
+ "QUICKSWAP-A": "ConnectV2QuickswapPolygon",
+ "UniswapV3-v1" : "ConnectV2UniswapV3Polygon",
+ "Uniswap-V3-Staker-v1.1" : "ConnectV2UniswapV3StakerPolygon",
+ "Paraswap-v5" : "ConnectV2ParaswapV5Polygon"
+ "1INCH-V4" : "ConnectV2OneInchV4Polygon",
};
const addressMapping: Record = {};
diff --git a/scripts/deployment/deployConnector.ts b/scripts/deployment/deployConnector.ts
index 44e4667d..2aaea507 100644
--- a/scripts/deployment/deployConnector.ts
+++ b/scripts/deployment/deployConnector.ts
@@ -1,4 +1,4 @@
-import { ethers } from "hardhat";
+import hre, { ethers } from "hardhat";
export const deployConnector = async (connectorName: string) => {
const Connector = await ethers.getContractFactory(connectorName);
@@ -6,5 +6,17 @@ export const deployConnector = async (connectorName: string) => {
await connector.deployed();
console.log(`${connectorName} Deployed: ${connector.address}`);
+
+ try {
+ await hre.run("verify:verify", {
+ address: connector.address,
+ constructorArguments: []
+ }
+ )
+ } catch (error) {
+ console.log(`Failed to verify: ${connectorName}@${connector.address}`)
+ console.log(error)
+ console.log()
+ }
return connector.address;
};
diff --git a/test/mainnet/sushiswap/sushiswap.test.ts b/test/mainnet/sushiswap/sushiswap.test.ts
new file mode 100644
index 00000000..8c70125b
--- /dev/null
+++ b/test/mainnet/sushiswap/sushiswap.test.ts
@@ -0,0 +1,147 @@
+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();
+ });
+ });
+});
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()
+ });
+ });
+})
diff --git a/test/polygon/paraswap/paraswap.test.ts b/test/polygon/paraswap/paraswap.test.ts
new file mode 100644
index 00000000..d1bd8f04
--- /dev/null
+++ b/test/polygon/paraswap/paraswap.test.ts
@@ -0,0 +1,171 @@
+import hre from "hardhat";
+import { expect } from "chai";
+import { abis } from "../../../scripts/constant/abis";
+import { addresses } from "../../../scripts/tests/polygon/addresses";
+import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
+import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
+import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
+import {
+ ConnectV2ParaswapV5Polygon__factory
+} from "../../../typechain";
+import { encodeSpells } from "../../../scripts/tests/encodeSpells";
+import BigNumber from "bignumber.js";
+import axios from "axios";
+// import { Signer } from "ethers";
+const { waffle, ethers } = hre;
+const { provider, deployContract } = waffle;
+import type { Signer, Contract } from "ethers";
+describe("Paraswap", function() {
+ const connectorName = "paraswap-test";
+ let dsaWallet0: any;
+ let masterSigner: Signer;
+ let instaConnectorsV2: Contract;
+ let connector: any;
+ const wallets = provider.getWallets();
+ const [wallet0, wallet1] = wallets;
+ before(async () => {
+ await hre.network.provider.request({
+ method: "hardhat_reset",
+ params: [
+ {
+ forking: {
+ // @ts-ignore
+ jsonRpcUrl: hre.config.networks.hardhat.forking.url,
+ },
+ },
+ ],
+ });
+ masterSigner = await getMasterSigner();
+ instaConnectorsV2 = await ethers.getContractAt(
+ abis.core.connectorsV2,
+ addresses.core.connectorsV2
+ );
+ connector = await deployAndEnableConnector({
+ connectorName,
+ contractArtifact: ConnectV2ParaswapV5Polygon__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(!!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 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")
+ );
+ });
+ });
+ describe("Main", function() {
+ it("should swap successfully", async function() {
+ async function getArg() {
+ const slippage = 1;
+ /* matic -> USDT */
+ const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // matic, decimals 18
+ const sellTokenDecimals = 18;
+ const buyTokenAddress = "0xc2132d05d31c914a87c6611c10748aeb04b58e8f"; // USDT, decimals 6
+ const buyTokenDecimals = 6;
+ const amount = 2;
+ const srcAmount = new BigNumber(amount)
+ .times(new BigNumber(10).pow(sellTokenDecimals))
+ .toFixed(0);
+ const fromAddress = dsaWallet0.address;
+ let url = `https://apiv5.paraswap.io/prices/`;
+ let params = {
+ srcToken: sellTokenAddress,
+ destToken: buyTokenAddress,
+ srcDecimals: sellTokenDecimals,
+ destDecimals: buyTokenDecimals,
+ amount: srcAmount,
+ side: "SELL",
+ network: 137,
+ };
+
+ const priceRoute = (await axios
+ .get(url, { params: params })).data.priceRoute
+
+
+ let buyTokenAmount = priceRoute.destAmount;
+ let minAmount = new BigNumber(priceRoute.destAmount)
+ .times(1 - slippage / 100)
+ .toFixed(0);
+
+ let txConfig = {
+ priceRoute: priceRoute,
+ srcToken: sellTokenAddress,
+ destToken: buyTokenAddress,
+ srcDecimals: sellTokenDecimals,
+ destDecimals: buyTokenDecimals,
+ srcAmount: srcAmount,
+ destAmount: minAmount,
+ userAddress: fromAddress,
+ };
+ let url2 = "https://apiv5.paraswap.io/transactions/137?ignoreChecks=true";
+ const calldata = (await axios
+ .post(url2, txConfig)).data.data
+
+ function caculateUnitAmt(
+ buyAmount: any,
+ sellAmount: any,
+ buyDecimal: any,
+ sellDecimal: any,
+ maxSlippage: any
+ ) {
+ let unitAmt: any;
+ unitAmt = new BigNumber(buyAmount)
+ .dividedBy(10 ** buyDecimal)
+ .dividedBy(new BigNumber(sellAmount).dividedBy(10 ** sellDecimal));
+ unitAmt = unitAmt.multipliedBy((100 - maxSlippage) / 100);
+ unitAmt = unitAmt.multipliedBy(1e18).toFixed(0);
+ return unitAmt;
+ }
+
+ let unitAmt = caculateUnitAmt(
+ buyTokenAmount,
+ srcAmount,
+ buyTokenDecimals,
+ sellTokenDecimals,
+ 1
+ );
+
+ return [
+ buyTokenAddress,
+ sellTokenAddress,
+ srcAmount,
+ unitAmt,
+ calldata,
+ 0,
+ ];
+ }
+ let arg = await getArg();
+ const spells = [
+ {
+ connector: connectorName,
+ method: "swap",
+ args: arg,
+ },
+ ];
+ const tx = await dsaWallet0
+ .connect(wallet0)
+ .cast(...encodeSpells(spells), wallet1.address);
+ const receipt = await tx.wait();
+
+ expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(
+ ethers.utils.parseEther("8")
+ );
+ });
+ });
+});
\ No newline at end of file
diff --git a/test/polygon/quickswap/quickswap.test.ts b/test/polygon/quickswap/quickswap.test.ts
new file mode 100644
index 00000000..3d3a9346
--- /dev/null
+++ b/test/polygon/quickswap/quickswap.test.ts
@@ -0,0 +1,137 @@
+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 { ConnectV2QuickswapPolygon__factory, ConnectV2QuickswapPolygon } from "../../../typechain";
+import type { Signer, Contract } from "ethers";
+
+const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063";
+
+describe("Quickswap", function () {
+ const connectorName = "Quickswap-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: ConnectV2QuickswapPolygon__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("10000"));
+ });
+ });
+
+ 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";
+
+ 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.001"); // 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/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"