Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V6 update strategy tests #301

Merged
merged 3 commits into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions test/forkMainnet/GenericSwap.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import { SigHelper } from "test/utils/SigHelper.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { computeContractAddress } from "test/utils/Addresses.sol";
import { Permit2Helper } from "test/utils/Permit2Helper.sol";
import { UniswapV3 } from "test/utils/UniswapV3.sol";
import { IUniswapV3Quoter } from "test/utils/IUniswapV3Quoter.sol";
import { IUniswapSwapRouter02 } from "test/utils/IUniswapSwapRouter02.sol";
import { MockStrategy } from "test/mocks/MockStrategy.sol";
import { GenericSwap } from "contracts/GenericSwap.sol";
import { AllowanceTarget } from "contracts/AllowanceTarget.sol";
import { TokenCollector } from "contracts/abstracts/TokenCollector.sol";
import { SmartOrderStrategy } from "contracts/SmartOrderStrategy.sol";
import { Constant } from "contracts/libraries/Constant.sol";
import { UniswapV3 } from "contracts/libraries/UniswapV3.sol";
import { GenericSwapData, getGSDataHash } from "contracts/libraries/GenericSwapData.sol";
import { IGenericSwap } from "contracts/interfaces/IGenericSwap.sol";
import { ISmartOrderStrategy } from "contracts/interfaces/ISmartOrderStrategy.sol";
import { IUniswapV3Quoter } from "contracts/interfaces/IUniswapV3Quoter.sol";
import { IUniswapSwapRouter02 } from "contracts/interfaces/IUniswapSwapRouter02.sol";

contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper {
using BalanceSnapshot for Snapshot;
Expand Down
132 changes: 82 additions & 50 deletions test/forkMainnet/SmartOrderStrategy/AMMs.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,34 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import { SmartOrderStrategyTest } from "./Setup.t.sol";
import { ICurveFiV2 } from "contracts/interfaces/ICurveFiV2.sol";
import { ICurveFiV2 } from "test/utils/ICurveFiV2.sol";
import { ISmartOrderStrategy } from "contracts/interfaces/ISmartOrderStrategy.sol";
import { IUniswapSwapRouter02 } from "contracts/interfaces/IUniswapSwapRouter02.sol";
import { IUniswapSwapRouter02 } from "test/utils/IUniswapSwapRouter02.sol";
import { Constant } from "contracts/libraries/Constant.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { UniswapV2Library } from "test/utils/UniswapV2Library.sol";
import { UniswapV3 } from "test/utils/UniswapV3.sol";

contract AMMsTest is SmartOrderStrategyTest {
using SafeERC20 for IERC20;
using BalanceSnapshot for Snapshot;

function testUniswapV2WithoutAmountReplace() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0, // minOutputAmount
defaultUniV2Path,
address(smartOrderStrategy)
function testUniswapV3WithoutAmountReplace() public {
bytes memory uniswapData = abi.encodeCall(
IUniswapSwapRouter02.exactInputSingle,
(
IUniswapSwapRouter02.ExactInputSingleParams({
tokenIn: defaultInputToken,
tokenOut: defaultOutputToken,
fee: defaultFee,
recipient: address(smartOrderStrategy),
amountIn: defaultInputAmount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
)
);

ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
Expand All @@ -36,8 +45,7 @@ contract AMMsTest is SmartOrderStrategyTest {
bytes memory data = abi.encode(operations);

// get the exact quote from uniswap
uint256[] memory amounts = UniswapV2Library.getAmountsOut(defaultInputAmount, defaultUniV2Path);
uint256 expectedOut = amounts[amounts.length - 1];
uint256 expectedOut = v3Quoter.quoteExactInput(encodedUniv3Path, defaultInputAmount);

vm.startPrank(genericSwap, genericSwap);
IERC20(defaultInputToken).safeTransfer(address(smartOrderStrategy), defaultInputAmount);
Expand All @@ -50,29 +58,35 @@ contract AMMsTest is SmartOrderStrategyTest {
gsOutputToken.assertChange(int256(expectedOut));
}

function testUniswapV2WithAmountReplace() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0,
defaultUniV2Path,
address(smartOrderStrategy)
function testUniswapV3WithAmountReplace() public {
bytes memory uniswapData = abi.encodeCall(
IUniswapSwapRouter02.exactInputSingle,
(
IUniswapSwapRouter02.ExactInputSingleParams({
tokenIn: defaultInputToken,
tokenOut: defaultOutputToken,
fee: defaultFee,
recipient: address(smartOrderStrategy),
amountIn: defaultInputAmount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: defaultInputToken,
inputRatio: defaultInputRatio,
dataOffset: uint128(4 + 32), // add 32 bytes of length prefix
dataOffset: uint128(4 + 32 + 128), // add 32 bytes of length prefix
value: 0,
data: uniswapData
});
bytes memory data = abi.encode(operations);

// get the exact quote from uniswap
uint256 inputAmountAfterRatio = (defaultInputAmount * defaultInputRatio) / Constant.BPS_MAX;
uint256[] memory amounts = UniswapV2Library.getAmountsOut(inputAmountAfterRatio, defaultUniV2Path);
uint256 expectedOut = amounts[amounts.length - 1];
uint256 expectedOut = v3Quoter.quoteExactInput(encodedUniv3Path, inputAmountAfterRatio);

vm.startPrank(genericSwap, genericSwap);
IERC20(defaultInputToken).safeTransfer(address(smartOrderStrategy), defaultInputAmount);
Expand All @@ -85,20 +99,27 @@ contract AMMsTest is SmartOrderStrategyTest {
gsOutputToken.assertChange(int256(expectedOut));
}

function testUniswapV2WithMaxAmountReplace() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0,
defaultUniV2Path,
address(smartOrderStrategy)
function testUniswapV3WithMaxAmountReplace() public {
bytes memory uniswapData = abi.encodeCall(
IUniswapSwapRouter02.exactInputSingle,
(
IUniswapSwapRouter02.ExactInputSingleParams({
tokenIn: defaultInputToken,
tokenOut: defaultOutputToken,
fee: defaultFee,
recipient: address(smartOrderStrategy),
amountIn: defaultInputAmount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: defaultInputToken,
inputRatio: Constant.BPS_MAX, // BPS_MAX indicate the input amount will be replaced by the actual balance
dataOffset: uint128(4 + 32), // add 32 bytes of length prefix
dataOffset: uint128(4 + 32 + 128), // add 32 bytes of length prefix
value: 0,
data: uniswapData
});
Expand All @@ -108,8 +129,7 @@ contract AMMsTest is SmartOrderStrategyTest {
uint256 actualInputAmount = 5678;

// get the exact quote from uniswap
uint256[] memory amounts = UniswapV2Library.getAmountsOut(actualInputAmount, defaultUniV2Path);
uint256 expectedOut = amounts[amounts.length - 1];
uint256 expectedOut = v3Quoter.quoteExactInput(encodedUniv3Path, actualInputAmount);

vm.startPrank(genericSwap, genericSwap);
IERC20(defaultInputToken).safeTransfer(address(smartOrderStrategy), actualInputAmount);
Expand All @@ -124,14 +144,21 @@ contract AMMsTest is SmartOrderStrategyTest {
}

function testUniswapV2WithWETHUnwrap() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0, // minOutputAmount
defaultUniV2Path,
address(smartOrderStrategy)
bytes memory uniswapData = abi.encodeCall(
IUniswapSwapRouter02.exactInputSingle,
(
IUniswapSwapRouter02.ExactInputSingleParams({
tokenIn: defaultInputToken,
tokenOut: defaultOutputToken,
fee: defaultFee,
recipient: address(smartOrderStrategy),
amountIn: defaultInputAmount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](2);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: defaultInputToken,
Expand All @@ -143,8 +170,7 @@ contract AMMsTest is SmartOrderStrategyTest {
bytes memory data = abi.encode(operations);

// get the exact quote from uniswap
uint256[] memory amounts = UniswapV2Library.getAmountsOut(defaultInputAmount, defaultUniV2Path);
uint256 expectedOut = amounts[amounts.length - 1];
uint256 expectedOut = v3Quoter.quoteExactInput(encodedUniv3Path, defaultInputAmount);

// set output token as ETH
address outputToken = Constant.ETH_ADDRESS;
Expand All @@ -160,20 +186,26 @@ contract AMMsTest is SmartOrderStrategyTest {
}

function testMultipleAMMs() public {
// (USDC -> USDT) via UniswapV2 + Curve
// (USDC -> USDT) via UniswapV3 + Curve
// UniswapV2 : USDC -> WETH
// Curve : WETH -> USDT

// get the exact quote from uniswap
uint256[] memory amounts = UniswapV2Library.getAmountsOut(defaultInputAmount, defaultUniV2Path);
uint256 uniOut = amounts[amounts.length - 1];

bytes memory uniswapData = abi.encodeWithSelector(
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0, // minOutputAmount
defaultUniV2Path,
address(smartOrderStrategy)
uint256 uniOut = v3Quoter.quoteExactInput(encodedUniv3Path, defaultInputAmount);

bytes memory uniswapData = abi.encodeCall(
IUniswapSwapRouter02.exactInputSingle,
(
IUniswapSwapRouter02.ExactInputSingleParams({
tokenIn: defaultInputToken,
tokenOut: defaultOutputToken,
fee: defaultFee,
recipient: address(smartOrderStrategy),
amountIn: defaultInputAmount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
)
);

// exhange function selector : 0x5b41b908
Expand Down
14 changes: 12 additions & 2 deletions test/forkMainnet/SmartOrderStrategy/Setup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Test } from "forge-std/Test.sol";
import { SmartOrderStrategy } from "contracts/SmartOrderStrategy.sol";
import { Tokens } from "test/utils/Tokens.sol";
import { BalanceUtil } from "test/utils/BalanceUtil.sol";
import { IUniswapV3Quoter } from "test/utils/IUniswapV3Quoter.sol";
import { UniswapV3 } from "test/utils/UniswapV3.sol";

contract SmartOrderStrategyTest is Test, Tokens, BalanceUtil {
address strategyOwner = makeAddr("strategyOwner");
Expand All @@ -15,11 +17,16 @@ contract SmartOrderStrategyTest is Test, Tokens, BalanceUtil {
uint128 defaultInputRatio = 5000;
uint256 defaultExpiry = block.timestamp + 100;
bytes defaultOpsData;
address[] defaultUniV2Path = [USDC_ADDRESS, WETH_ADDRESS];
bytes encodedUniv3Path;
address[] defaultUniV2Path = [defaultInputToken, defaultOutputToken];
address[] tokenList = [USDT_ADDRESS, USDC_ADDRESS, WETH_ADDRESS, WBTC_ADDRESS];
address[] ammList = [UNISWAP_SWAP_ROUTER_02_ADDRESS, SUSHISWAP_ADDRESS, CURVE_TRICRYPTO2_POOL_ADDRESS];
address[] ammList = [UNISWAP_SWAP_ROUTER_02_ADDRESS, CURVE_TRICRYPTO2_POOL_ADDRESS];

uint24 defaultFee = 3000;
uint24[] v3Fees = [defaultFee];

SmartOrderStrategy smartOrderStrategy;
IUniswapV3Quoter v3Quoter;

function setUp() public virtual {
// Deploy and setup SmartOrderStrategy
Expand All @@ -36,6 +43,9 @@ contract SmartOrderStrategyTest is Test, Tokens, BalanceUtil {
SmartOrderStrategy.Operation[] memory operations = new SmartOrderStrategy.Operation[](1);
defaultOpsData = abi.encode(operations);

v3Quoter = IUniswapV3Quoter(UNISWAP_V3_QUOTER_ADDRESS);
encodedUniv3Path = UniswapV3.encodePath(defaultUniV2Path, v3Fees);

vm.label(UNISWAP_UNIVERSAL_ROUTER_ADDRESS, "UniswapUniversalRouter");
}
}
6 changes: 3 additions & 3 deletions test/forkMainnet/UniAgent/SwapRouter02.t.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { IUniswapSwapRouter02 } from "contracts/interfaces/IUniswapSwapRouter02.sol";
import { IUniswapV3Quoter } from "contracts/interfaces/IUniswapV3Quoter.sol";
import { IUniswapSwapRouter02 } from "test/utils/IUniswapSwapRouter02.sol";
import { IUniswapV3Quoter } from "test/utils/IUniswapV3Quoter.sol";
import { IUniAgent } from "contracts/interfaces/IUniAgent.sol";
import { UniswapV3 } from "contracts/libraries/UniswapV3.sol";
import { UniswapV3 } from "test/utils/UniswapV3.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { UniswapV2Library } from "test/utils/UniswapV2Library.sol";
import { UniAgentTest } from "test/forkMainnet/UniAgent/Setup.t.sol";
Expand Down
6 changes: 3 additions & 3 deletions test/forkMainnet/UniAgent/Universal.t.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { IUniswapV3Quoter } from "contracts/interfaces/IUniswapV3Quoter.sol";
import { IUniversalRouter } from "contracts/interfaces/IUniswapUniversalRouter.sol";
import { IUniswapV3Quoter } from "test/utils/IUniswapV3Quoter.sol";
import { IUniversalRouter } from "test/utils/IUniswapUniversalRouter.sol";
import { IUniAgent } from "contracts/interfaces/IUniAgent.sol";
import { UniswapV3 } from "contracts/libraries/UniswapV3.sol";
import { UniswapV3 } from "test/utils/UniswapV3.sol";
import { UniswapCommands } from "test/utils/UniswapCommands.sol";
import { UniswapV2Library } from "test/utils/UniswapV2Library.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
Expand Down
2 changes: 1 addition & 1 deletion test/forkMainnet/UniAgent/V2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity 0.8.17;

import { IUniAgent } from "contracts/interfaces/IUniAgent.sol";
import { IUniswapV2Router } from "contracts/interfaces/IUniswapV2Router.sol";
import { IUniswapV2Router } from "test/utils/IUniswapV2Router.sol";
import { Constant } from "contracts/libraries/Constant.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { UniswapV2Library } from "test/utils/UniswapV2Library.sol";
Expand Down
6 changes: 3 additions & 3 deletions test/forkMainnet/UniAgent/V3.t.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { IUniswapV3Quoter } from "contracts/interfaces/IUniswapV3Quoter.sol";
import { IUniswapV3SwapRouter } from "contracts/interfaces/IUniswapV3SwapRouter.sol";
import { IUniswapV3Quoter } from "test/utils/IUniswapV3Quoter.sol";
import { IUniswapV3SwapRouter } from "test/utils/IUniswapV3SwapRouter.sol";
import { IUniAgent } from "contracts/interfaces/IUniAgent.sol";
import { UniswapV3 } from "contracts/libraries/UniswapV3.sol";
import { UniswapV3 } from "test/utils/UniswapV3.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { UniAgentTest } from "test/forkMainnet/UniAgent/Setup.t.sol";

Expand Down
2 changes: 1 addition & 1 deletion test/mocks/MockLimitOrderTaker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s

import { Ownable } from "contracts/abstracts/Ownable.sol";
import { IStrategy } from "contracts/interfaces/IStrategy.sol";
import { IUniswapSwapRouter02 } from "contracts/interfaces/IUniswapSwapRouter02.sol";
import { IUniswapSwapRouter02 } from "test/utils/IUniswapSwapRouter02.sol";
import { MockERC1271Wallet } from "./MockERC1271Wallet.sol";

contract MockLimitOrderTaker is IStrategy, MockERC1271Wallet {
Expand Down
2 changes: 2 additions & 0 deletions test/utils/Addresses.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ function readAddresses(Vm vm) view returns (string memory data) {
string memory fileName;
if (chainId == 1) {
fileName = "test/utils/config/mainnet.json";
} else if (chainId == 137) {
fileName = "test/utils/config/polygon.json";
} else if (chainId == 5) {
fileName = "test/utils/config/goerli.json";
} else if (chainId == 42161) {
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import { IUniswapV3SwapRouter } from "../interfaces/IUniswapV3SwapRouter.sol";
import { IUniswapV3Quoter } from "../interfaces/IUniswapV3Quoter.sol";
import { IUniswapV3SwapRouter } from "./IUniswapV3SwapRouter.sol";
import { IUniswapV3Quoter } from "./IUniswapV3Quoter.sol";

library UniswapV3 {
using Path for bytes;
Expand Down
2 changes: 1 addition & 1 deletion test/utils/config/polygon.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"LON_ADDRESS": "0x6f7C932e7684666C9fd1d44527765433e01fF61d",
"WBTC_ADDRESS": "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6",

"CURVE_TRICRYPTO2_POOL_ADDRESS": "0x000000000000000000000000000000000000000",
"CURVE_TRICRYPTO2_POOL_ADDRESS": "0xd51a44d3fae010294c616388b506acda1bfaae46",
"SUSHISWAP_ADDRESS": "0x000000000000000000000000000000000000000",
"UNISWAP_V3_QUOTER_ADDRESS": "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
"UNISWAP_PERMIT2_ADDRESS": "0x000000000022d473030f116ddee9f6b43ac78ba3",
Expand Down
Loading