Merge branch 'main' into feat/0x

This commit is contained in:
0xPradyuman 2022-01-06 12:38:27 +05:30 committed by GitHub
commit e35b3d41e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 5633 additions and 85 deletions

22
.prettierrc Normal file
View File

@ -0,0 +1,22 @@
{
"printWidth": 120,
"singleQuote": false,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "none",
"semi": true,
"plugins": ["./node_modules/prettier-plugin-solidity"],
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 80,
"tabWidth": 4,
"useTabs": true,
"singleQuote": false,
"bracketSpacing": true,
"explicitTypes": "always"
}
}
]
}

View File

@ -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 {

View File

@ -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(

View File

@ -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";
}

View File

@ -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;
}

View File

@ -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(

View File

@ -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";
}

View File

@ -18,7 +18,7 @@ abstract contract Helpers is DSMath, Basic {
address internal constant paraswap = 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57;
function _swapHelper(SwapData memory swapData, uint256 wmaticAmt) internal returns (uint256 buyAmt) {
function _swapHelper(SwapData memory swapData, uint256 wavaxAmt) internal returns (uint256 buyAmt) {
TokenInterface buyToken = swapData.buyToken;
(uint256 _buyDec, uint256 _sellDec) = getTokensDec(buyToken, swapData.sellToken);
uint256 _sellAmt18 = convertTo18(_sellDec, swapData._sellAmt);
@ -26,7 +26,7 @@ abstract contract Helpers is DSMath, Basic {
uint256 initalBal = getTokenBal(buyToken);
(bool success, ) = paraswap.call{value: wmaticAmt}(swapData.callData);
(bool success, ) = paraswap.call{value: wavaxAmt}(swapData.callData);
if (!success) revert("paraswap-failed");
uint256 finalBal = getTokenBal(buyToken);
@ -39,16 +39,16 @@ abstract contract Helpers is DSMath, Basic {
function _swap(SwapData memory swapData, uint256 setId) internal returns (SwapData memory) {
TokenInterface _sellAddr = swapData.sellToken;
uint256 maticAmt;
uint256 avaxAmt;
if (address(_sellAddr) == avaxAddr) {
maticAmt = swapData._sellAmt;
avaxAmt = swapData._sellAmt;
} else {
address tokenProxy = AugustusSwapperInterface(paraswap).getTokenTransferProxy();
approve(TokenInterface(_sellAddr), tokenProxy, swapData._sellAmt);
}
swapData._buyAmt = _swapHelper(swapData, maticAmt);
swapData._buyAmt = _swapHelper(swapData, avaxAmt);
setUint(setId, swapData._buyAmt);

View File

@ -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";
}

View File

@ -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}();
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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(

View File

@ -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: <a href="https://api.1inch.exchange/swagger/ethereum/#/Swap/SwapFactoryCommonController_getSwap" target="_blank">here </a>
* @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";
}

View File

@ -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
);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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";
}

View File

@ -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
);
}

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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";
}

View File

@ -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
);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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";
}

View File

@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
contract Events {
event LogDeposit(
address indexed userAddress,
address indexed token,
uint256 amount,
uint256 indexed bondingShareId,
uint256 lpAmount,
uint256 durationWeeks,
uint256 getId,
uint256 setId
);
event LogWithdraw(
address indexed userAddress,
uint256 indexed bondingShareId,
uint256 lpAmount,
uint256 endBlock,
address indexed token,
uint256 amount,
uint256 getId,
uint256 setId
);
}

View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import { Basic } from "../../common/basic.sol";
import { IUbiquityAlgorithmicDollarManager } from "./interfaces.sol";
abstract contract Helpers is Basic {
/**
* @dev Ubiquity Algorithmic Dollar Manager
*/
IUbiquityAlgorithmicDollarManager internal constant ubiquityManager =
IUbiquityAlgorithmicDollarManager(
0x4DA97a8b831C345dBe6d16FF7432DF2b7b776d98
);
/**
* @dev DAI Address
*/
address internal constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
/**
* @dev USDC Address
*/
address internal constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
/**
* @dev USDT Address
*/
address internal constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
/**
* @dev Curve 3CRV Token Address
*/
address internal constant CRV3 = 0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490;
/**
* @dev Curve 3Pool Address
*/
address internal constant Pool3 =
0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7;
/**
* @dev Ubiquity Algorithmic Dollar Address
*/
function getUAD() internal returns (address) {
return ubiquityManager.dollarTokenAddress();
}
/**
* @dev Ubiquity Metapool uAD / 3CRV Address
*/
function getUADCRV3() internal returns (address) {
return ubiquityManager.stableSwapMetaPoolAddress();
}
}

