Skip to content

Commit

Permalink
update tests using UniswapSwapRouter02 instead
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesjhongc committed Nov 8, 2023
1 parent a252093 commit 66bfe17
Show file tree
Hide file tree
Showing 17 changed files with 273 additions and 116 deletions.
76 changes: 52 additions & 24 deletions test/forkMainnet/GenericSwap.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ 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 { UniswapStrategy } from "contracts/UniswapStrategy.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 { IUniswapRouterV2 } from "contracts/interfaces/IUniswapRouterV2.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 All @@ -37,8 +40,13 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper
uint256 takerPrivateKey = uint256(1);
address taker = vm.addr(takerPrivateKey);
uint256 defaultExpiry = block.timestamp + 1;
address defaultInputToken = USDT_ADDRESS;
uint256 defaultInputAmount = 10 * 1e6;
address defaultOutputToken = DAI_ADDRESS;
address[] defaultPath = [defaultInputToken, defaultOutputToken];
uint24[] defaultV3Fees = [3000];
bytes defaultTakerPermit;
UniswapStrategy uniswapStrategy;
SmartOrderStrategy smartStrategy;
GenericSwap genericSwap;
GenericSwapData defaultGSData;
MockStrategy mockStrategy;
Expand All @@ -53,43 +61,63 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper
allowanceTarget = new AllowanceTarget(allowanceTargetOwner, trusted);

genericSwap = new GenericSwap(UNISWAP_PERMIT2_ADDRESS, address(allowanceTarget));
uniswapStrategy = new UniswapStrategy(strategyAdmin, address(genericSwap), UNISWAP_V2_ADDRESS);
smartStrategy = new SmartOrderStrategy(strategyAdmin, address(genericSwap), WETH_ADDRESS);
mockStrategy = new MockStrategy();
vm.prank(strategyAdmin);
uniswapStrategy.approveToken(USDT_ADDRESS, UNISWAP_V2_ADDRESS, type(uint256).max);

address[] memory defaultPath = new address[](2);
defaultPath[0] = USDT_ADDRESS;
defaultPath[1] = DAI_ADDRESS;
bytes memory makerSpecificData = abi.encode(defaultExpiry, defaultPath);
bytes memory swapData = abi.encode(UNISWAP_V2_ADDRESS, makerSpecificData);
address[] memory tokenList = new address[](1);
tokenList[0] = USDT_ADDRESS;
address[] memory ammList = new address[](1);
ammList[0] = UNISWAP_SWAP_ROUTER_02_ADDRESS;
smartStrategy.approveTokens(tokenList, ammList);

IUniswapV3Quoter v3Quoter = IUniswapV3Quoter(UNISWAP_V3_QUOTER_ADDRESS);
bytes memory encodedPath = UniswapV3.encodePath(defaultPath, defaultV3Fees);
uint256 expectedOut = v3Quoter.quoteExactInput(encodedPath, defaultInputAmount);
uint256 minOutputAmount = (expectedOut * 95) / 100; // default 5% slippage tolerance
bytes memory routerPayload = abi.encodeCall(
IUniswapSwapRouter02.exactInputSingle,
(
IUniswapSwapRouter02.ExactInputSingleParams({
tokenIn: defaultInputToken,
tokenOut: defaultOutputToken,
fee: defaultV3Fees[0],
recipient: address(smartStrategy),
amountIn: defaultInputAmount,
amountOutMinimum: minOutputAmount,
sqrtPriceLimitX96: 0
})
)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: defaultInputToken,
inputRatio: 0, // zero ratio indicate no replacement
dataOffset: 0,
value: 0,
data: routerPayload
});
bytes memory swapData = abi.encode(operations);

deal(taker, 100 ether);
setTokenBalanceAndApprove(taker, UNISWAP_PERMIT2_ADDRESS, tokens, 100000);
deal(address(mockStrategy), 100 ether);
setTokenBalanceAndApprove(address(mockStrategy), UNISWAP_PERMIT2_ADDRESS, tokens, 100000);

