chore: start implementing test changes related to partialFillOffset and encoded receiver

This commit is contained in:
pedrobergamini
2025-08-05 22:45:48 -03:00
parent 2583e9239e
commit 1336eb5f90
4 changed files with 125 additions and 277 deletions

View File

@@ -114,13 +114,17 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
bytes memory bebopCalldata, bytes memory bebopCalldata,
uint8 partialFillOffset, uint8 partialFillOffset,
uint256 originalFilledTakerAmount, uint256 originalFilledTakerAmount,
bool approvalNeeded bool approvalNeeded,
address receiver
) = _decodeData(data); ) = _decodeData(data);
// Modify the filledTakerAmount in the calldata // Modify the filledTakerAmount in the calldata
// If the filledTakerAmount is the same as the original, the original calldata is returned // If the filledTakerAmount is the same as the original, the original calldata is returned
bytes memory finalCalldata = _modifyFilledTakerAmount( bytes memory finalCalldata = _modifyFilledTakerAmount(
bebopCalldata, givenAmount, originalFilledTakerAmount, partialFillOffset bebopCalldata,
givenAmount,
originalFilledTakerAmount,
partialFillOffset
); );
// Transfer tokens if needed // Transfer tokens if needed
@@ -134,9 +138,8 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max); IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
} }
// Bebop orders specify the receiver, so we need to check the receiver's balance // Check the receiver's balance before the swap
// We'll use the executor's balance since Bebop should send tokens here for the router to collect uint256 balanceBefore = _balanceOf(tokenOut, receiver);
uint256 balanceBefore = _balanceOf(tokenOut, address(this));
// Execute the swap with the forwarded calldata // Execute the swap with the forwarded calldata
uint256 ethValue = tokenIn == address(0) ? givenAmount : 0; uint256 ethValue = tokenIn == address(0) ? givenAmount : 0;
@@ -144,8 +147,8 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
// Use OpenZeppelin's Address library for safe call with value // Use OpenZeppelin's Address library for safe call with value
bebopSettlement.functionCallWithValue(finalCalldata, ethValue); bebopSettlement.functionCallWithValue(finalCalldata, ethValue);
// Calculate actual amount received by the executor // Calculate actual amount received by the receiver
uint256 balanceAfter = _balanceOf(tokenOut, address(this)); uint256 balanceAfter = _balanceOf(tokenOut, receiver);
calculatedAmount = balanceAfter - balanceBefore; calculatedAmount = balanceAfter - balanceBefore;
} }
@@ -160,12 +163,13 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
bytes memory bebopCalldata, bytes memory bebopCalldata,
uint8 partialFillOffset, uint8 partialFillOffset,
uint256 originalFilledTakerAmount, uint256 originalFilledTakerAmount,
bool approvalNeeded bool approvalNeeded,
address receiver
) )
{ {
// Need at least 79 bytes for the minimum fixed fields // Need at least 99 bytes for the minimum fixed fields
// 20 + 20 + 1 + 4 (calldata length) + 1 (offset) + 32 (original amount) + 1 (approval) = 79 // 20 + 20 + 1 + 4 (calldata length) + 1 (offset) + 32 (original amount) + 1 (approval) + 20 (receiver) = 99
if (data.length < 79) revert BebopExecutor__InvalidDataLength(); if (data.length < 99) revert BebopExecutor__InvalidDataLength();
// Decode fixed fields // Decode fixed fields
tokenIn = address(bytes20(data[0:20])); tokenIn = address(bytes20(data[0:20]));
@@ -174,7 +178,7 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
// Get bebop calldata length and validate // Get bebop calldata length and validate
uint32 bebopCalldataLength = uint32(bytes4(data[41:45])); uint32 bebopCalldataLength = uint32(bytes4(data[41:45]));
if (data.length != 79 + bebopCalldataLength) { if (data.length != 99 + bebopCalldataLength) {
revert BebopExecutor__InvalidDataLength(); revert BebopExecutor__InvalidDataLength();
} }
@@ -191,6 +195,11 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
// Extract approval flag // Extract approval flag
approvalNeeded = data[78 + bebopCalldataLength] != 0; approvalNeeded = data[78 + bebopCalldataLength] != 0;
// Extract receiver address
receiver = address(
bytes20(data[79 + bebopCalldataLength:99 + bebopCalldataLength])
);
} }
/// @dev Modifies the filledTakerAmount in the bebop calldata to handle slippage /// @dev Modifies the filledTakerAmount in the bebop calldata to handle slippage
@@ -210,8 +219,9 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
uint256 filledTakerAmountPos = 4 + uint256(partialFillOffset) * 32; uint256 filledTakerAmountPos = 4 + uint256(partialFillOffset) * 32;
// Cap the fill amount at what we actually have available // Cap the fill amount at what we actually have available
uint256 newFilledTakerAmount = uint256 newFilledTakerAmount = originalFilledTakerAmount > givenAmount
originalFilledTakerAmount > givenAmount ? givenAmount : originalFilledTakerAmount; ? givenAmount
: originalFilledTakerAmount;
// If the new filledTakerAmount is the same as the original, return the original calldata // If the new filledTakerAmount is the same as the original, return the original calldata
if (newFilledTakerAmount == originalFilledTakerAmount) { if (newFilledTakerAmount == originalFilledTakerAmount) {

File diff suppressed because one or more lines are too long

View File

@@ -102,7 +102,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32) uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
originalAmountIn, originalAmountIn,
uint8(1) // approvalNeeded: true uint8(1), // approvalNeeded: true
address(123)
); );
// Test decoding // Test decoding
@@ -113,7 +114,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bytes memory decodedBebopCalldata, bytes memory decodedBebopCalldata,
uint8 decodedPartialFillOffset, uint8 decodedPartialFillOffset,
uint256 decodedOriginalAmountIn, uint256 decodedOriginalAmountIn,
bool decodedApprovalNeeded bool decodedApprovalNeeded,
address decodedReceiver
) = bebopExecutor.decodeParams(params); ) = bebopExecutor.decodeParams(params);
assertEq(tokenIn, USDC_ADDR, "tokenIn mismatch"); assertEq(tokenIn, USDC_ADDR, "tokenIn mismatch");
@@ -135,6 +137,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
"originalAmountIn mismatch" "originalAmountIn mismatch"
); );
assertTrue(decodedApprovalNeeded, "approvalNeeded should be true"); assertTrue(decodedApprovalNeeded, "approvalNeeded should be true");
assertEq(decodedReceiver, address(123), "receiver mismatch");
} }
// Single Order Tests // Single Order Tests
@@ -217,18 +220,22 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32) uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
testData.order.taker_amount, // originalAmountIn (matches what encoder would produce) testData.order.taker_amount, // originalAmountIn (matches what encoder would produce)
uint8(1) // approvalNeeded: true uint8(1), // approvalNeeded: true
originalTakerAddress // receiver from order
); );
// Check initial ONDO balance of receiver
uint256 initialOndoBalance = ONDO.balanceOf(originalTakerAddress);
uint256 amountOut = bebopExecutor.swap(testData.amountIn, params); uint256 amountOut = bebopExecutor.swap(testData.amountIn, params);
// Verify results // Verify results
assertEq(amountOut, testData.expectedAmountOut, "Incorrect amount out"); assertEq(amountOut, testData.expectedAmountOut, "Incorrect amount out");
// The harness transfers tokens to the executor to simulate proper flow // Since we're using real order data, tokens go to the original receiver
assertEq( assertEq(
ONDO.balanceOf(address(bebopExecutor)), ONDO.balanceOf(originalTakerAddress) - initialOndoBalance,
testData.expectedAmountOut, testData.expectedAmountOut,
"ONDO should be in executor" "ONDO should be at receiver"
); );
assertEq( assertEq(
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor" USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
@@ -313,9 +320,13 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32) uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
testData.order.taker_amount, // originalAmountIn (full order amount) testData.order.taker_amount, // originalAmountIn (full order amount)
uint8(1) // approvalNeeded: true uint8(1), // approvalNeeded: true
originalTakerAddress // receiver from order
); );
// Check initial ONDO balance of receiver
uint256 initialOndoBalance = ONDO.balanceOf(originalTakerAddress);
uint256 amountOut = bebopExecutor.swap(testData.amountIn, params); uint256 amountOut = bebopExecutor.swap(testData.amountIn, params);
// Verify partial fill results // Verify partial fill results
@@ -324,11 +335,11 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
testData.expectedAmountOut, testData.expectedAmountOut,
"Incorrect partial amount out" "Incorrect partial amount out"
); );
// The harness transfers tokens to the executor to simulate proper flow // Since we're using real order data, tokens go to the original receiver
assertEq( assertEq(
ONDO.balanceOf(address(bebopExecutor)), ONDO.balanceOf(originalTakerAddress) - initialOndoBalance,
testData.expectedAmountOut, testData.expectedAmountOut,
"ONDO should be in executor" "ONDO should be at receiver"
); );
assertEq( assertEq(
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor" USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
@@ -448,9 +459,13 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32) uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
totalTakerAmount, // originalAmountIn totalTakerAmount, // originalAmountIn
uint8(0) // approvalNeeded: false for native ETH uint8(0), // approvalNeeded: false for native ETH
originalTakerAddress // receiver from order
); );
// Check initial USDC balance of receiver
uint256 initialUsdcBalance = USDC.balanceOf(originalTakerAddress);
// Execute the aggregate swap with ETH value // Execute the aggregate swap with ETH value
uint256 amountOut = bebopExecutor.swap{value: totalTakerAmount}( uint256 amountOut = bebopExecutor.swap{value: totalTakerAmount}(
totalTakerAmount, params totalTakerAmount, params
@@ -458,11 +473,11 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
// Verify results // Verify results
assertEq(amountOut, totalMakerAmount, "Incorrect amount out"); assertEq(amountOut, totalMakerAmount, "Incorrect amount out");
// The harness transfers tokens to the executor to simulate proper flow // Since we're using real order data, tokens go to the original receiver
assertEq( assertEq(
USDC.balanceOf(address(bebopExecutor)), USDC.balanceOf(originalTakerAddress) - initialUsdcBalance,
totalMakerAmount, totalMakerAmount,
"USDC should be in executor" "USDC should be at receiver"
); );
// ETH balance check - the harness may have different balance due to test setup // ETH balance check - the harness may have different balance due to test setup
// Just ensure no excessive ETH is stuck // Just ensure no excessive ETH is stuck
@@ -588,9 +603,13 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32) uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
totalTakerAmount, // originalAmountIn (full order amount) totalTakerAmount, // originalAmountIn (full order amount)
uint8(0) // approvalNeeded: false for native ETH uint8(0), // approvalNeeded: false for native ETH
originalTakerAddress // receiver from order
); );
// Check initial USDC balance of receiver
uint256 initialUsdcBalance = USDC.balanceOf(originalTakerAddress);
// Execute the partial aggregate swap with ETH value // Execute the partial aggregate swap with ETH value
uint256 amountOut = bebopExecutor.swap{value: partialFillAmount}( uint256 amountOut = bebopExecutor.swap{value: partialFillAmount}(
partialFillAmount, params partialFillAmount, params
@@ -600,11 +619,11 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
assertEq( assertEq(
amountOut, expectedPartialOutput, "Incorrect partial amount out" amountOut, expectedPartialOutput, "Incorrect partial amount out"
); );
// The harness transfers tokens to the executor to simulate proper flow // Since we're using real order data, tokens go to the original receiver
assertEq( assertEq(
USDC.balanceOf(address(bebopExecutor)), USDC.balanceOf(originalTakerAddress) - initialUsdcBalance,
expectedPartialOutput, expectedPartialOutput,
"USDC should be in executor" "USDC should be at receiver"
); );
// ETH balance check - the harness may have different balance due to test setup // ETH balance check - the harness may have different balance due to test setup
// Just ensure no excessive ETH is stuck // Just ensure no excessive ETH is stuck
@@ -637,7 +656,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32) uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
originalAmountIn, originalAmountIn,
uint8(1) // approvalNeeded: true uint8(1), // approvalNeeded: true
address(bebopExecutor)
); );
// Verify valid params work // Verify valid params work
@@ -713,7 +733,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32) uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
uint256(200000000), // originalAmountIn uint256(200000000), // originalAmountIn
uint8(1) // approvalNeeded: true uint8(1), // approvalNeeded: true
originalTakerAddress // receiver from order
); );
// Deal 200 USDC to the executor // Deal 200 USDC to the executor
@@ -727,16 +748,19 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
vm.prank(maker); vm.prank(maker);
ONDO.approve(BEBOP_SETTLEMENT, expectedAmountOut); ONDO.approve(BEBOP_SETTLEMENT, expectedAmountOut);
// Check initial ONDO balance of receiver
uint256 initialOndoBalance = ONDO.balanceOf(originalTakerAddress);
// Execute the swap // Execute the swap
uint256 amountOut = bebopExecutor.swap(amountIn, protocolData); uint256 amountOut = bebopExecutor.swap(amountIn, protocolData);
// Verify results // Verify results
assertEq(amountOut, expectedAmountOut, "Incorrect amount out"); assertEq(amountOut, expectedAmountOut, "Incorrect amount out");
// The harness transfers tokens to the executor to simulate proper flow // Since we're using historical data, tokens go to the original receiver
assertEq( assertEq(
ONDO.balanceOf(address(bebopExecutor)), ONDO.balanceOf(originalTakerAddress) - initialOndoBalance,
expectedAmountOut, expectedAmountOut,
"ONDO should be in executor" "ONDO should be at receiver"
); );
assertEq( assertEq(
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor" USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
@@ -834,7 +858,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bebopCalldata, bebopCalldata,
uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32) uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
ethAmount, // originalAmountIn ethAmount, // originalAmountIn
uint8(0) // approvalNeeded: false for native ETH uint8(0), // approvalNeeded: false for native ETH
orderTaker // receiver from order
); );
// Fund the two makers from the real transaction with USDC // Fund the two makers from the real transaction with USDC
@@ -854,17 +879,20 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
vm.deal(ALICE, ethAmount); vm.deal(ALICE, ethAmount);
vm.startPrank(ALICE); vm.startPrank(ALICE);
// Check initial USDC balance of receiver
uint256 initialUsdcBalance = IERC20(USDC_ADDR).balanceOf(orderTaker);
// Execute the swap with native ETH // Execute the swap with native ETH
uint256 amountOut = uint256 amountOut =
bebopExecutor.swap{value: ethAmount}(ethAmount, protocolData); bebopExecutor.swap{value: ethAmount}(ethAmount, protocolData);
// Verify results // Verify results
assertEq(amountOut, expAmountOut, "Incorrect amount out"); assertEq(amountOut, expAmountOut, "Incorrect amount out");
// The harness transfers tokens to the executor to simulate proper flow // Since we're using historical data, tokens go to the original receiver
assertEq( assertEq(
IERC20(USDC_ADDR).balanceOf(address(bebopExecutor)), IERC20(USDC_ADDR).balanceOf(orderTaker) - initialUsdcBalance,
expAmountOut, expAmountOut,
"USDC should be in executor" "USDC should be at receiver"
); );
// ETH balance check - the harness may have different balance due to test setup // ETH balance check - the harness may have different balance due to test setup
// Just ensure no excessive ETH is stuck // Just ensure no excessive ETH is stuck
@@ -876,202 +904,6 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
vm.stopPrank(); vm.stopPrank();
} }
// Test exposed_getActualFilledTakerAmount function
function testGetActualFilledTakerAmount_FilledLessThanGiven() public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// When filledTakerAmount < givenAmount
// Should return filledTakerAmount
uint256 givenAmount = 1000e18;
uint256 filledTakerAmount = 700e18;
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(
result,
filledTakerAmount,
"Should return filledTakerAmount when less than givenAmount"
);
}
function testGetActualFilledTakerAmount_FilledGreaterThanGiven() public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// When filledTakerAmount > givenAmount
// Should return givenAmount (capped)
uint256 givenAmount = 500e18;
uint256 filledTakerAmount = 700e18;
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(
result,
givenAmount,
"Should return givenAmount when filledTakerAmount exceeds it"
);
}
function testGetActualFilledTakerAmount_FilledEqualsGiven() public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// When filledTakerAmount == givenAmount
// Should return filledTakerAmount
uint256 givenAmount = 700e18;
uint256 filledTakerAmount = 700e18;
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(
result,
filledTakerAmount,
"Should return filledTakerAmount when equal to givenAmount"
);
}
function testGetActualFilledTakerAmount_ZeroGivenAmount() public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// When givenAmount is 0
// Should always return 0 regardless of filledTakerAmount
uint256 givenAmount = 0;
uint256 filledTakerAmount = 100e18;
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(result, 0, "Should return 0 when givenAmount is 0");
}
function testGetActualFilledTakerAmount_ZeroFilledTakerAmount() public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// When filledTakerAmount is 0 (encoder should prevent this, but test edge case)
// Should return 0
uint256 givenAmount = 1000e18;
uint256 filledTakerAmount = 0;
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(result, 0, "Should return 0 when filledTakerAmount is 0");
}
function testGetActualFilledTakerAmount_SmallAmounts() public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// Test with small amounts (e.g., for tokens with low decimals)
uint256 givenAmount = 100; // 100 units
uint256 filledTakerAmount = 50; // 50 units
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(
result, filledTakerAmount, "Should handle small amounts correctly"
);
// Test when filledTakerAmount exceeds givenAmount
filledTakerAmount = 150;
result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(
result, givenAmount, "Should cap at givenAmount for small amounts"
);
}
function testGetActualFilledTakerAmount_MaxUint256Values() public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
// Test with max uint256 values (edge case)
uint256 givenAmount = type(uint256).max;
uint256 filledTakerAmount = type(uint256).max - 1;
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(
result, filledTakerAmount, "Should handle max values correctly"
);
// Test with filledTakerAmount exceeding givenAmount
givenAmount = type(uint256).max - 100;
filledTakerAmount = type(uint256).max;
result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
assertEq(
result,
givenAmount,
"Should cap at givenAmount even with max filledTakerAmount"
);
}
function testFuzzGetActualFilledTakerAmount(
uint256 givenAmount,
uint256 filledTakerAmount
) public {
// Deploy Bebop executor harness
bebopExecutor =
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
uint256 result = bebopExecutor.exposed_getActualFilledTakerAmount(
givenAmount, filledTakerAmount
);
// Verify the invariants
// Result should be min(givenAmount, filledTakerAmount)
if (filledTakerAmount > givenAmount) {
assertEq(
result,
givenAmount,
"Should return givenAmount when filledTakerAmount > givenAmount"
);
} else {
assertEq(
result,
filledTakerAmount,
"Should return filledTakerAmount when filledTakerAmount <= givenAmount"
);
}
// Result should never exceed givenAmount
assertLe(result, givenAmount, "Result should never exceed givenAmount");
// Result should never exceed filledTakerAmount
assertLe(
result,
filledTakerAmount,
"Result should never exceed filledTakerAmount"
);
}
// Test exposed_modifyFilledTakerAmount function // Test exposed_modifyFilledTakerAmount function
function testModifyFilledTakerAmount_SingleOrder() public { function testModifyFilledTakerAmount_SingleOrder() public {
// Deploy Bebop executor harness // Deploy Bebop executor harness
@@ -1108,7 +940,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bytes memory modifiedCalldata = bebopExecutor bytes memory modifiedCalldata = bebopExecutor
.exposed_modifyFilledTakerAmount( .exposed_modifyFilledTakerAmount(
originalCalldata, givenAmount, originalAmountIn, 12 // partialFillOffset for swapSingle originalCalldata,
givenAmount,
originalAmountIn,
12 // partialFillOffset for swapSingle
); );
// Decode the modified calldata to verify the filledTakerAmount was updated // Decode the modified calldata to verify the filledTakerAmount was updated
@@ -1184,7 +1019,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
bytes memory modifiedCalldata = bebopExecutor bytes memory modifiedCalldata = bebopExecutor
.exposed_modifyFilledTakerAmount( .exposed_modifyFilledTakerAmount(
originalCalldata, givenAmount, originalAmountIn, 2 // partialFillOffset for swapAggregate originalCalldata,
givenAmount,
originalAmountIn,
2 // partialFillOffset for swapAggregate
); );
// Decode the modified calldata to verify the filledTakerAmount was updated // Decode the modified calldata to verify the filledTakerAmount was updated
@@ -1243,7 +1081,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
// So we'll test that it properly sets the value we want // So we'll test that it properly sets the value we want
bytes memory modifiedCalldata = bebopExecutor bytes memory modifiedCalldata = bebopExecutor
.exposed_modifyFilledTakerAmount( .exposed_modifyFilledTakerAmount(
originalCalldata, givenAmount, originalAmountIn, 12 // partialFillOffset for swapSingle originalCalldata,
givenAmount,
originalAmountIn,
12 // partialFillOffset for swapSingle
); );
// Extract the new filledTakerAmount // Extract the new filledTakerAmount
@@ -1259,7 +1100,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
// Normal test - amounts match so calldata should be unchanged // Normal test - amounts match so calldata should be unchanged
bytes memory modifiedCalldata = bebopExecutor bytes memory modifiedCalldata = bebopExecutor
.exposed_modifyFilledTakerAmount( .exposed_modifyFilledTakerAmount(
originalCalldata, givenAmount, originalAmountIn, 12 // partialFillOffset for swapSingle originalCalldata,
givenAmount,
originalAmountIn,
12 // partialFillOffset for swapSingle
); );
assertEq( assertEq(

View File

@@ -60,21 +60,13 @@ contract BebopExecutorHarness is BebopExecutor, Test {
bytes memory bebopCalldata, bytes memory bebopCalldata,
uint8 partialFillOffset, uint8 partialFillOffset,
uint256 originalFilledTakerAmount, uint256 originalFilledTakerAmount,
bool approvalNeeded bool approvalNeeded,
address receiver
) )
{ {
return _decodeData(data); return _decodeData(data);
} }
// No longer needed since we inlined the logic
function exposed_getActualFilledTakerAmount(
uint256 givenAmount,
uint256 filledTakerAmount
) external pure returns (uint256 actualFilledTakerAmount) {
// Inline the simple logic here for backward compatibility
actualFilledTakerAmount = filledTakerAmount > givenAmount ? givenAmount : filledTakerAmount;
}
// Expose the internal modifyFilledTakerAmount function for testing // Expose the internal modifyFilledTakerAmount function for testing
function exposed_modifyFilledTakerAmount( function exposed_modifyFilledTakerAmount(
bytes memory bebopCalldata, bytes memory bebopCalldata,
@@ -83,7 +75,10 @@ contract BebopExecutorHarness is BebopExecutor, Test {
uint8 partialFillOffset uint8 partialFillOffset
) external pure returns (bytes memory) { ) external pure returns (bytes memory) {
return _modifyFilledTakerAmount( return _modifyFilledTakerAmount(
bebopCalldata, givenAmount, originalFilledTakerAmount, partialFillOffset bebopCalldata,
givenAmount,
originalFilledTakerAmount,
partialFillOffset
); );
} }
@@ -102,6 +97,8 @@ contract BebopExecutorHarness is BebopExecutor, Test {
bytes memory bebopCalldata, bytes memory bebopCalldata,
, // partialFillOffset not needed in test harness , // partialFillOffset not needed in test harness
uint256 originalFilledTakerAmount, uint256 originalFilledTakerAmount,
, // approvalNeeded not needed in test harness
// receiver not needed since we extract it from bebop calldata
) = _decodeData(data); ) = _decodeData(data);
// Extract taker address, receiver, and expiry from bebop calldata // Extract taker address, receiver, and expiry from bebop calldata
@@ -139,16 +136,13 @@ contract BebopExecutorHarness is BebopExecutor, Test {
expiry = order.expiry; expiry = order.expiry;
} }
// Inline the simple logic since _getActualFilledTakerAmount was removed uint256 actualFilledTakerAmount = originalFilledTakerAmount
uint256 actualFilledTakerAmount = > givenAmount ? givenAmount : originalFilledTakerAmount;
originalFilledTakerAmount > givenAmount ? givenAmount : originalFilledTakerAmount;
// For testing: transfer tokens from executor to taker address // For testing: transfer tokens from executor to taker address
// This simulates the taker having the tokens with approval // This simulates the taker having the tokens with approval
if (tokenIn != address(0)) { if (tokenIn != address(0)) {
_transfer( // The executor already has the tokens from the test, just transfer to taker
address(this), transferType, tokenIn, actualFilledTakerAmount
);
IERC20(tokenIn).safeTransfer(takerAddress, actualFilledTakerAmount); IERC20(tokenIn).safeTransfer(takerAddress, actualFilledTakerAmount);
// Approve settlement from taker's perspective // Approve settlement from taker's perspective