View File

@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma abicoder v2;
interface IUbiquityBondingV2 {
struct Bond {
address minter;
uint256 lpFirstDeposited;
uint256 creationBlock;
uint256 lpRewardDebt;
uint256 endBlock;
uint256 lpAmount;
}
function deposit(uint256 lpAmount, uint256 durationWeeks)
external
returns (uint256 bondingShareId);
function removeLiquidity(uint256 lpAmount, uint256 bondId) external;
function holderTokens(address) external view returns (uint256[] memory);
function totalLP() external view returns (uint256);
function totalSupply() external view returns (uint256);
function getBond(uint256 bondId) external returns (Bond memory bond);
}
interface IUbiquityMetaPool {
function add_liquidity(uint256[2] memory _amounts, uint256 _min_mint_amount)
external
returns (uint256);
function remove_liquidity_one_coin(
uint256 lpAmount,
int128 i,
uint256 min_amount
) external returns (uint256);
}
interface I3Pool {
function add_liquidity(
uint256[3] calldata _amounts,
uint256 _min_mint_amount
) external;
function remove_liquidity_one_coin(
uint256 lpAmount,
int128 i,
uint256 min_amount
) external;
}
interface IUbiquityAlgorithmicDollarManager {
function dollarTokenAddress() external returns (address);
function stableSwapMetaPoolAddress() external returns (address);
function bondingContractAddress() external returns (address);
function bondingShareAddress() external returns (address);
}

View File

