chore: start implementing test changes related to partialFillOffset and encoded receiver
This commit is contained in:
@@ -114,13 +114,17 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
||||
bytes memory bebopCalldata,
|
||||
uint8 partialFillOffset,
|
||||
uint256 originalFilledTakerAmount,
|
||||
bool approvalNeeded
|
||||
bool approvalNeeded,
|
||||
address receiver
|
||||
) = _decodeData(data);
|
||||
|
||||
// Modify the filledTakerAmount in the calldata
|
||||
// If the filledTakerAmount is the same as the original, the original calldata is returned
|
||||
bytes memory finalCalldata = _modifyFilledTakerAmount(
|
||||
bebopCalldata, givenAmount, originalFilledTakerAmount, partialFillOffset
|
||||
bebopCalldata,
|
||||
givenAmount,
|
||||
originalFilledTakerAmount,
|
||||
partialFillOffset
|
||||
);
|
||||
|
||||
// Transfer tokens if needed
|
||||
@@ -134,9 +138,8 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
||||
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
||||
}
|
||||
|
||||
// Bebop orders specify the receiver, so we need to check the receiver's balance
|
||||
// We'll use the executor's balance since Bebop should send tokens here for the router to collect
|
||||
uint256 balanceBefore = _balanceOf(tokenOut, address(this));
|
||||
// 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;
|
||||
@@ -144,8 +147,8 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
||||
// Use OpenZeppelin's Address library for safe call with value
|
||||
bebopSettlement.functionCallWithValue(finalCalldata, ethValue);
|
||||
|
||||
// Calculate actual amount received by the executor
|
||||
uint256 balanceAfter = _balanceOf(tokenOut, address(this));
|
||||
// Calculate actual amount received by the receiver
|
||||
uint256 balanceAfter = _balanceOf(tokenOut, receiver);
|
||||
calculatedAmount = balanceAfter - balanceBefore;
|
||||
}
|
||||
|
||||
@@ -160,12 +163,13 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
||||
bytes memory bebopCalldata,
|
||||
uint8 partialFillOffset,
|
||||
uint256 originalFilledTakerAmount,
|
||||
bool approvalNeeded
|
||||
bool approvalNeeded,
|
||||
address receiver
|
||||
)
|
||||
{
|
||||
// Need at least 79 bytes for the minimum fixed fields
|
||||
// 20 + 20 + 1 + 4 (calldata length) + 1 (offset) + 32 (original amount) + 1 (approval) = 79
|
||||
if (data.length < 79) revert BebopExecutor__InvalidDataLength();
|
||||
// Need at least 99 bytes for the minimum fixed fields
|
||||
// 20 + 20 + 1 + 4 (calldata length) + 1 (offset) + 32 (original amount) + 1 (approval) + 20 (receiver) = 99
|
||||
if (data.length < 99) revert BebopExecutor__InvalidDataLength();
|
||||
|
||||
// Decode fixed fields
|
||||
tokenIn = address(bytes20(data[0:20]));
|
||||
@@ -174,7 +178,7 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
||||
|
||||
// Get bebop calldata length and validate
|
||||
uint32 bebopCalldataLength = uint32(bytes4(data[41:45]));
|
||||
if (data.length != 79 + bebopCalldataLength) {
|
||||
if (data.length != 99 + bebopCalldataLength) {
|
||||
revert BebopExecutor__InvalidDataLength();
|
||||
}
|
||||
|
||||
@@ -191,6 +195,11 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
||||
|
||||
// Extract approval flag
|
||||
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
|
||||
@@ -210,8 +219,9 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
||||
uint256 filledTakerAmountPos = 4 + uint256(partialFillOffset) * 32;
|
||||
|
||||
// Cap the fill amount at what we actually have available
|
||||
uint256 newFilledTakerAmount =
|
||||
originalFilledTakerAmount > givenAmount ? givenAmount : originalFilledTakerAmount;
|
||||
uint256 newFilledTakerAmount = originalFilledTakerAmount > givenAmount
|
||||
? givenAmount
|
||||
: originalFilledTakerAmount;
|
||||
|
||||
// If the new filledTakerAmount is the same as the original, return the original calldata
|
||||
if (newFilledTakerAmount == originalFilledTakerAmount) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -102,7 +102,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
|
||||
originalAmountIn,
|
||||
uint8(1) // approvalNeeded: true
|
||||
uint8(1), // approvalNeeded: true
|
||||
address(123)
|
||||
);
|
||||
|
||||
// Test decoding
|
||||
@@ -113,7 +114,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bytes memory decodedBebopCalldata,
|
||||
uint8 decodedPartialFillOffset,
|
||||
uint256 decodedOriginalAmountIn,
|
||||
bool decodedApprovalNeeded
|
||||
bool decodedApprovalNeeded,
|
||||
address decodedReceiver
|
||||
) = bebopExecutor.decodeParams(params);
|
||||
|
||||
assertEq(tokenIn, USDC_ADDR, "tokenIn mismatch");
|
||||
@@ -135,6 +137,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
"originalAmountIn mismatch"
|
||||
);
|
||||
assertTrue(decodedApprovalNeeded, "approvalNeeded should be true");
|
||||
assertEq(decodedReceiver, address(123), "receiver mismatch");
|
||||
}
|
||||
|
||||
// Single Order Tests
|
||||
@@ -217,18 +220,22 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
|
||||
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);
|
||||
|
||||
// Verify results
|
||||
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(
|
||||
ONDO.balanceOf(address(bebopExecutor)),
|
||||
ONDO.balanceOf(originalTakerAddress) - initialOndoBalance,
|
||||
testData.expectedAmountOut,
|
||||
"ONDO should be in executor"
|
||||
"ONDO should be at receiver"
|
||||
);
|
||||
assertEq(
|
||||
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
|
||||
@@ -313,9 +320,13 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
|
||||
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);
|
||||
|
||||
// Verify partial fill results
|
||||
@@ -324,11 +335,11 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
testData.expectedAmountOut,
|
||||
"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(
|
||||
ONDO.balanceOf(address(bebopExecutor)),
|
||||
ONDO.balanceOf(originalTakerAddress) - initialOndoBalance,
|
||||
testData.expectedAmountOut,
|
||||
"ONDO should be in executor"
|
||||
"ONDO should be at receiver"
|
||||
);
|
||||
assertEq(
|
||||
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
|
||||
@@ -448,9 +459,13 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
|
||||
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
|
||||
uint256 amountOut = bebopExecutor.swap{value: totalTakerAmount}(
|
||||
totalTakerAmount, params
|
||||
@@ -458,11 +473,11 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
|
||||
// Verify results
|
||||
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(
|
||||
USDC.balanceOf(address(bebopExecutor)),
|
||||
USDC.balanceOf(originalTakerAddress) - initialUsdcBalance,
|
||||
totalMakerAmount,
|
||||
"USDC should be in executor"
|
||||
"USDC should be at receiver"
|
||||
);
|
||||
// ETH balance check - the harness may have different balance due to test setup
|
||||
// Just ensure no excessive ETH is stuck
|
||||
@@ -588,9 +603,13 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
|
||||
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
|
||||
uint256 amountOut = bebopExecutor.swap{value: partialFillAmount}(
|
||||
partialFillAmount, params
|
||||
@@ -600,11 +619,11 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
assertEq(
|
||||
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(
|
||||
USDC.balanceOf(address(bebopExecutor)),
|
||||
USDC.balanceOf(originalTakerAddress) - initialUsdcBalance,
|
||||
expectedPartialOutput,
|
||||
"USDC should be in executor"
|
||||
"USDC should be at receiver"
|
||||
);
|
||||
// ETH balance check - the harness may have different balance due to test setup
|
||||
// Just ensure no excessive ETH is stuck
|
||||
@@ -637,7 +656,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
|
||||
originalAmountIn,
|
||||
uint8(1) // approvalNeeded: true
|
||||
uint8(1), // approvalNeeded: true
|
||||
address(bebopExecutor)
|
||||
);
|
||||
|
||||
// Verify valid params work
|
||||
@@ -713,7 +733,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(12), // partialFillOffset for swapSingle (388 = 4 + 12*32)
|
||||
uint256(200000000), // originalAmountIn
|
||||
uint8(1) // approvalNeeded: true
|
||||
uint8(1), // approvalNeeded: true
|
||||
originalTakerAddress // receiver from order
|
||||
);
|
||||
|
||||
// Deal 200 USDC to the executor
|
||||
@@ -727,16 +748,19 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
vm.prank(maker);
|
||||
ONDO.approve(BEBOP_SETTLEMENT, expectedAmountOut);
|
||||
|
||||
// Check initial ONDO balance of receiver
|
||||
uint256 initialOndoBalance = ONDO.balanceOf(originalTakerAddress);
|
||||
|
||||
// Execute the swap
|
||||
uint256 amountOut = bebopExecutor.swap(amountIn, protocolData);
|
||||
|
||||
// Verify results
|
||||
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(
|
||||
ONDO.balanceOf(address(bebopExecutor)),
|
||||
ONDO.balanceOf(originalTakerAddress) - initialOndoBalance,
|
||||
expectedAmountOut,
|
||||
"ONDO should be in executor"
|
||||
"ONDO should be at receiver"
|
||||
);
|
||||
assertEq(
|
||||
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
|
||||
@@ -834,7 +858,8 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
bebopCalldata,
|
||||
uint8(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
|
||||
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
|
||||
@@ -854,17 +879,20 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
vm.deal(ALICE, ethAmount);
|
||||
vm.startPrank(ALICE);
|
||||
|
||||
// Check initial USDC balance of receiver
|
||||
uint256 initialUsdcBalance = IERC20(USDC_ADDR).balanceOf(orderTaker);
|
||||
|
||||
// Execute the swap with native ETH
|
||||
uint256 amountOut =
|
||||
bebopExecutor.swap{value: ethAmount}(ethAmount, protocolData);
|
||||
|
||||
// Verify results
|
||||
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(
|
||||
IERC20(USDC_ADDR).balanceOf(address(bebopExecutor)),
|
||||
IERC20(USDC_ADDR).balanceOf(orderTaker) - initialUsdcBalance,
|
||||
expAmountOut,
|
||||
"USDC should be in executor"
|
||||
"USDC should be at receiver"
|
||||
);
|
||||
// ETH balance check - the harness may have different balance due to test setup
|
||||
// Just ensure no excessive ETH is stuck
|
||||
@@ -876,202 +904,6 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
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
|
||||
function testModifyFilledTakerAmount_SingleOrder() public {
|
||||
// Deploy Bebop executor harness
|
||||
@@ -1108,7 +940,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
|
||||
bytes memory modifiedCalldata = bebopExecutor
|
||||
.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
|
||||
@@ -1184,7 +1019,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
|
||||
bytes memory modifiedCalldata = bebopExecutor
|
||||
.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
|
||||
@@ -1243,7 +1081,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
// So we'll test that it properly sets the value we want
|
||||
bytes memory modifiedCalldata = bebopExecutor
|
||||
.exposed_modifyFilledTakerAmount(
|
||||
originalCalldata, givenAmount, originalAmountIn, 12 // partialFillOffset for swapSingle
|
||||
originalCalldata,
|
||||
givenAmount,
|
||||
originalAmountIn,
|
||||
12 // partialFillOffset for swapSingle
|
||||
);
|
||||
|
||||
// Extract the new filledTakerAmount
|
||||
@@ -1259,7 +1100,10 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
||||
// Normal test - amounts match so calldata should be unchanged
|
||||
bytes memory modifiedCalldata = bebopExecutor
|
||||
.exposed_modifyFilledTakerAmount(
|
||||
originalCalldata, givenAmount, originalAmountIn, 12 // partialFillOffset for swapSingle
|
||||
originalCalldata,
|
||||
givenAmount,
|
||||
originalAmountIn,
|
||||
12 // partialFillOffset for swapSingle
|
||||
);
|
||||
|
||||
assertEq(
|
||||
|
||||
@@ -60,21 +60,13 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
||||
bytes memory bebopCalldata,
|
||||
uint8 partialFillOffset,
|
||||
uint256 originalFilledTakerAmount,
|
||||
bool approvalNeeded
|
||||
bool approvalNeeded,
|
||||
address receiver
|
||||
)
|
||||
{
|
||||
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
|
||||
function exposed_modifyFilledTakerAmount(
|
||||
bytes memory bebopCalldata,
|
||||
@@ -83,7 +75,10 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
||||
uint8 partialFillOffset
|
||||
) external pure returns (bytes memory) {
|
||||
return _modifyFilledTakerAmount(
|
||||
bebopCalldata, givenAmount, originalFilledTakerAmount, partialFillOffset
|
||||
bebopCalldata,
|
||||
givenAmount,
|
||||
originalFilledTakerAmount,
|
||||
partialFillOffset
|
||||
);
|
||||
}
|
||||
|
||||
@@ -102,6 +97,8 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
||||
bytes memory bebopCalldata,
|
||||
, // partialFillOffset not needed in test harness
|
||||
uint256 originalFilledTakerAmount,
|
||||
, // approvalNeeded not needed in test harness
|
||||
// receiver not needed since we extract it from bebop calldata
|
||||
) = _decodeData(data);
|
||||
|
||||
// Extract taker address, receiver, and expiry from bebop calldata
|
||||
@@ -139,16 +136,13 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
||||
expiry = order.expiry;
|
||||
}
|
||||
|
||||
// Inline the simple logic since _getActualFilledTakerAmount was removed
|
||||
uint256 actualFilledTakerAmount =
|
||||
originalFilledTakerAmount > givenAmount ? givenAmount : originalFilledTakerAmount;
|
||||
uint256 actualFilledTakerAmount = originalFilledTakerAmount
|
||||
> givenAmount ? givenAmount : originalFilledTakerAmount;
|
||||
|
||||
// For testing: transfer tokens from executor to taker address
|
||||
// This simulates the taker having the tokens with approval
|
||||
if (tokenIn != address(0)) {
|
||||
_transfer(
|
||||
address(this), transferType, tokenIn, actualFilledTakerAmount
|
||||
);
|
||||
// The executor already has the tokens from the test, just transfer to taker
|
||||
IERC20(tokenIn).safeTransfer(takerAddress, actualFilledTakerAmount);
|
||||
|
||||
// Approve settlement from taker's perspective
|
||||
|
||||
Reference in New Issue
Block a user