defaultGSData = GenericSwapData({
maker: payable(address(uniswapStrategy)),
takerToken: USDT_ADDRESS,
takerTokenAmount: 10 * 1e6,
makerToken: DAI_ADDRESS,
makerTokenAmount: 0, // to be filled later
minMakerTokenAmount: 0, // to be filled later
maker: payable(address(smartStrategy)),
takerToken: defaultInputToken,
takerTokenAmount: defaultInputAmount,
makerToken: defaultOutputToken,
makerTokenAmount: expectedOut,
minMakerTokenAmount: minOutputAmount,
expiry: defaultExpiry,
salt: 5678,
recipient: payable(taker),
strategyData: swapData
});

defaultTakerPermit = getTokenlonPermit2Data(taker, takerPrivateKey, defaultGSData.takerToken, address(genericSwap));

IUniswapRouterV2 router = IUniswapRouterV2(UNISWAP_V2_ADDRESS);
uint256[] memory amounts = router.getAmountsOut(defaultGSData.takerTokenAmount, defaultPath);
uint256 expectedOut = amounts[amounts.length - 1];
// update defaultGSData
defaultGSData.makerTokenAmount = expectedOut;
defaultGSData.minMakerTokenAmount = (expectedOut * 95) / 100; // default 5% slippage tolerance
}

