feat: add cyclicSwapAmountOut tracker in _swap, add split cylic tests
This commit is contained in:
@@ -329,6 +329,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
|
||||
uint256[] memory remainingAmounts = new uint256[](nTokens);
|
||||
uint256[] memory amounts = new uint256[](nTokens);
|
||||
uint256 cyclicSwapAmountOut = 0;
|
||||
amounts[0] = amountIn;
|
||||
remainingAmounts[0] = amountIn;
|
||||
|
||||
@@ -345,13 +346,15 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
||||
currentAmountOut = _callExecutor(
|
||||
swapData.executor(), currentAmountIn, swapData.protocolData()
|
||||
);
|
||||
amounts[tokenOutIndex] = tokenOutIndex == 0
|
||||
? currentAmountOut
|
||||
: amounts[tokenOutIndex] + currentAmountOut;
|
||||
if (tokenOutIndex == 0) {
|
||||
cyclicSwapAmountOut += currentAmountOut;
|
||||
} else {
|
||||
amounts[tokenOutIndex] += currentAmountOut;
|
||||
}
|
||||
remainingAmounts[tokenOutIndex] += currentAmountOut;
|
||||
remainingAmounts[tokenInIndex] -= currentAmountIn;
|
||||
}
|
||||
return amounts[tokenOutIndex];
|
||||
return tokenOutIndex == 0 ? cyclicSwapAmountOut : amounts[tokenOutIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,6 +45,7 @@ contract Constants is Test, BaseConstants {
|
||||
address DAI_USDC_POOL = 0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5;
|
||||
address WETH_WBTC_POOL = 0xBb2b8038a1640196FbE3e38816F3e67Cba72D940;
|
||||
address USDC_WBTC_POOL = 0x004375Dff511095CC5A197A54140a24eFEF3A416;
|
||||
address USDC_WETH_USV2 = 0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc;
|
||||
|
||||
// Uniswap v3
|
||||
address USV3_FACTORY_ETHEREUM = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
|
||||
|
||||
@@ -1195,26 +1195,26 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
function testCyclicSequentialSwap() public {
|
||||
// This test has start and end tokens that are the same
|
||||
// The flow is:
|
||||
// USDC -> WETH -> USDC -> WETH -> USDC using two pools, and four swaps
|
||||
// USDC -> WETH -> USDC using two pools
|
||||
uint256 amountIn = 100 * 10 ** 6;
|
||||
deal(USDC_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory usdcWethPoolOneZeroForOneData = encodeUniswapV3Swap(
|
||||
bytes memory usdcWethV3Pool1ZeroOneData = encodeUniswapV3Swap(
|
||||
USDC_ADDR, WETH_ADDR, tychoRouterAddr, USDC_WETH_USV3, true
|
||||
);
|
||||
|
||||
bytes memory usdcWethPoolTwoOneForZeroData = encodeUniswapV3Swap(
|
||||
bytes memory usdcWethV3Pool2OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3_2, false
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](4);
|
||||
bytes[] memory swaps = new bytes[](2);
|
||||
// USDC -> WETH
|
||||
swaps[0] = encodeSwap(
|
||||
uint8(0),
|
||||
uint8(1),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethPoolOneZeroForOneData
|
||||
usdcWethV3Pool1ZeroOneData
|
||||
);
|
||||
// WETH -> USDC
|
||||
swaps[1] = encodeSwap(
|
||||
@@ -1222,30 +1222,14 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
uint8(0),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethPoolTwoOneForZeroData
|
||||
);
|
||||
// USDC -> WETH
|
||||
swaps[2] = encodeSwap(
|
||||
uint8(0),
|
||||
uint8(1),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethPoolOneZeroForOneData
|
||||
);
|
||||
// WETH -> USDC
|
||||
swaps[3] = encodeSwap(
|
||||
uint8(1),
|
||||
uint8(0),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethPoolTwoOneForZeroData
|
||||
usdcWethV3Pool2OneZeroData
|
||||
);
|
||||
|
||||
tychoRouter.exposedSwap(amountIn, 2, pleEncode(swaps));
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99778590);
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99889294);
|
||||
}
|
||||
|
||||
function testCyclicSplitSwap() public {
|
||||
function testSplitInputCyclicSwap() public {
|
||||
// This test has start and end tokens that are the same
|
||||
// The flow is:
|
||||
// ┌─── WETH (Pool 1) ───┐
|
||||
@@ -1259,18 +1243,18 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
uint256 amountIn = 100 * 10 ** 6;
|
||||
deal(USDC_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory usdcWethPoolOneZeroForOneData = encodeUniswapV3Swap(
|
||||
bytes memory usdcWethV3Pool1ZeroOneData = encodeUniswapV3Swap(
|
||||
USDC_ADDR, WETH_ADDR, tychoRouterAddr, USDC_WETH_USV3, true
|
||||
);
|
||||
bytes memory usdcWethPoolOneOneForZeroData = encodeUniswapV3Swap(
|
||||
bytes memory usdcWethV3Pool1OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3, false
|
||||
);
|
||||
|
||||
bytes memory usdcWethPoolTwoZeroForOneData = encodeUniswapV3Swap(
|
||||
bytes memory usdcWethV3Pool2ZeroOneData = encodeUniswapV3Swap(
|
||||
USDC_ADDR, WETH_ADDR, tychoRouterAddr, USDC_WETH_USV3_2, true
|
||||
);
|
||||
|
||||
bytes memory usdcWethPoolTwoOneForZeroData = encodeUniswapV3Swap(
|
||||
bytes memory usdcWethV3Pool2OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3_2, false
|
||||
);
|
||||
|
||||
@@ -1281,7 +1265,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
uint8(1),
|
||||
(0xffffff * 60) / 100, // 60%
|
||||
address(usv3Executor),
|
||||
usdcWethPoolOneZeroForOneData
|
||||
usdcWethV3Pool1ZeroOneData
|
||||
);
|
||||
// WETH -> USDC
|
||||
swaps[1] = encodeSwap(
|
||||
@@ -1289,7 +1273,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
uint8(0),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethPoolTwoOneForZeroData
|
||||
usdcWethV3Pool2OneZeroData
|
||||
);
|
||||
|
||||
// USDC -> WETH
|
||||
@@ -1298,7 +1282,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
uint8(1),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethPoolTwoZeroForOneData
|
||||
usdcWethV3Pool2ZeroOneData
|
||||
);
|
||||
|
||||
// WETH -> USDC
|
||||
@@ -1307,12 +1291,63 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
||||
uint8(0),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethPoolOneOneForZeroData
|
||||
usdcWethV3Pool1OneZeroData
|
||||
);
|
||||
tychoRouter.exposedSwap(amountIn, 2, pleEncode(swaps));
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99345512);
|
||||
}
|
||||
|
||||
function testSplitOutputCyclicSwap() public {
|
||||
// This test has start and end tokens that are the same
|
||||
// The flow is:
|
||||
// ┌─── WETH (Pool 2, 60% split) ───┐
|
||||
// │ │
|
||||
// USDC ----─┤ ├─> USDC
|
||||
// │ │
|
||||
// └─── WETH (Pool 2, the rest) ───┘
|
||||
//
|
||||
uint256 amountIn = 100 * 10 ** 6;
|
||||
deal(USDC_ADDR, tychoRouterAddr, amountIn);
|
||||
|
||||
bytes memory usdcWethV2Data = encodeUniswapV2Swap(
|
||||
USDC_ADDR, USDC_WETH_USV2, tychoRouterAddr, true
|
||||
);
|
||||
|
||||
bytes memory usdcWethV3Pool1OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3, false
|
||||
);
|
||||
|
||||
bytes memory usdcWethV3Pool2OneZeroData = encodeUniswapV3Swap(
|
||||
WETH_ADDR, USDC_ADDR, tychoRouterAddr, USDC_WETH_USV3_2, false
|
||||
);
|
||||
|
||||
bytes[] memory swaps = new bytes[](3);
|
||||
// USDC -> WETH
|
||||
swaps[0] = encodeSwap(
|
||||
uint8(0), uint8(1), uint24(0), address(usv2Executor), usdcWethV2Data
|
||||
);
|
||||
// WETH -> USDC
|
||||
swaps[1] = encodeSwap(
|
||||
uint8(1),
|
||||
uint8(0),
|
||||
(0xffffff * 60) / 100,
|
||||
address(usv3Executor),
|
||||
usdcWethV3Pool1OneZeroData
|
||||
);
|
||||
|
||||
// WETH -> USDC
|
||||
swaps[2] = encodeSwap(
|
||||
uint8(1),
|
||||
uint8(0),
|
||||
uint24(0),
|
||||
address(usv3Executor),
|
||||
usdcWethV3Pool2OneZeroData
|
||||
);
|
||||
|
||||
tychoRouter.exposedSwap(amountIn, 2, pleEncode(swaps));
|
||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 99525908);
|
||||
}
|
||||
|
||||
// Base Network Tests
|
||||
// Make sure to set the RPC_URL to base network
|
||||
function testSwapSingleBase() public {
|
||||
|
||||
Reference in New Issue
Block a user