@ -0,0 +1,222 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
pragma abicoder v2;
/**
* @title Ubiquity.
* @dev Ubiquity Dollar (uAD).
*/
import { TokenInterface } from "../../common/interfaces.sol";
import { IUbiquityBondingV2, IUbiquityMetaPool, I3Pool } from "./interfaces.sol";
import { Helpers } from "./helpers.sol";
import { Events } from "./events.sol";
abstract contract UbiquityResolver is Helpers, Events {
/**
* @dev Deposit into Ubiquity protocol
* @notice 3POOL (DAI / USDC / USDT) => METAPOOL (3CRV / uAD) => uAD3CRV-f => Ubiquity BondingShare
* @notice STEP 1 : 3POOL (DAI / USDC / USDT) => 3CRV
* @notice STEP 2 : METAPOOL(3CRV / UAD) => uAD3CRV-f
* @notice STEP 3 : uAD3CRV-f => Ubiquity BondingShare
* @param token Token deposited : DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f
* @param amount Amount of tokens to deposit (For max: `uint256(-1)`)
* @param durationWeeks Duration in weeks tokens will be locked (4-208)
* @param getId ID to retrieve amt.
* @param setId ID stores the bonding share id of tokens deposited.
*/
function deposit(
address token,
uint256 amount,
uint256 durationWeeks,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
address UAD3CRVf = getUADCRV3();
bool[6] memory tok = [
token == DAI, // 0
token == USDC, // 1
token == USDT, // 2
token == CRV3, // 3
token == getUAD(), // 4
token == UAD3CRVf // 5
];
require(
// DAI / USDC / USDT / CRV3 / UAD / UAD3CRVF
tok[0] || tok[1] || tok[2] || tok[3] || tok[4] || tok[5],
"Invalid token: must be DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f"
);
uint256 _amount = getUint(getId, amount);
uint256 lpAmount;
// Full balance if amount = -1
if (_amount == uint256(-1)) {
_amount = getTokenBal(TokenInterface(token));
}
// STEP 1 : SwapTo3CRV : Deposit DAI, USDC or USDT into 3Pool to get 3Crv LPs
// DAI / USDC / USDT
if (tok[0] || tok[1] || tok[2]) {
uint256[3] memory amounts1;
if (tok[0]) amounts1[0] = _amount;
else if (tok[1]) amounts1[1] = _amount;
else if (tok[2]) amounts1[2] = _amount;
approve(TokenInterface(token), Pool3, _amount);
I3Pool(Pool3).add_liquidity(amounts1, 0);
}
// STEP 2 : ProvideLiquidityToMetapool : Deposit in uAD3CRV pool to get uAD3CRV-f LPs
// DAI / USDC / USDT / CRV3 / UAD
if (tok[0] || tok[1] || tok[2] || tok[3] || tok[4]) {
uint256[2] memory amounts2;
address token2 = token;
uint256 _amount2;
if (tok[4]) {
_amount2 = _amount;
amounts2[0] = _amount2;
} else {
if (tok[3]) {
_amount2 = _amount;
} else {
token2 = CRV3;
_amount2 = getTokenBal(TokenInterface(token2));
}
amounts2[1] = _amount2;
}
approve(TokenInterface(token2), UAD3CRVf, _amount2);
lpAmount = IUbiquityMetaPool(UAD3CRVf).add_liquidity(amounts2, 0);
}
// STEP 3 : Farm/ApeIn : Deposit uAD3CRV-f LPs into UbiquityBondingV2 and get Ubiquity Bonding Shares
// UAD3CRVF
if (tok[5]) {
lpAmount = _amount;
}
address bonding = ubiquityManager.bondingContractAddress();
approve(TokenInterface(UAD3CRVf), bonding, lpAmount);
uint256 bondingShareId = IUbiquityBondingV2(bonding).deposit(
lpAmount,
durationWeeks
);
setUint(setId, bondingShareId);
_eventName = "LogDeposit(address,address,uint256,uint256,uint256,uint256,uint256,uint256)";
_eventParam = abi.encode(
address(this),
token,
amount,
bondingShareId,
lpAmount,
durationWeeks,
getId,
setId
);
}
/**
* @dev Withdraw from Ubiquity protocol
* @notice Ubiquity BondingShare => uAD3CRV-f => METAPOOL (3CRV / uAD) => 3POOL (DAI / USDC / USDT)
* @notice STEP 1 : Ubiquity BondingShare => uAD3CRV-f
* @notice STEP 2 : uAD3CRV-f => METAPOOL(3CRV / UAD)
* @notice STEP 3 : 3CRV => 3POOL (DAI / USDC / USDT)
* @param bondingShareId Bonding Share Id to withdraw
* @param token Token to withdraw to : DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f
* @param getId ID
* @param setId ID
*/
function withdraw(
uint256 bondingShareId,
address token,
uint256 getId,
uint256 setId
)
external
payable
returns (string memory _eventName, bytes memory _eventParam)
{
address UAD3CRVf = getUADCRV3();
bool[6] memory tok = [
token == DAI, // 0
token == USDC, // 1
token == USDT, // 2
token == CRV3, // 3
token == getUAD(), // 4
token == UAD3CRVf // 5
];
require(
// DAI / USDC / USDT / CRV3 / UAD / UAD3CRVF
tok[0] || tok[1] || tok[2] || tok[3] || tok[4] || tok[5],
"Invalid token: must be DAI, USDC, USDT, 3CRV, uAD or uAD3CRV-f"
);
uint256 _bondingShareId = getUint(getId, bondingShareId);
// Get Bond
IUbiquityBondingV2.Bond memory bond = IUbiquityBondingV2(
ubiquityManager.bondingShareAddress()
).getBond(_bondingShareId);
require(address(this) == bond.minter, "Not bond owner");
// STEP 1 : Withdraw Ubiquity Bonding Shares to get back uAD3CRV-f LPs
address bonding = ubiquityManager.bondingContractAddress();
IUbiquityBondingV2(bonding).removeLiquidity(
bond.lpAmount,
_bondingShareId
);
// STEP 2 : Withdraw uAD3CRV-f LPs to get back uAD or 3Crv
// DAI / USDC / USDT / CRV3 / UAD
if (tok[0] || tok[1] || tok[2] || tok[3] || tok[4]) {
uint256 amount2 = getTokenBal(TokenInterface(UAD3CRVf));
IUbiquityMetaPool(UAD3CRVf).remove_liquidity_one_coin(
amount2,
tok[4] ? 0 : 1,
0
);
}
// STEP 3 : Withdraw 3Crv LPs from 3Pool to get back DAI, USDC or USDT
// DAI / USDC / USDT
if (tok[0] || tok[1] || tok[2]) {
uint256 amount1 = getTokenBal(TokenInterface(CRV3));
I3Pool(Pool3).remove_liquidity_one_coin(
amount1,
tok[0] ? 0 : (tok[1] ? 1 : 2),
0
);
}
uint256 amount = getTokenBal(TokenInterface(token));
setUint(setId, amount);
_eventName = "LogWithdraw(address,uint256,uint256,uint256,address,uint256,uint256,uint256)";
_eventParam = abi.encode(
address(this),
_bondingShareId,
bond.lpAmount,
bond.endBlock,
token,
amount,
getId,
setId
);
}
}
contract ConnectV2Ubiquity is UbiquityResolver {
string public constant name = "Ubiquity-v1";
}