function testGenericSwapWithUniswap() public {
Expand Down
3 changes: 1 addition & 2 deletions test/forkMainnet/LimitOrderSwap/CoordinatedTaker.t.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { IUniswapRouterV2 } from "contracts/interfaces/IUniswapRouterV2.sol";
import { ILimitOrderSwap } from "contracts/interfaces/ILimitOrderSwap.sol";
import { ICoordinatedTaker } from "contracts/interfaces/ICoordinatedTaker.sol";
import { IWETH } from "contracts/interfaces/IWETH.sol";
Expand All @@ -25,7 +24,7 @@ contract CoordinatedTakerTest is LimitOrderSwapTest {
address user = vm.addr(userPrivateKey);

address[] tokenList = [USDC_ADDRESS, USDT_ADDRESS, DAI_ADDRESS, WETH_ADDRESS, WBTC_ADDRESS];
address[] ammList = [UNISWAP_V2_ADDRESS, SUSHISWAP_ADDRESS];
address[] ammList = [UNISWAP_SWAP_ROUTER_02_ADDRESS, SUSHISWAP_ADDRESS];

uint256 crdPrivateKey = uint256(2);
address coordinator = vm.addr(crdPrivateKey);
Expand Down
9 changes: 4 additions & 5 deletions test/forkMainnet/LimitOrderSwap/Fill.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ pragma solidity 0.8.17;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import { IUniswapRouterV2 } from "contracts/interfaces/IUniswapRouterV2.sol";
import { ILimitOrderSwap } from "contracts/interfaces/ILimitOrderSwap.sol";
import { Constant } from "contracts/libraries/Constant.sol";
import { LimitOrder, getLimitOrderHash } from "contracts/libraries/LimitOrder.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { UniswapV2Library } from "test/utils/UniswapV2Library.sol";
import { LimitOrderSwapTest } from "test/forkMainnet/LimitOrderSwap/Setup.t.sol";
import { MockStrategy } from "test/mocks/MockStrategy.sol";

Expand Down Expand Up @@ -74,17 +74,16 @@ contract FillTest is LimitOrderSwapTest {
uint256 fee = (order.makerTokenAmount * defaultFeeFactor) / Constant.BPS_MAX;
{
// update order takerTokenAmount by AMM quote
IUniswapRouterV2 router = IUniswapRouterV2(UNISWAP_V2_ADDRESS);
uint256[] memory amounts = router.getAmountsOut(defaultOrder.makerTokenAmount - fee, defaultAMMPath);
uint256[] memory amounts = UniswapV2Library.getAmountsOut(defaultOrder.makerTokenAmount - fee, defaultAMMPath);
order.takerTokenAmount = amounts[amounts.length - 1];
}

bytes memory makerSig = signLimitOrder(makerPrivateKey, order, address(limitOrderSwap));

bytes memory extraAction;
{
bytes memory makerSpecificData = abi.encode(defaultExpiry, defaultAMMPath);
bytes memory strategyData = abi.encode(UNISWAP_V2_ADDRESS, makerSpecificData);
bytes memory makerSpecificData = abi.encode(defaultAMMPath);
bytes memory strategyData = abi.encode(UNISWAP_SWAP_ROUTER_02_ADDRESS, makerSpecificData);
extraAction = abi.encode(address(mockLimitOrderTaker), strategyData);
}

Expand Down
4 changes: 2 additions & 2 deletions test/forkMainnet/LimitOrderSwap/Setup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ contract LimitOrderSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelp
allowanceTarget = new AllowanceTarget(allowanceTargetOwner, trusted);

limitOrderSwap = new LimitOrderSwap(limitOrderOwner, UNISWAP_PERMIT2_ADDRESS, address(allowanceTarget), IWETH(WETH_ADDRESS), feeCollector);
mockLimitOrderTaker = new MockLimitOrderTaker(walletOwner, UNISWAP_V2_ADDRESS);
mockLimitOrderTaker = new MockLimitOrderTaker(walletOwner, UNISWAP_SWAP_ROUTER_02_ADDRESS);

deal(maker, 100 ether);
setTokenBalanceAndApprove(maker, UNISWAP_PERMIT2_ADDRESS, tokens, 100000);
Expand All @@ -76,7 +76,7 @@ contract LimitOrderSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelp
tokenList[0] = DAI_ADDRESS;
tokenList[1] = USDT_ADDRESS;
vm.startPrank(walletOwner);
mockLimitOrderTaker.setAllowance(tokenList, UNISWAP_V2_ADDRESS);
mockLimitOrderTaker.setAllowance(tokenList, UNISWAP_SWAP_ROUTER_02_ADDRESS);
vm.stopPrank();

defaultOrder = LimitOrder({
Expand Down
53 changes: 22 additions & 31 deletions test/forkMainnet/SmartOrderStrategy/AMMs.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@ 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 { IUniswapRouterV2 } from "contracts/interfaces/IUniswapRouterV2.sol";
import { ICurveFiV2 } from "contracts/interfaces/ICurveFiV2.sol";
import { ISmartOrderStrategy } from "contracts/interfaces/ISmartOrderStrategy.sol";
import { IUniswapSwapRouter02 } from "contracts/interfaces/IUniswapSwapRouter02.sol";
import { Constant } from "contracts/libraries/Constant.sol";
import { BalanceSnapshot, Snapshot } from "test/utils/BalanceSnapshot.sol";
import { UniswapV2Library } from "test/utils/UniswapV2Library.sol";

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

function testUniswapV2WithoutAmountReplace() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapRouterV2.swapExactTokensForTokens.selector,
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0, // minOutputAmount
defaultUniV2Path,
address(smartOrderStrategy),
defaultExpiry
address(smartOrderStrategy)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_V2_ADDRESS,
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: defaultInputToken,
inputRatio: 0, // zero ratio indicate no replacement
dataOffset: 0,
Expand All @@ -36,8 +36,7 @@ contract AMMsTest is SmartOrderStrategyTest {
bytes memory data = abi.encode(operations);

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

vm.startPrank(genericSwap, genericSwap);
Expand All @@ -53,16 +52,15 @@ contract AMMsTest is SmartOrderStrategyTest {

function testUniswapV2WithAmountReplace() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapRouterV2.swapExactTokensForTokens.selector,
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0,
defaultUniV2Path,
address(smartOrderStrategy),
defaultExpiry
address(smartOrderStrategy)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_V2_ADDRESS,
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: defaultInputToken,
inputRatio: defaultInputRatio,
dataOffset: uint128(4 + 32), // add 32 bytes of length prefix
Expand All @@ -73,8 +71,7 @@ contract AMMsTest is SmartOrderStrategyTest {

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

vm.startPrank(genericSwap, genericSwap);
Expand All @@ -90,16 +87,15 @@ contract AMMsTest is SmartOrderStrategyTest {

function testUniswapV2WithMaxAmountReplace() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapRouterV2.swapExactTokensForTokens.selector,
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0,
defaultUniV2Path,
address(smartOrderStrategy),
defaultExpiry
address(smartOrderStrategy)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](1);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_V2_ADDRESS,
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
Expand All @@ -112,8 +108,7 @@ contract AMMsTest is SmartOrderStrategyTest {
uint256 actualInputAmount = 5678;

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

vm.startPrank(genericSwap, genericSwap);
Expand All @@ -130,16 +125,15 @@ contract AMMsTest is SmartOrderStrategyTest {

function testUniswapV2WithWETHUnwrap() public {
bytes memory uniswapData = abi.encodeWithSelector(
IUniswapRouterV2.swapExactTokensForTokens.selector,
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0, // minOutputAmount
defaultUniV2Path,
address(smartOrderStrategy),
defaultExpiry
address(smartOrderStrategy)
);
ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](2);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_V2_ADDRESS,
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: defaultInputToken,
inputRatio: 0, // zero ratio indicate no replacement
dataOffset: 0,
Expand All @@ -149,8 +143,7 @@ contract AMMsTest is SmartOrderStrategyTest {
bytes memory data = abi.encode(operations);

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

// set output token as ETH
Expand All @@ -172,17 +165,15 @@ contract AMMsTest is SmartOrderStrategyTest {
// Curve : WETH -> USDT

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

bytes memory uniswapData = abi.encodeWithSelector(
IUniswapRouterV2.swapExactTokensForTokens.selector,
IUniswapSwapRouter02.swapExactTokensForTokens.selector,
defaultInputAmount,
0, // minOutputAmount
defaultUniV2Path,
address(smartOrderStrategy),
defaultExpiry
address(smartOrderStrategy)
);

// exhange function selector : 0x5b41b908
Expand All @@ -192,7 +183,7 @@ contract AMMsTest is SmartOrderStrategyTest {

ISmartOrderStrategy.Operation[] memory operations = new ISmartOrderStrategy.Operation[](2);
operations[0] = ISmartOrderStrategy.Operation({
dest: UNISWAP_V2_ADDRESS,
dest: UNISWAP_SWAP_ROUTER_02_ADDRESS,
inputToken: USDC_ADDRESS,
inputRatio: 0, // zero ratio indicate no replacement
dataOffset: 0,
Expand Down
2 changes: 1 addition & 1 deletion test/forkMainnet/SmartOrderStrategy/Setup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract SmartOrderStrategyTest is Test, Tokens, BalanceUtil {
bytes defaultOpsData;
address[] defaultUniV2Path = [USDC_ADDRESS, WETH_ADDRESS];
address[] tokenList = [USDT_ADDRESS, USDC_ADDRESS, WETH_ADDRESS, WBTC_ADDRESS];
address[] ammList = [UNISWAP_V2_ADDRESS, SUSHISWAP_ADDRESS, CURVE_TRICRYPTO2_POOL_ADDRESS];
address[] ammList = [UNISWAP_SWAP_ROUTER_02_ADDRESS, SUSHISWAP_ADDRESS, CURVE_TRICRYPTO2_POOL_ADDRESS];

SmartOrderStrategy smartOrderStrategy;

Expand Down
Loading

0 comments on commit 66bfe17

Please sign in to comment.