fix(Bebop): Fix encoding and tests

Misc: Fix revert condition in UniswapXFiller

Took 1 hour 20 minutes
This commit is contained in:
Diana Carvalho
2025-08-13 15:11:43 +01:00
parent 7024da395d
commit e79347842f
13 changed files with 96 additions and 791 deletions

View File

@@ -24,9 +24,6 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
/// @notice Bebop-specific errors
error BebopExecutor__InvalidDataLength();
error BebopExecutor__InvalidInput();
error BebopExecutor__InvalidSignatureLength();
error BebopExecutor__InvalidSignatureType();
error BebopExecutor__ZeroAddress();
/// @notice The Bebop settlement contract address
@@ -78,17 +75,14 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
}
// Check the receiver's balance before the swap
uint256 balanceBefore = _balanceOf(tokenOut, receiver);
// Execute the swap with the forwarded calldata
uint256 ethValue = tokenIn == address(0) ? givenAmount : 0;
// Use OpenZeppelin's Address library for safe call with value
// This will revert if the call fails
// slither-disable-next-line unused-return
bebopSettlement.functionCallWithValue(finalCalldata, ethValue);
// Calculate actual amount received by the receiver
uint256 balanceAfter = _balanceOf(tokenOut, receiver);
calculatedAmount = balanceAfter - balanceBefore;
}
@@ -149,6 +143,7 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
}
// Use assembly to modify the filledTakerAmount at the correct position
// slither-disable-next-line assembly
assembly {
// Get pointer to the data portion of the bytes array
let dataPtr := add(bebopCalldata, 0x20)

View File

@@ -60,10 +60,9 @@ contract UniswapXFiller is AccessControl, IReactorCallback {
ResolvedOrder[] calldata resolvedOrders,
bytes calldata callbackData
) external onlyRole(REACTOR_ROLE) {
require(
resolvedOrders.length == 1,
UniswapXFiller__BatchExecutionNotSupported()
);
if (resolvedOrders.length != 1) {
revert UniswapXFiller__BatchExecutionNotSupported();
}
ResolvedOrder memory order = resolvedOrders[0];

View File

@@ -27,26 +27,4 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup {
assertTrue(success, "Call Failed");
assertEq(balanceAfter - balanceBefore, 732214216964381330);
}
function testSingleUSV4IntegrationInputETH() public {
// Test created with calldata from our router encoder.
// Performs a single swap from ETH to PEPE without wrapping or unwrapping
//
// ETH ───(USV4)──> PEPE
//
deal(ALICE, 1 ether);
uint256 balanceBefore = IERC20(PEPE_ADDR).balanceOf(ALICE);
bytes memory callData =
loadCallDataFromFile("test_single_encoding_strategy_usv4_eth_in");
(bool success,) = tychoRouterAddr.call{value: 1 ether}(callData);
vm.stopPrank();
uint256 balanceAfter = IERC20(PEPE_ADDR).balanceOf(ALICE);
assertTrue(success, "Call Failed");
assertEq(balanceAfter - balanceBefore, 235610487387677804636755778);
}
}

View File

@@ -513,48 +513,4 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup {
assertTrue(success, "Call Failed");
assertEq(balanceAfter - balanceBefore, 1404194006633772805);
}
// function testUSV3BebopIntegration() public {
// // Performs a sequential swap from WETH to ONDO through USDC using USV3 and Bebop RFQ
// //
// // WETH ──(USV3)──> USDC ───(Bebop RFQ)──> ONDO
//
// // The Bebop order expects:
// // - 200 USDC input -> 237.21 ONDO output
// // - Receiver: 0xc5564C13A157E6240659fb81882A28091add8670
// // - Maker: 0xCe79b081c0c924cb67848723ed3057234d10FC6b
//
// // Now using 0.099 WETH to get approximately 200 USDC from UniswapV3
// uint256 wethAmount = 99000000000000000; // 0.099 WETH
// address orderTaker = 0xc5564C13A157E6240659fb81882A28091add8670; // Must match Bebop order taker
// deal(WETH_ADDR, orderTaker, wethAmount);
// uint256 balanceBefore = IERC20(ONDO_ADDR).balanceOf(orderTaker);
//
// // Fund the Bebop maker with ONDO and approve settlement
// uint256 ondoAmount = 237212396774431060000; // From the real order
// deal(ONDO_ADDR, 0xCe79b081c0c924cb67848723ed3057234d10FC6b, ondoAmount);
// vm.prank(0xCe79b081c0c924cb67848723ed3057234d10FC6b);
// IERC20(ONDO_ADDR).approve(BEBOP_SETTLEMENT, ondoAmount);
//
// // Approve router from the order taker
// vm.startPrank(orderTaker);
// IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max);
// bytes memory callData = loadCallDataFromFile("test_uniswap_v3_bebop");
// (bool success,) = tychoRouterAddr.call(callData);
//
// vm.stopPrank();
//
// uint256 balanceAfter = IERC20(ONDO_ADDR).balanceOf(orderTaker);
//
// assertTrue(success, "Call Failed");
// assertEq(balanceAfter - balanceBefore, ondoAmount);
// assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0);
//
// // With 0.099 WETH input, UniswapV3 produces ~200.15 USDC
// // Bebop order consumes exactly 200 USDC, leaving only dust amount
// uint256 expectedLeftoverUsdc = 153845; // ~0.153845 USDC dust
// assertEq(
// IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), expectedLeftoverUsdc
// );
// }
}