View File

@ -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
);
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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";
}

View File

@ -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
);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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";
}

View File

@ -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;

View File

@ -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";
}

View File

@ -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
);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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";
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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";
}

View File

@ -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
);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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";
}

View File

@ -39,6 +39,13 @@ const mnemonic =
process.env.MNEMONIC ??
"test test test test test test test test test test test junk";
const networkGasPriceConfig: Record<string, string> = {
"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")

View File

@ -57,6 +57,9 @@
"hardhat": "^2.7.0",
"hardhat-deploy": "^0.9.14",
"hardhat-deploy-ethers": "^0.3.0-beta.11",
"prettier": "^2.4.1",
"prettier-plugin-solidity": "^1.0.0-beta.18",
"solhint": "^3.3.6",
"husky": "^7.0.4",
"solidity-coverage": "0.7.17",
"ts-node": "^10.4.0",

View File

@ -5,19 +5,24 @@ async function main() {
const accounts = await ethers.getSigners();
const connectMapping: Record<string, string> = {
// "1INCH-A": "ConnectV2OneInch",
// "1INCH-B": "ConnectV2OneProto",
// "AAVE-V1-A": "ConnectV2AaveV1",
// "AAVE-V2-A": "ConnectV2AaveV2",
// "AUTHORITY-A": "ConnectV2Auth",
// "BASIC-A": "ConnectV2Basic",
// "COMP-A": "ConnectV2COMP",
// "COMPOUND-A": "ConnectV2Compound",
// "DYDX-A": "ConnectV2Dydx",
// "FEE-A": "ConnectV2Fee",
// "GELATO-A": "ConnectV2Gelato",
// "MAKERDAO-A": "ConnectV2Maker",
// "UNISWAP-A": "ConnectV2UniswapV2",
"1INCH-A": "ConnectV2OneInch",
"1INCH-B": "ConnectV2OneProto",
"AAVE-V1-A": "ConnectV2AaveV1",
"AAVE-V2-A": "ConnectV2AaveV2",
"AUTHORITY-A": "ConnectV2Auth",
"BASIC-A": "ConnectV2Basic",
"COMP-A": "ConnectV2COMP",
"COMPOUND-A": "ConnectV2Compound",
"DYDX-A": "ConnectV2Dydx",
"FEE-A": "ConnectV2Fee",
"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",
"ZEROEX-A": "ConnectV2ZeroExAvalanche",
};

View File

@ -6,7 +6,7 @@ import { execScript } from "./command";
let start: number, end: number;
async function testRunner() {
const chain = ["avalanche", "mainnet", "polygon"];
const chain = ["avalanche", "mainnet", "polygon", "arbitrum"];
start = Date.now();
for (let ch of chain) {

View File

@ -25,7 +25,7 @@ async function testRunner() {
const { testName } = await inquirer.prompt([
{
name: "testName",
message: "For which resolver you want to run the tests?",
message: "For which connector you want to run the tests?",
type: "list",
choices: ["all", ...availableTests],
},

View File

@ -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();
});
});
});

