fix(univ4): Append callback data instead of prepending
Bring back tests on the executor level. This way the executor can actually be used alone --- don't change below this line --- ENG-4222 Took 12 minutes
This commit is contained in:
@@ -449,9 +449,9 @@ contract TychoRouter is
|
|||||||
returns (bytes memory)
|
returns (bytes memory)
|
||||||
{
|
{
|
||||||
require(data.length >= 20, "Invalid data length");
|
require(data.length >= 20, "Invalid data length");
|
||||||
address executor = address(uint160(bytes20(data[0:20])));
|
bytes4 selector = bytes4(data[data.length - 4:]);
|
||||||
bytes4 selector = bytes4(data[20:24]);
|
address executor = address(uint160(bytes20(data[data.length - 24:data.length - 4])));
|
||||||
bytes memory protocolData = data[24:];
|
bytes memory protocolData = data[:data.length - 24];
|
||||||
|
|
||||||
if (!executors[executor]) {
|
if (!executors[executor]) {
|
||||||
revert ExecutionDispatcher__UnapprovedExecutor();
|
revert ExecutionDispatcher__UnapprovedExecutor();
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {V4Router} from "@uniswap/v4-periphery/src/V4Router.sol";
|
|||||||
import {Actions} from "@uniswap/v4-periphery/src/libraries/Actions.sol";
|
import {Actions} from "@uniswap/v4-periphery/src/libraries/Actions.sol";
|
||||||
import {IV4Router} from "@uniswap/v4-periphery/src/interfaces/IV4Router.sol";
|
import {IV4Router} from "@uniswap/v4-periphery/src/interfaces/IV4Router.sol";
|
||||||
import {PathKey} from "@uniswap/v4-periphery/src/libraries/PathKey.sol";
|
import {PathKey} from "@uniswap/v4-periphery/src/libraries/PathKey.sol";
|
||||||
import "lib/forge-std/src/console.sol";
|
|
||||||
|
|
||||||
error UniswapV4Executor__InvalidDataLength();
|
error UniswapV4Executor__InvalidDataLength();
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ contract UniswapV4Executor is IExecutor, V4Router {
|
|||||||
UniswapV4Executor.UniswapV4Pool[] memory pools
|
UniswapV4Executor.UniswapV4Pool[] memory pools
|
||||||
) = _decodeData(data);
|
) = _decodeData(data);
|
||||||
|
|
||||||
bytes memory fullData;
|
bytes memory swapData;
|
||||||
if (pools.length == 1) {
|
if (pools.length == 1) {
|
||||||
PoolKey memory key = PoolKey({
|
PoolKey memory key = PoolKey({
|
||||||
currency0: Currency.wrap(zeroForOne ? tokenIn : tokenOut),
|
currency0: Currency.wrap(zeroForOne ? tokenIn : tokenOut),
|
||||||
@@ -75,9 +74,8 @@ contract UniswapV4Executor is IExecutor, V4Router {
|
|||||||
);
|
);
|
||||||
params[1] = abi.encode(key.currency0, amountIn);
|
params[1] = abi.encode(key.currency0, amountIn);
|
||||||
params[2] = abi.encode(key.currency1, amountOutMin);
|
params[2] = abi.encode(key.currency1, amountOutMin);
|
||||||
bytes memory swapData = abi.encode(actions, params);
|
swapData = abi.encode(actions, params);
|
||||||
fullData =
|
|
||||||
abi.encodePacked(callbackExecutor, callbackSelector, swapData);
|
|
||||||
} else {
|
} else {
|
||||||
PathKey[] memory path = new PathKey[](pools.length);
|
PathKey[] memory path = new PathKey[](pools.length);
|
||||||
for (uint256 i = 0; i < pools.length; i++) {
|
for (uint256 i = 0; i < pools.length; i++) {
|
||||||
@@ -109,11 +107,10 @@ contract UniswapV4Executor is IExecutor, V4Router {
|
|||||||
);
|
);
|
||||||
params[1] = abi.encode(currencyIn, amountIn);
|
params[1] = abi.encode(currencyIn, amountIn);
|
||||||
params[2] = abi.encode(Currency.wrap(tokenOut), amountOutMin);
|
params[2] = abi.encode(Currency.wrap(tokenOut), amountOutMin);
|
||||||
bytes memory swapData = abi.encode(actions, params);
|
swapData = abi.encode(actions, params);
|
||||||
fullData =
|
|
||||||
abi.encodePacked(callbackExecutor, callbackSelector, swapData);
|
|
||||||
}
|
}
|
||||||
|
bytes memory fullData =
|
||||||
|
abi.encodePacked( swapData, callbackExecutor, callbackSelector);
|
||||||
uint256 tokenOutBalanceBefore;
|
uint256 tokenOutBalanceBefore;
|
||||||
|
|
||||||
tokenOutBalanceBefore = tokenOut == address(0)
|
tokenOutBalanceBefore = tokenOut == address(0)
|
||||||
|
|||||||
@@ -98,4 +98,80 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
assertEq(decodedPools[1].fee, pool2Fee);
|
assertEq(decodedPools[1].fee, pool2Fee);
|
||||||
assertEq(decodedPools[1].tickSpacing, tickSpacing2);
|
assertEq(decodedPools[1].tickSpacing, tickSpacing2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testSingleSwap() public {
|
||||||
|
uint256 amountIn = 100 ether;
|
||||||
|
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
||||||
|
uint256 usdeBalanceBeforePool = USDE.balanceOf(poolManager);
|
||||||
|
uint256 usdeBalanceBeforeSwapExecutor =
|
||||||
|
USDE.balanceOf(address(uniswapV4Exposed));
|
||||||
|
|
||||||
|
UniswapV4Executor.UniswapV4Pool[] memory pools =
|
||||||
|
new UniswapV4Executor.UniswapV4Pool[](1);
|
||||||
|
pools[0] = UniswapV4Executor.UniswapV4Pool({
|
||||||
|
intermediaryToken: USDT_ADDR,
|
||||||
|
fee: uint24(100),
|
||||||
|
tickSpacing: int24(1)
|
||||||
|
});
|
||||||
|
|
||||||
|
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||||
|
USDE_ADDR,
|
||||||
|
USDT_ADDR,
|
||||||
|
uint256(1),
|
||||||
|
true,
|
||||||
|
address(uniswapV4Exposed),
|
||||||
|
SafeCallback.unlockCallback.selector,
|
||||||
|
pools
|
||||||
|
);
|
||||||
|
|
||||||
|
uint256 amountOut = uniswapV4Exposed.swap(amountIn, data);
|
||||||
|
assertEq(USDE.balanceOf(poolManager), usdeBalanceBeforePool + amountIn);
|
||||||
|
assertEq(
|
||||||
|
USDE.balanceOf(address(uniswapV4Exposed)),
|
||||||
|
usdeBalanceBeforeSwapExecutor - amountIn
|
||||||
|
);
|
||||||
|
assertTrue(USDT.balanceOf(address(uniswapV4Exposed)) == amountOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testMultipleSwap() public {
|
||||||
|
// USDE -> USDT -> WBTC
|
||||||
|
uint256 amountIn = 100 ether;
|
||||||
|
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
||||||
|
uint256 usdeBalanceBeforePool = USDE.balanceOf(poolManager);
|
||||||
|
uint256 usdeBalanceBeforeSwapExecutor =
|
||||||
|
USDE.balanceOf(address(uniswapV4Exposed));
|
||||||
|
|
||||||
|
|
||||||
|
UniswapV4Executor.UniswapV4Pool[] memory pools =
|
||||||
|
new UniswapV4Executor.UniswapV4Pool[](2);
|
||||||
|
pools[0] = UniswapV4Executor.UniswapV4Pool({
|
||||||
|
intermediaryToken: USDT_ADDR,
|
||||||
|
fee: uint24(100),
|
||||||
|
tickSpacing: int24(1)
|
||||||
|
});
|
||||||
|
pools[1] = UniswapV4Executor.UniswapV4Pool({
|
||||||
|
intermediaryToken: WBTC_ADDR,
|
||||||
|
fee: uint24(3000),
|
||||||
|
tickSpacing: int24(60)
|
||||||
|
});
|
||||||
|
|
||||||
|
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||||
|
USDE_ADDR,
|
||||||
|
WBTC_ADDR,
|
||||||
|
uint256(1),
|
||||||
|
true,
|
||||||
|
address(uniswapV4Exposed),
|
||||||
|
SafeCallback.unlockCallback.selector,
|
||||||
|
pools
|
||||||
|
);
|
||||||
|
|
||||||
|
uint256 amountOut = uniswapV4Exposed.swap(amountIn, data);
|
||||||
|
assertEq(USDE.balanceOf(poolManager), usdeBalanceBeforePool + amountIn);
|
||||||
|
assertEq(
|
||||||
|
USDE.balanceOf(address(uniswapV4Exposed)),
|
||||||
|
usdeBalanceBeforeSwapExecutor - amountIn
|
||||||
|
);
|
||||||
|
assertTrue(IERC20(WBTC_ADDR).balanceOf(address(uniswapV4Exposed)) == amountOut);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user