diff --git a/foundry/interfaces/ICurveRouter.sol b/foundry/interfaces/ICurveRouter.sol index 57eb17a..357128c 100644 --- a/foundry/interfaces/ICurveRouter.sol +++ b/foundry/interfaces/ICurveRouter.sol @@ -1,28 +1,29 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.26; +/** + * @title Curve Router Interface + * @notice Interface for interacting with Curve's router contract for token swaps across various Curve pools + * @dev This interface allows for executing swaps through Curve's router, which can handle different pool types + */ interface ICurveRouter { - function exchange( - address[11] memory route, - uint256[5][5] memory swapParams, - uint256 amountIn, - uint256 minAmountOut, - address[5] memory pools, - address receiver - ) external payable returns (uint256); - // slither-disable-next-line naming-convention - function get_dy( - address[] memory route, - uint256[] memory swapParams, - uint256 amountIn, - address[] memory pools - ) external view returns (uint256); - - -} - - struct CurveRouterParams { + /** + * @notice Parameters for executing a swap through the Curve router + * @dev This struct encapsulates all necessary parameters for a Curve swap + * @param route Array of addresses representing the swap path (tokens and pools) + * @param swapParams 2D array containing swap parameters for each hop: + * [0]: tokenIn index in the pool + * [1]: tokenOut index in the pool + * [2]: swap type (1 for regular swap) + * [3]: pool type (1-4 depending on the Curve pool implementation) + * [4]: number of coins in the pool + * @param amountIn Amount of input token to swap + * @param minAmountOut Minimum amount of output token to receive + * @param pools Array of pool addresses involved in the swap + * @param receiver Address to receive the output tokens + */ + struct CurveRouterParams { address[11] route; uint256[5][5] swapParams; uint256 amountIn; @@ -31,3 +32,21 @@ interface ICurveRouter { address receiver; } + /** + * @notice Executes a token swap through Curve pools + * @dev This function handles the routing of tokens through one or more Curve pools + * @dev The parameters are encoded in the `CurveRouterParams` struct + * @return Amount of output tokens received from the swap + */ + function exchange( + address[11] memory route, + uint256[5][5] memory swapParams, + uint256 amountIn, + uint256 minAmountOut, + address[5] memory pools, + address receiver + ) external payable returns (uint256); +} + + + diff --git a/foundry/src/executors/CurveExecutor.sol b/foundry/src/executors/CurveExecutor.sol index fc5748b..0010b9a 100644 --- a/foundry/src/executors/CurveExecutor.sol +++ b/foundry/src/executors/CurveExecutor.sol @@ -27,7 +27,7 @@ contract CurveExecutor is IExecutor { payable returns (uint256) { - CurveRouterParams memory params = _decodeData(data); + ICurveRouter.CurveRouterParams memory params = _decodeData(data); if (params.route[0] != ethAddress) { // slither-disable-next-line unused-return IERC20(params.route[0]).approve(address(curveRouter), amountIn); @@ -55,10 +55,8 @@ contract CurveExecutor is IExecutor { function _decodeData(bytes calldata data) internal pure - returns (CurveRouterParams memory params) + returns (ICurveRouter.CurveRouterParams memory params) { - return abi.decode(data, (CurveRouterParams)); + return abi.decode(data, (ICurveRouter.CurveRouterParams)); } - - receive() external payable {} } diff --git a/foundry/test/Constants.sol b/foundry/test/Constants.sol index 567b201..a6905d6 100644 --- a/foundry/test/Constants.sol +++ b/foundry/test/Constants.sol @@ -90,30 +90,16 @@ contract Constants is Test, BaseConstants { 0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9; // Curve - // 3pool - Pool type 1 - address TRIPOOL_USDT_USDC_DAI = 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7; - // Tricrypto - Pool type 3 - address TRICRYPTO_USDC_WBTC_WETH = - 0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B; - // stEth - Pool type 4 + address TRIPOOL = 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7; + address TRICRYPTO_POOL = 0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B; address STETH_POOL = 0xDC24316b9AE028F1497c275EB9192a3Ea0f67022; - // LUSD - Pool type 5 address LUSD_POOL = 0xEd279fDD11cA84bEef15AF5D39BB4d4bEE23F0cA; - // Compound - Pool type 6 address CPOOL = 0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56; - // LDO - Pool type 7 address LDO_POOL = 0x9409280DC1e6D33AB7A8C6EC03e5763FB61772B5; - // CRV - Pool type 8 address CRV_POOL = 0x8301AE4fc9c624d1D396cbDAa1ed877821D7C511; - // AAVE - Pool type 0 address AAVE_POOL = 0xDeBF20617708857ebe4F679508E7b7863a8A8EeE; - - // BASE META POOL - address FRAXPYUSD_ADDR = address(0xA5588F7cdf560811710A2D82D3C9c99769DB1Dcb); - - // Curve pools taken from the substreams - address TRICRYPTO_USDT_WETH_WBTC = - 0xD51a44d3FaE010294C616388b506AcdA1bfAAE46; + address FRAXPYUSD_POOL = address(0xA5588F7cdf560811710A2D82D3C9c99769DB1Dcb); + address TRICRYPTO2_POOL = 0xD51a44d3FaE010294C616388b506AcdA1bfAAE46; address SUSD_POOL = 0xA5407eAE9Ba41422680e2e00537571bcC53efBfD; address FRAX_USDC_POOL = 0xDcEF968d416a41Cdac0ED8702fAC8128A64241A2; address USDE_USDC_POOL = 0x02950460E2b9529D0E00284A5fA2d7bDF3fA4d72; diff --git a/foundry/test/CurveRouterGasTest.t.sol b/foundry/test/CurveRouterGasTest.t.sol index 38c8cf4..7b86995 100644 --- a/foundry/test/CurveRouterGasTest.t.sol +++ b/foundry/test/CurveRouterGasTest.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.26; import {Constants} from "./Constants.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {console} from "forge-std/console.sol"; import {ICurveRouter} from "../interfaces/ICurveRouter.sol"; contract CurveRouterGasTest is Constants { @@ -17,7 +16,7 @@ contract CurveRouterGasTest is Constants { function testCurveRouter() public { address[11] memory route; route[0] = WETH_ADDR; - route[1] = TRICRYPTO_USDC_WBTC_WETH; + route[1] = TRICRYPTO_POOL; route[2] = USDC_ADDR; uint256[5][5] memory swapParams; @@ -35,7 +34,7 @@ contract CurveRouterGasTest is Constants { vm.startPrank(ALICE); IERC20(WETH_ADDR).approve(address(curveRouter), amountIn); - uint256 amountOut = curveRouter.exchange( + curveRouter.exchange( route, swapParams, amountIn, minAmountOut, pools, address(this) ); vm.stopPrank(); diff --git a/foundry/test/executors/CurveExecutor.t.sol b/foundry/test/executors/CurveExecutor.t.sol index 32572cd..9771845 100644 --- a/foundry/test/executors/CurveExecutor.t.sol +++ b/foundry/test/executors/CurveExecutor.t.sol @@ -9,15 +9,21 @@ interface ICurvePool { function coins(uint256 i) external view returns (address); } +// Curve pool registry +// This is the registry that contains the information about the pool +// The naming convention is different because it is in vyper interface MetaRegistry { + // Get the number of coins in the pool function get_n_coins(address pool) external view returns (uint256); + // Get the indices of the coins in the pool function get_coin_indices(address pool, address from, address to) external view returns (int128, int128, bool); } -interface ILendingPool { +// Aave lending pool +interface IAaveLendingPool { function deposit( address asset, uint256 amount, @@ -38,7 +44,7 @@ contract CurveExecutorExposed is CurveExecutor { function decodeParams(bytes calldata data) external pure - returns (CurveRouterParams memory params) + returns (ICurveRouter.CurveRouterParams memory params) { return _decodeData(data); } @@ -58,11 +64,11 @@ contract CurveExecutorTest is Test, Constants { } function testDecodeParams() public view { - address[11] memory route; - route[0] = WETH_ADDR; - route[1] = TRICRYPTO_USDC_WBTC_WETH; - route[2] = USDC_ADDR; + address[11] memory route = + _getRoute(WETH_ADDR, USDC_ADDR, TRICRYPTO_POOL); + // The meta registry does not have information about the pool. + // We manually set the swap params. uint256[5][5] memory swapParams; swapParams[0][0] = 2; // tokenIn Index swapParams[0][1] = 0; // tokenOut Index @@ -78,11 +84,11 @@ contract CurveExecutorTest is Test, Constants { route, swapParams, amountIn, minAmountOut, pools, address(this) ); - CurveRouterParams memory params = + ICurveRouter.CurveRouterParams memory params = curveExecutorExposed.decodeParams(data); assertEq(params.route[0], WETH_ADDR); - assertEq(params.route[1], TRICRYPTO_USDC_WBTC_WETH); + assertEq(params.route[1], TRICRYPTO_POOL); assertEq(params.route[2], USDC_ADDR); assertEq(params.swapParams[0][0], 2); assertEq(params.swapParams[0][1], 0); @@ -90,7 +96,316 @@ contract CurveExecutorTest is Test, Constants { assertEq(params.swapParams[0][3], 3); } - function testCurveSwapPoolType0() public { + // The following pools are unique and do not have a factory + + function testSwapTriPool() public { + address[11] memory route = _getRoute(DAI_ADDR, USDC_ADDR, TRIPOOL); + uint256[5][5] memory swapParams = + _getSwapParams(TRIPOOL, DAI_ADDR, USDC_ADDR, 1, 1); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(DAI_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, swapParams, amountIn, minAmountOut, pools, address(this) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 999796); + assertEq(IERC20(USDC_ADDR).balanceOf(address(this)), amountOut); + } + + function testSwapStEthPool() public { + address[11] memory route = _getRoute(ETH_ADDR, STETH_ADDR, STETH_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(STETH_POOL, ETH_ADDR, STETH_ADDR, 1, 1); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, swapParams, amountIn, minAmountOut, pools, address(this) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertTrue(amountOut >= 1 ether); + assertEq(IERC20(STETH_ADDR).balanceOf(address(this)), amountOut - 1); // Gets 1 wei less than amountOut + } + + function testSwapTricrypto2Pool() public { + address[11] memory route = + _getRoute(WETH_ADDR, WBTC_ADDR, TRICRYPTO2_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(TRICRYPTO2_POOL, WETH_ADDR, WBTC_ADDR, 1, 3); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(WETH_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 2279618); + assertEq( + IERC20(WBTC_ADDR).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + function testSwapSUSDPool() public { + address[11] memory route = _getRoute(USDC_ADDR, SUSD_ADDR, SUSD_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(SUSD_POOL, USDC_ADDR, SUSD_ADDR, 1, 1); + + uint256 amountIn = 100 * 10 ** 6; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(USDC_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 100488101605550214590); + assertEq( + IERC20(SUSD_ADDR).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + function testSwapFraxUsdcPool() public { + address[11] memory route = + _getRoute(FRAX_ADDR, USDC_ADDR, FRAX_USDC_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(FRAX_USDC_POOL, FRAX_ADDR, USDC_ADDR, 1, 1); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(FRAX_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 998096); + assertEq( + IERC20(USDC_ADDR).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + // The following pool is from CryptoSwapNG, deployed by factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf + // - It is a plain pool + + function testSwapUsdeUsdcPool() public { + address[11] memory route = + _getRoute(USDC_ADDR, USDE_ADDR, USDE_USDC_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(USDE_USDC_POOL, USDC_ADDR, USDE_ADDR, 1, 1); + + uint256 amountIn = 100 * 10 ** 6; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(USDC_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 100064812138999986170); + assertEq( + IERC20(USDE_ADDR).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + // The following pool is from CryptoSwapNG, deployed by factory 0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf + // - It is a meta pool + + function testSwapDolaFraxPyusdPool() public { + address[11] memory route = + _getRoute(DOLA_ADDR, FRAXPYUSD_POOL, DOLA_FRAXPYUSD_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(DOLA_FRAXPYUSD_POOL, DOLA_ADDR, FRAXPYUSD_POOL, 1, 1); + + uint256 amountIn = 100 * 10 ** 6; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(DOLA_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 99688991); + assertEq( + IERC20(FRAXPYUSD_POOL).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + // The following pool is from CryptoPool, deployed by factory 0xF18056Bbd320E96A48e3Fbf8bC061322531aac99 + + function testSwapWethXyoPool() public { + address[11] memory route = _getRoute(XYO_ADDR, WETH_ADDR, WETH_XYO_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(WETH_XYO_POOL, XYO_ADDR, WETH_ADDR, 1, 2); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(XYO_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 6081816039338); + assertEq( + IERC20(WETH_ADDR).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + // The following pool is from Tricrypto, deployed by factory 0x0c0e5f2fF0ff18a3be9b835635039256dC4B4963 + + function testSwapTricryptoPool() public { + address[11] memory route = + _getRoute(WETH_ADDR, USDC_ADDR, TRICRYPTO_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(TRICRYPTO_POOL, WETH_ADDR, USDC_ADDR, 1, 3); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(WETH_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, swapParams, amountIn, minAmountOut, pools, address(this) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 1861130973); + assertEq(IERC20(USDC_ADDR).balanceOf(address(this)), amountOut); + } + + // The following pool is from Twocrypto, deployed by factory 0x98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f + + function testSwapUwuWethPool() public { + address[11] memory route = _getRoute(UWU_ADDR, WETH_ADDR, UWU_WETH_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(UWU_WETH_POOL, UWU_ADDR, WETH_ADDR, 1, 2); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(UWU_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 2873786684675); + assertEq( + IERC20(WETH_ADDR).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + // The following pool is from StableSwap, deployed by factory 0x4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d + // - It is a plain pool + + function testSwapCrvusdUsdtPool() public { + address[11] memory route = + _getRoute(CRVUSD_ADDR, USDT_ADDR, CRVUSD_USDT_POOL); + uint256[5][5] memory swapParams = + _getSwapParams(CRVUSD_USDT_POOL, CRVUSD_ADDR, USDT_ADDR, 1, 1); + + uint256 amountIn = 1 ether; + uint256 minAmountOut = 0; + address[5] memory pools; + + deal(CRVUSD_ADDR, address(curveExecutorExposed), amountIn); + bytes memory data = abi.encode( + route, + swapParams, + amountIn, + minAmountOut, + pools, + address(curveExecutorExposed) + ); + + uint256 amountOut = curveExecutorExposed.swap(amountIn, data); + + assertEq(amountOut, 999910); + assertEq( + IERC20(USDT_ADDR).balanceOf(address(curveExecutorExposed)), + amountOut + ); + } + + // The following pools were taken from the old curve executor tests + + function testSwapAavePool() public { address[11] memory route = _getRoute(ADAI_ADDR, AUSDC_ADDR, AAVE_POOL); uint256[5][5] memory swapParams = _getSwapParams(AAVE_POOL, ADAI_ADDR, AUSDC_ADDR, 1, 1); @@ -118,102 +433,11 @@ contract CurveExecutorTest is Test, Constants { ); } - function testCurveSwapPoolType1() public { - address[11] memory route = - _getRoute(DAI_ADDR, USDC_ADDR, TRIPOOL_USDT_USDC_DAI); - uint256[5][5] memory swapParams = - _getSwapParams(TRIPOOL_USDT_USDC_DAI, DAI_ADDR, USDC_ADDR, 1, 1); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(DAI_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, swapParams, amountIn, minAmountOut, pools, address(this) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 999796); - assertEq(IERC20(USDC_ADDR).balanceOf(address(this)), amountOut); - } - - function testCurveSwapPoolType3() public { - address[11] memory route = - _getRoute(WETH_ADDR, USDC_ADDR, TRICRYPTO_USDC_WBTC_WETH); - uint256[5][5] memory swapParams = - _getSwapParams(TRICRYPTO_USDC_WBTC_WETH, WETH_ADDR, USDC_ADDR, 1, 3); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(WETH_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, swapParams, amountIn, minAmountOut, pools, address(this) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 1861130973); - assertEq(IERC20(USDC_ADDR).balanceOf(address(this)), amountOut); - } - - function testCurveSwapPoolType4() public { - address[11] memory route = _getRoute(ETH_ADDR, STETH_ADDR, STETH_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(STETH_POOL, ETH_ADDR, STETH_ADDR, 1, 1); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertTrue(amountOut >= 1 ether); - assertEq( - IERC20(STETH_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - 1 - ); // Gets 1 wei less than amountOut - - // Now reverse the swap - amountIn = amountOut - 1; - route = _getRoute(STETH_ADDR, ETH_ADDR, STETH_POOL); - swapParams = _getSwapParams(STETH_POOL, STETH_ADDR, ETH_ADDR, 1, 1); - - data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(address(curveExecutorExposed).balance, 999800010006950374); - } - - function testCurveSwapPoolType5() public { + function testSwapLusdUsdtPool() public { address[11] memory route = _getRoute(LUSD_ADDR, USDT_ADDR, LUSD_POOL); uint256[5][5] memory swapParams = _getSwapParams(LUSD_POOL, LUSD_ADDR, USDT_ADDR, 2, 1); - // pool.coins(index) reverts, defaulting tokenOut index to 0 - swapParams[0][1] = 3; - uint256 amountIn = 1 ether; uint256 minAmountOut = 0; address[5] memory pools; @@ -237,14 +461,11 @@ contract CurveExecutorTest is Test, Constants { ); } - function testCurveSwapPoolType6() public { + function testSwapCompoundPool() public { address[11] memory route = _getRoute(DAI_ADDR, USDC_ADDR, CPOOL); uint256[5][5] memory swapParams = _getSwapParams(CPOOL, DAI_ADDR, USDC_ADDR, 2, 1); - // pool.coins(index) reverts, defaulting tokenOut index to 0 - swapParams[0][1] = 1; - uint256 amountIn = 1 ether; uint256 minAmountOut = 0; address[5] memory pools; @@ -268,14 +489,11 @@ contract CurveExecutorTest is Test, Constants { ); } - function testCurveSwapPoolType7() public { + function testSwapLdoPool() public { address[11] memory route = _getRoute(WETH_ADDR, LDO_ADDR, LDO_POOL); uint256[5][5] memory swapParams = _getSwapParams(LDO_POOL, WETH_ADDR, LDO_ADDR, 1, 4); - // pool.coins(index) reverts, defaulting tokenOut index to 0 - swapParams[0][1] = 1; - uint256 amountIn = 1 ether; uint256 minAmountOut = 0; address[5] memory pools; @@ -298,7 +516,7 @@ contract CurveExecutorTest is Test, Constants { ); } - function testCurveSwapPoolType8() public { + function testSwapCrvPool() public { address[11] memory route = _getRoute(CRV_ADDR, WETH_ADDR, CRV_POOL); // The registry does not have information about the pool. @@ -333,237 +551,6 @@ contract CurveExecutorTest is Test, Constants { ); } - /// These tests are taken from the substreams - - function testCurveSwapTricrypto2() public { - address[11] memory route = - _getRoute(WETH_ADDR, WBTC_ADDR, TRICRYPTO_USDT_WETH_WBTC); - uint256[5][5] memory swapParams = - _getSwapParams(TRICRYPTO_USDT_WETH_WBTC, WETH_ADDR, WBTC_ADDR, 1, 3); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(WETH_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 2279618); - assertEq( - IERC20(WBTC_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - - function testCurveSwapSUSD() public { - address[11] memory route = _getRoute(USDC_ADDR, SUSD_ADDR, SUSD_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(SUSD_POOL, USDC_ADDR, SUSD_ADDR, 1, 1); - - uint256 amountIn = 100 * 10 ** 6; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(USDC_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 100488101605550214590); - assertEq( - IERC20(SUSD_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - - function testCurveSwapFraxUSDC() public { - address[11] memory route = - _getRoute(FRAX_ADDR, USDC_ADDR, FRAX_USDC_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(FRAX_USDC_POOL, FRAX_ADDR, USDC_ADDR, 1, 1); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(FRAX_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 998096); - assertEq( - IERC20(USDC_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - - function testCurveSwapCryptoSwapNGFactoryPlainPool() public { - address[11] memory route = - _getRoute(USDC_ADDR, USDE_ADDR, USDE_USDC_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(USDE_USDC_POOL, USDC_ADDR, USDE_ADDR, 1, 1); - - uint256 amountIn = 100 * 10 ** 6; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(USDC_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 100064812138999986170); - assertEq( - IERC20(USDE_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - - function testCurveSwapMetaPool() public { - address[11] memory route = - _getRoute(DOLA_ADDR, FRAXPYUSD_ADDR, DOLA_FRAXPYUSD_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(DOLA_FRAXPYUSD_POOL, DOLA_ADDR, FRAXPYUSD_ADDR, 1, 1); - - uint256 amountIn = 100 * 10 ** 6; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(DOLA_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 99688991); - assertEq( - IERC20(FRAXPYUSD_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - - function testCurveSwapWethXyo() public { - address[11] memory route = _getRoute(XYO_ADDR, WETH_ADDR, WETH_XYO_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(WETH_XYO_POOL, XYO_ADDR, WETH_ADDR, 1, 2); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(XYO_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 6081816039338); - assertEq( - IERC20(WETH_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - - function testCurveSwapUwuWeth() public { - address[11] memory route = _getRoute(UWU_ADDR, WETH_ADDR, UWU_WETH_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(UWU_WETH_POOL, UWU_ADDR, WETH_ADDR, 1, 2); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(UWU_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 2873786684675); - assertEq( - IERC20(WETH_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - - function testCurveSwapStableSwapFactoryPlainPool() public { - address[11] memory route = - _getRoute(CRVUSD_ADDR, USDT_ADDR, CRVUSD_USDT_POOL); - uint256[5][5] memory swapParams = - _getSwapParams(CRVUSD_USDT_POOL, CRVUSD_ADDR, USDT_ADDR, 1, 1); - - uint256 amountIn = 1 ether; - uint256 minAmountOut = 0; - address[5] memory pools; - - deal(CRVUSD_ADDR, address(curveExecutorExposed), amountIn); - bytes memory data = abi.encode( - route, - swapParams, - amountIn, - minAmountOut, - pools, - address(curveExecutorExposed) - ); - - uint256 amountOut = curveExecutorExposed.swap(amountIn, data); - - assertEq(amountOut, 999910); - assertEq( - IERC20(USDT_ADDR).balanceOf(address(curveExecutorExposed)), - amountOut - ); - } - function _getRoute(address tokenIn, address tokenOut, address pool) internal pure @@ -582,7 +569,7 @@ contract CurveExecutorTest is Test, Constants { uint256 poolType ) internal view returns (uint256[5][5] memory swapParams) { uint256 nCoins = metaRegistry.get_n_coins(pool); - (int128 coinInIndex, int128 coinOutIndex, bool isMetapool) = + (int128 coinInIndex, int128 coinOutIndex,) = metaRegistry.get_coin_indices(pool, tokenIn, tokenOut); swapParams[0][0] = uint256(int256(coinInIndex)); @@ -594,8 +581,8 @@ contract CurveExecutorTest is Test, Constants { function dealAaveDai() internal { deal(DAI_ADDR, address(curveExecutorExposed), 100_000 * 10 ** 18); - ILendingPool aave = - ILendingPool(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9); + IAaveLendingPool aave = + IAaveLendingPool(0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9); vm.startPrank(address(curveExecutorExposed)); IERC20(DAI_ADDR).approve(address(aave), type(uint256).max);