View File

@@ -192,28 +192,6 @@ contract TychoRouterTestSetup is Constants, Permit2TestHelper, TestUtils {
);
}
function encodeBebopSwap(
address tokenIn,
address tokenOut,
RestrictTransferFrom.TransferType transferType,
uint8 partialFillOffset,
uint256 originalAmountIn,
bool approvalNeeded,
address receiver,
bytes memory bebopCalldata
) internal pure returns (bytes memory) {
return abi.encodePacked(
tokenIn,
tokenOut,
uint8(transferType),
partialFillOffset,
originalAmountIn,
approvalNeeded ? uint8(1) : uint8(0),
receiver,
bebopCalldata
);
}
function encodeUniswapV2Swap(
address tokenIn,
address target,

File diff suppressed because one or more lines are too long

View File

@@ -50,34 +50,27 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
}
function testDecodeData() public {
// Fork to ensure consistent setup
vm.createSelectFork(vm.rpcUrl("mainnet"), 22667985);
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorExposed(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// Create a simple bebop calldata
bytes memory bebopCalldata = abi.encodePacked(
bytes4(0x4dcebcba), // swapSingle selector
hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000068470140"
);
uint256 originalAmountIn = 200000000; // 200 USDC
// Create the executor params
bytes memory params = abi.encodePacked(
USDC_ADDR,
ONDO_ADDR,
uint8(RestrictTransferFrom.TransferType.Transfer),
uint8(2), // partialFillOffset for swapSingle (68 = 4 + 2*32)
uint8(2),
originalAmountIn,
true,
address(123),
bebopCalldata
);
// Test decoding
(
address tokenIn,
address tokenOut,
@@ -325,10 +318,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
}
function testInvalidDataLength() public {
// Fork to ensure consistent setup
vm.createSelectFork(vm.rpcUrl("mainnet"), 22667985);
// Deploy Bebop executor with real settlement contract
bebopExecutor =
new BebopExecutorExposed(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
@@ -342,9 +332,9 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
WETH_ADDR,
USDC_ADDR,
uint8(RestrictTransferFrom.TransferType.Transfer),
uint8(2), // partialFillOffset for swapSingle (68 = 4 + 2*32)
uint8(2),
originalAmountIn,
uint8(1), // approvalNeeded: true
true,
address(bebopExecutor),
bebopCalldata
);