View File

@ -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()
});
});
})

View File

@ -0,0 +1,462 @@
import { expect } from "chai";
import hre from "hardhat";
const { waffle, ethers } = hre;
const { provider } = waffle;
const { BigNumber, utils } = ethers;
import {deployAndEnableConnector} from "../../../scripts/tests/deployAndEnableConnector";
import {buildDSAv2} from "../../../scripts/tests/buildDSAv2";
import {encodeSpells} from "../../../scripts/tests/encodeSpells";
import {addresses} from "../../../scripts/tests/mainnet/addresses";
import {abis} from "../../../scripts/constant/abis";
import {impersonateAccounts} from "../../../scripts/tests/impersonate";
import type { Signer, Contract, BigNumberish } from "ethers";
import {forkReset, sendEth, mineNBlock} from "./utils";
import { ConnectV2Ubiquity__factory } from "../../../typechain";
import { abi as implementationsABI } from "../../../scripts/constant/abi/core/InstaImplementations.json";
const implementationsMappingAddr = "0xCBA828153d3a85b30B5b912e1f2daCac5816aE9D";
describe("Ubiquity", function () {
const ubiquityTest = "UBIQUITY-TEST-A";
const BOND = "0x2dA07859613C14F6f05c97eFE37B9B4F212b5eF5";
const UAD = "0x0F644658510c95CB46955e55D7BA9DDa9E9fBEc6";
const DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const USDT = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
const CRV3 = "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490";
const POOL3 = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7";
const UAD3CRVF = "0x20955CB69Ae1515962177D164dfC9522feef567E";
const ethWhaleAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
const uadWhaleAddress = "0xefC0e701A824943b469a694aC564Aa1efF7Ab7dd";
const blockFork = 13097100;
const one = BigNumber.from(10).pow(18);
const onep = BigNumber.from(10).pow(6);
const ABI = [
"function balanceOf(address owner) view returns (uint256)",
"function allowance(address owner, address spender) external view returns (uint256)",
"function transfer(address to, uint amount) returns (boolean)",
"function remove_liquidity_one_coin(uint256 _burn_amount, int128 i, uint256 _min_received) external returns (uint256)",
"function add_liquidity(uint256[3],uint256) returns (uint256)",
"function approve(address, uint256) external",
"function holderTokens(address) view returns (uint256[])",
"function getBond(uint256) view returns (tuple(address,uint256,uint256,uint256,uint256,uint256))"
];
let dsa: Contract;
let POOL3Contract: Contract;
let CRV3Contract: Contract;
let uAD3CRVfContract: Contract;
let uADContract: Contract;
let DAIContract: Contract;
let USDCContract: Contract;
let USDTContract: Contract;
let BONDContract: Contract;
let instaIndex: Contract;
let instaConnectorsV2: Contract;
let connector: Contract;
let instaImplementationsMapping;
let InstaAccountV2DefaultImpl;
let uadWhale;
const bondingShare = async function (address: any) {
let lpAmount = BigNumber.from(0);
let lpAmountTotal = BigNumber.from(0);
let bondId = -1;
const bondIds = await BONDContract.holderTokens(address);
const bondN = bondIds?.length || 0;
if (bondN) {
for await (bondId of bondIds) {
lpAmountTotal = lpAmountTotal.add((await BONDContract.getBond(bondId))[5]);
}
bondId = Number(bondIds[bondN - 1]);
lpAmount = (await BONDContract.getBond(bondId))[5];
}
return { bondId, bondN, lpAmount, lpAmountTotal };
};
const depositAndGetOneBond = async function () {
await dsaDepositUAD3CRVf(100);
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "deposit",
args: [UAD3CRVF, one.mul(100), 1, 0, 0]
}
]),
uadWhaleAddress
);
};
before(async () => {
// await forkReset(blockFork);
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
blockNumber: 13097100,
},
},
],
});
[uadWhale] = await impersonateAccounts([uadWhaleAddress]);
const [ethWhale] = await impersonateAccounts([ethWhaleAddress]);
await sendEth(ethWhale, uadWhaleAddress, 100);
POOL3Contract = new ethers.Contract(POOL3, ABI, uadWhale);
CRV3Contract = new ethers.Contract(CRV3, ABI, uadWhale);
uAD3CRVfContract = new ethers.Contract(UAD3CRVF, ABI, uadWhale);
uADContract = new ethers.Contract(UAD, ABI, uadWhale);
DAIContract = new ethers.Contract(DAI, ABI, uadWhale);
USDCContract = new ethers.Contract(USDC, ABI, uadWhale);
USDTContract = new ethers.Contract(USDT, ABI, uadWhale);
BONDContract = new ethers.Contract(BOND, ABI, uadWhale);
dsa = (await buildDSAv2(uadWhaleAddress)).connect(uadWhale);
await sendEth(ethWhale, dsa.address, 100);
await sendEth(ethWhale, uadWhaleAddress, 100);
instaIndex = new ethers.Contract(addresses.core.instaIndex, abis.core.instaIndex, ethWhale);
const masterAddress = await instaIndex.master();
const [master] = await impersonateAccounts([masterAddress]);
await sendEth(ethWhale, masterAddress, 100);
instaConnectorsV2 = new ethers.Contract(addresses.core.connectorsV2, abis.core.connectorsV2);
instaImplementationsMapping = await ethers.getContractAt(implementationsABI, implementationsMappingAddr);
InstaAccountV2DefaultImpl = await ethers.getContractFactory("InstaDefaultImplementation");
InstaAccountV2DefaultImpl = await InstaAccountV2DefaultImpl.deploy(addresses.core.instaIndex);
await InstaAccountV2DefaultImpl.deployed();
await (
await instaImplementationsMapping.connect(master).setDefaultImplementation(InstaAccountV2DefaultImpl.address)
).wait();
connector = await deployAndEnableConnector({
connectorName: ubiquityTest,
contractArtifact: ConnectV2Ubiquity__factory,
signer: master,
connectors: instaConnectorsV2
});
});
const logAll = async function () {
console.log("dsa eth", utils.formatEther(await ethers.provider.getBalance(dsa.address)));
console.log("dsa dai", utils.formatEther(await DAIContract.balanceOf(dsa.address)));
console.log("dsa usdc", utils.formatUnits(await USDCContract.balanceOf(dsa.address), 6));
console.log("dsa usdt", utils.formatUnits(await USDTContract.balanceOf(dsa.address), 6));
console.log("dsa uad", utils.formatEther(await uADContract.balanceOf(dsa.address)));
console.log("dsa 3CRV", utils.formatEther(await CRV3Contract.balanceOf(dsa.address)));
console.log("dsa uad3CRV-f", utils.formatEther(await uAD3CRVfContract.balanceOf(dsa.address)));
const { bondId, bondN, lpAmount, lpAmountTotal } = await bondingShare(dsa.address);
console.log("dsa n bonds", utils.formatEther(lpAmountTotal), bondN);
console.log("dsa last bond", utils.formatEther(lpAmount), bondId);
};
afterEach(logAll);
const dsaDepositUAD3CRVf = async (amount: BigNumberish) => {
await uAD3CRVfContract.transfer(dsa.address, one.mul(amount));
};
const dsaDepositUAD = async (amount: BigNumberish) => {
await uAD3CRVfContract.remove_liquidity_one_coin(one.mul(amount).mul(110).div(100), 0, one.mul(amount));
await uADContract.transfer(dsa.address, one.mul(amount));
};
const dsaDepositCRV3 = async (amount: BigNumberish) => {
await uAD3CRVfContract.remove_liquidity_one_coin(one.mul(amount).mul(110).div(100), 1, one.mul(amount));
await CRV3Contract.transfer(dsa.address, one.mul(amount));
};
const dsaDepositDAI = async (amount: BigNumberish) => {
await uAD3CRVfContract.remove_liquidity_one_coin(
one.mul(amount).mul(120).div(100),
1,
one.mul(amount).mul(110).div(100)
);
await POOL3Contract.remove_liquidity_one_coin(one.mul(amount).mul(110).div(100), 0, one.mul(amount));
await DAIContract.transfer(dsa.address, one.mul(amount));
};
const dsaDepositUSDC = async (amount: BigNumberish) => {
await uAD3CRVfContract.remove_liquidity_one_coin(
one.mul(amount).mul(120).div(100),
1,
one.mul(amount).mul(110).div(100)
);
await POOL3Contract.remove_liquidity_one_coin(one.mul(amount).mul(110).div(100), 1, onep.mul(amount));
await USDCContract.transfer(dsa.address, onep.mul(amount));
};
const dsaDepositUSDT = async (amount: BigNumberish) => {
await uAD3CRVfContract.remove_liquidity_one_coin(
one.mul(amount).mul(120).div(100),
1,
one.mul(amount).mul(110).div(100)
);
await POOL3Contract.remove_liquidity_one_coin(one.mul(amount).mul(110).div(100), 2, onep.mul(amount));
await USDTContract.transfer(dsa.address, onep.mul(amount));
};
describe("Deposit", function () {
it("should deposit uAD3CRVf to get Ubiquity Bonding Shares", async function () {
await logAll();
await dsaDepositUAD3CRVf(100);
expect((await bondingShare(dsa.address)).lpAmount).to.be.equal(0);
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "deposit",
args: [UAD3CRVF, one.mul(100), 4, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
expect((await bondingShare(dsa.address)).lpAmount).to.be.gt(0);
});
it("should deposit uAD to get Ubiquity Bonding Shares", async function () {
await dsaDepositUAD(100);
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "deposit",
args: [UAD, one.mul(100), 4, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
expect((await bondingShare(dsa.address)).lpAmount).to.be.gt(0);
});
it("should deposit 3CRV to get Ubiquity Bonding Shares", async function () {
await dsaDepositCRV3(100);
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "deposit",
args: [CRV3, one.mul(100), 4, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
expect((await bondingShare(dsa.address)).lpAmount).to.be.gt(0);
});
it("should deposit DAI to get Ubiquity Bonding Shares", async function () {
await dsaDepositDAI(100);
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "deposit",
args: [DAI, one.mul(100), 4, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
expect((await bondingShare(dsa.address)).lpAmount).to.be.gt(0);
});
it("should deposit USDC to get Ubiquity Bonding Shares", async function () {
await dsaDepositUSDC(100);
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "deposit",
args: [USDC, onep.mul(100), 4, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
expect((await bondingShare(dsa.address)).lpAmount).to.be.gt(0);
});
it("should deposit USDT to get Ubiquity Bonding Shares", async function () {
await dsaDepositUSDT(100);
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "deposit",
args: [USDT, onep.mul(100), 4, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
expect((await bondingShare(dsa.address)).lpAmount).to.be.gt(0);
});
});
describe("Withdraw", function () {
let bondId = -1;
before(async () => {
await depositAndGetOneBond();
await depositAndGetOneBond();
await depositAndGetOneBond();
await depositAndGetOneBond();
await depositAndGetOneBond();
await depositAndGetOneBond();
({ bondId } = await bondingShare(dsa.address));
await logAll();
console.log("Mining 50 000 blocks for more than one week, please wait...");
await mineNBlock(50000, 1);
});
it("Should deposit and withdraw DAI", async function () {
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "withdraw",
args: [bondId, DAI, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
});
it("Should deposit and withdraw USDC", async function () {
// await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "withdraw",
args: [bondId - 1, USDC, 0, 0]
}
]),
uadWhaleAddress
);
// ).to.be.not.reverted;
});
it("Should deposit and withdraw USDT", async function () {
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "withdraw",
args: [bondId - 2, USDT, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
});
it("Should deposit and withdraw UAD", async function () {
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "withdraw",
args: [bondId - 3, UAD, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
});
it("Should deposit and withdraw CRV3", async function () {
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "withdraw",
args: [bondId - 4, CRV3, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
});
it("Should deposit and withdraw UAD3CRVF", async function () {
await expect(
dsa.cast(
...encodeSpells([
{
connector: ubiquityTest,
method: "withdraw",
args: [bondId - 5, UAD3CRVF, 0, 0]
}
]),
uadWhaleAddress
)
).to.be.not.reverted;
});
});
describe("DSA wallet setup", function () {
it("Should have contracts deployed.", async function () {
expect(POOL3Contract.address).to.be.properAddress;
expect(CRV3Contract.address).to.be.properAddress;
expect(uADContract.address).to.be.properAddress;
expect(uAD3CRVfContract.address).to.be.properAddress;
expect(DAIContract.address).to.be.properAddress;
expect(USDCContract.address).to.be.properAddress;
expect(USDTContract.address).to.be.properAddress;
expect(BONDContract.address).to.be.properAddress;
expect(instaIndex.address).to.be.properAddress;
expect(instaConnectorsV2.address).to.be.properAddress;
expect(connector.address).to.be.properAddress;
expect(dsa.address).to.be.properAddress;
});
it("Should deposit uAD3CRVf into DSA wallet", async function () {
await dsaDepositUAD3CRVf(100);
expect(await uAD3CRVfContract.balanceOf(dsa.address)).to.be.gte(one.mul(100));
});
it("Should deposit uAD into DSA wallet", async function () {
await dsaDepositUAD(100);
expect(await uADContract.balanceOf(dsa.address)).to.be.gte(one.mul(100));
});
it("Should deposit 3CRV into DSA wallet", async function () {
await dsaDepositCRV3(100);
expect(await CRV3Contract.balanceOf(dsa.address)).to.be.gte(one.mul(100));
});
it("Should deposit DAI into DSA wallet", async function () {
await dsaDepositDAI(100);
expect(await DAIContract.balanceOf(dsa.address)).to.be.gte(one.mul(100));
});
it("Should deposit USDC into DSA wallet", async function () {
await dsaDepositUSDC(100);
expect(await USDCContract.balanceOf(dsa.address)).to.be.gte(onep.mul(100));
});
it("Should deposit USDT into DSA wallet", async function () {
await dsaDepositUSDT(100);
expect(await USDTContract.balanceOf(dsa.address)).to.be.gte(onep.mul(100));
});
});
});

View File

@ -0,0 +1,55 @@
import hre, { ethers, network } from "hardhat";
import hardhatConfig from "../../../hardhat.config";
export async function forkReset(blockNumber: any) {
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
// @ts-ignore
jsonRpcUrl: hardhatConfig.networks.hardhat.forking.url,
blockNumber
}
}
]
});
}
export async function mineBlock(timestamp: any) {
await network.provider.request({
method: "evm_mine",
params: [timestamp]
});
}
export async function sendEth(from: any, to: any, amount: any) {
await from.sendTransaction({
to: to,
value: ethers.BigNumber.from(10).pow(18).mul(amount)
});
}
export async function mineNBlock(blockCount: any, secondsBetweenBlock: any) {
const blockBefore = await ethers.provider.getBlock("latest");
const maxMinedBlockPerBatch = 1000;
let blockToMine = blockCount;
let blockTime = blockBefore.timestamp;
while (blockToMine > maxMinedBlockPerBatch) {
// eslint-disable-next-line @typescript-eslint/no-loop-func
const minings: any = [maxMinedBlockPerBatch].map((_v, i) => {
const newTs = blockTime + i + (secondsBetweenBlock || 1);
return mineBlock(newTs);
});
// eslint-disable-next-line no-await-in-loop
await Promise.all(minings);
blockToMine -= maxMinedBlockPerBatch;
blockTime = blockTime + maxMinedBlockPerBatch - 1 + maxMinedBlockPerBatch * (secondsBetweenBlock || 1);
}
const minings = [blockToMine].map((_v, i) => {
const newTs = blockTime + i + (secondsBetweenBlock || 1);
return mineBlock(newTs);
});
// eslint-disable-next-line no-await-in-loop
await Promise.all(minings);
}

View File

@ -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")
);
});
});
});

View File

@ -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();
});
});
});

515
yarn.lock
View File

@ -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"