test: fix all aggregate order tests and a few executor bugs
This commit is contained in:
@@ -193,8 +193,10 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
givenAmount, order.taker_amount, filledTakerAmount
|
givenAmount, order.taker_amount, filledTakerAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (tokenIn != address(0)) {
|
||||||
// Transfer tokens to executor
|
// Transfer tokens to executor
|
||||||
_transfer(address(this), transferType, tokenIn, givenAmount);
|
_transfer(address(this), transferType, tokenIn, givenAmount);
|
||||||
|
}
|
||||||
|
|
||||||
// Approve Bebop settlement to spend tokens if needed
|
// Approve Bebop settlement to spend tokens if needed
|
||||||
if (approvalNeeded) {
|
if (approvalNeeded) {
|
||||||
@@ -248,20 +250,24 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
revert BebopExecutor__InvalidInput();
|
revert BebopExecutor__InvalidInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
// For aggregate orders, calculate total taker amount across all makers
|
// For aggregate orders, calculate total taker amount across all amounts of the 2D array
|
||||||
uint256 totalTakerAmount = 0;
|
uint256 totalTakerAmount;
|
||||||
for (uint256 i = 0; i < order.taker_amounts.length; i++) {
|
for (uint256 i = 0; i < order.taker_amounts.length; i++) {
|
||||||
totalTakerAmount += order.taker_amounts[i][0];
|
for (uint256 j = 0; j < order.taker_amounts[i].length; j++) {
|
||||||
|
totalTakerAmount += order.taker_amounts[i][j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 actualFilledTakerAmount = _getActualFilledTakerAmount(
|
uint256 actualFilledTakerAmount = _getActualFilledTakerAmount(
|
||||||
givenAmount, totalTakerAmount, filledTakerAmount
|
givenAmount, totalTakerAmount, filledTakerAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
// Transfer single input token
|
if (tokenIn != address(0)) {
|
||||||
|
// Transfer tokens to executor
|
||||||
_transfer(address(this), transferType, tokenIn, givenAmount);
|
_transfer(address(this), transferType, tokenIn, givenAmount);
|
||||||
|
}
|
||||||
|
|
||||||
// Approve if needed
|
// Approve Bebop settlement to spend tokens if needed
|
||||||
if (approvalNeeded) {
|
if (approvalNeeded) {
|
||||||
// slither-disable-next-line unused-return
|
// slither-disable-next-line unused-return
|
||||||
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
||||||
|
|||||||
@@ -299,14 +299,13 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup {
|
|||||||
// The calldata swaps 200 USDC for ONDO
|
// The calldata swaps 200 USDC for ONDO
|
||||||
// The receiver in the order is 0xc5564C13A157E6240659fb81882A28091add8670
|
// The receiver in the order is 0xc5564C13A157E6240659fb81882A28091add8670
|
||||||
address orderReceiver = 0xc5564C13A157E6240659fb81882A28091add8670;
|
address orderReceiver = 0xc5564C13A157E6240659fb81882A28091add8670;
|
||||||
|
address maker = 0xCe79b081c0c924cb67848723ed3057234d10FC6b;
|
||||||
deal(USDC_ADDR, ALICE, 200 * 10 ** 6); // 200 USDC
|
deal(USDC_ADDR, ALICE, 200 * 10 ** 6); // 200 USDC
|
||||||
uint256 expAmountOut = 237212396774431060000; // Expected ONDO amount from calldata
|
uint256 expAmountOut = 237212396774431060000; // Expected ONDO amount from calldata
|
||||||
|
|
||||||
// Fund the maker with ONDO and approve settlement
|
// Fund the maker with ONDO and approve settlement
|
||||||
deal(
|
deal(ONDO_ADDR, maker, expAmountOut);
|
||||||
ONDO_ADDR, 0xCe79b081c0c924cb67848723ed3057234d10FC6b, expAmountOut
|
vm.prank(maker);
|
||||||
);
|
|
||||||
vm.prank(0xCe79b081c0c924cb67848723ed3057234d10FC6b);
|
|
||||||
IERC20(ONDO_ADDR).approve(BEBOP_SETTLEMENT, expAmountOut);
|
IERC20(ONDO_ADDR).approve(BEBOP_SETTLEMENT, expAmountOut);
|
||||||
|
|
||||||
vm.startPrank(ALICE);
|
vm.startPrank(ALICE);
|
||||||
@@ -322,47 +321,51 @@ contract TychoRouterTestProtocolIntegration is TychoRouterTestSetup {
|
|||||||
uint256 finalBalance = IERC20(ONDO_ADDR).balanceOf(orderReceiver);
|
uint256 finalBalance = IERC20(ONDO_ADDR).balanceOf(orderReceiver);
|
||||||
assertTrue(success, "Call Failed");
|
assertTrue(success, "Call Failed");
|
||||||
assertGe(finalBalance, expAmountOut);
|
assertGe(finalBalance, expAmountOut);
|
||||||
assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 0);
|
assertEq(
|
||||||
|
IERC20(USDC_ADDR).balanceOf(tychoRouterAddr),
|
||||||
|
0,
|
||||||
|
"USDC left in router"
|
||||||
|
);
|
||||||
|
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBebopAggregateIntegration() public {
|
function testBebopAggregateIntegration() public {
|
||||||
// // Setup: Alice has USDC, wants WETH (through multiple makers)
|
// Based on real transaction: https://etherscan.io/tx/0xec88410136c287280da87d0a37c1cb745f320406ca3ae55c678dec11996c1b1c
|
||||||
// deal(USDC_ADDR, ALICE, 1000 * 10 ** 6);
|
address orderTaker = 0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6; // This is both taker and receiver in the order
|
||||||
// uint256 expAmountOut = 400000000000000000; // 0.4 WETH
|
uint256 ethAmount = 9850000000000000; // 0.00985 WETH
|
||||||
|
uint256 expAmountOut = 17969561; // 17.969561 USDC expected output
|
||||||
|
|
||||||
// // Fund the two makers from the calldata with WETH
|
// Fund the two makers from the real transaction with USDC
|
||||||
// address maker1 = 0x1111111111111111111111111111111111111111;
|
address maker1 = 0x67336Cec42645F55059EfF241Cb02eA5cC52fF86;
|
||||||
// address maker2 = 0x2222222222222222222222222222222222222222;
|
address maker2 = 0xBF19CbF0256f19f39A016a86Ff3551ecC6f2aAFE;
|
||||||
|
|
||||||
// // Maker 1 provides 0.24 WETH, Maker 2 provides 0.16 WETH
|
deal(USDC_ADDR, maker1, 10607211); // Maker 1 provides 10.607211 USDC
|
||||||
// deal(WETH_ADDR, maker1, 240000000000000000);
|
deal(USDC_ADDR, maker2, 7362350); // Maker 2 provides 7.362350 USDC
|
||||||
// deal(WETH_ADDR, maker2, 160000000000000000);
|
|
||||||
|
|
||||||
// // Makers approve settlement contract
|
// Makers approve settlement contract
|
||||||
// vm.prank(maker1);
|
vm.prank(maker1);
|
||||||
// IERC20(WETH_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
IERC20(USDC_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
||||||
// vm.prank(maker2);
|
vm.prank(maker2);
|
||||||
// IERC20(WETH_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
IERC20(USDC_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
||||||
|
|
||||||
// vm.startPrank(ALICE);
|
// Fund ALICE with ETH as it will send the transaction
|
||||||
// IERC20(USDC_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
vm.deal(ALICE, ethAmount);
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
|
||||||
// bytes memory callData = loadCallDataFromFile(
|
// Load calldata from file
|
||||||
// "test_single_encoding_strategy_bebop_aggregate"
|
bytes memory callData = loadCallDataFromFile(
|
||||||
// );
|
"test_single_encoding_strategy_bebop_aggregate"
|
||||||
|
);
|
||||||
|
|
||||||
// (bool success,) = tychoRouterAddr.call(callData);
|
// Execute the swap
|
||||||
|
(bool success,) = tychoRouterAddr.call{value: ethAmount}(callData);
|
||||||
|
uint256 finalBalance = IERC20(USDC_ADDR).balanceOf(orderTaker);
|
||||||
|
|
||||||
// uint256 finalBalance = IERC20(WETH_ADDR).balanceOf(ALICE);
|
assertTrue(success, "Call Failed");
|
||||||
|
assertGe(finalBalance, expAmountOut);
|
||||||
|
assertEq(address(tychoRouterAddr).balance, 0, "ETH left in router");
|
||||||
|
|
||||||
// assertTrue(success, "Call Failed");
|
vm.stopPrank();
|
||||||
// assertGe(finalBalance, expAmountOut);
|
|
||||||
// assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 0);
|
|
||||||
|
|
||||||
// vm.stopPrank();
|
|
||||||
|
|
||||||
vm.skip(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -48,7 +48,7 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
|||||||
uint256 filledTakerAmount,
|
uint256 filledTakerAmount,
|
||||||
bytes memory quoteData,
|
bytes memory quoteData,
|
||||||
bytes memory makerSignaturesData,
|
bytes memory makerSignaturesData,
|
||||||
bool approvalNeeded
|
bool // approvalNeeded - unused in test harness
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return _decodeData(data);
|
return _decodeData(data);
|
||||||
@@ -85,8 +85,27 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
|||||||
givenAmount, order.taker_amount, filledTakerAmount
|
givenAmount, order.taker_amount, filledTakerAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (tokenIn != address(0)) {
|
||||||
// Transfer tokens to executor
|
// Transfer tokens to executor
|
||||||
_transfer(address(this), transferType, tokenIn, givenAmount);
|
_transfer(address(this), transferType, tokenIn, givenAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: NOT NEEDED FOR TESTING
|
||||||
|
// // Approve Bebop settlement to spend tokens if needed
|
||||||
|
// if (approvalNeeded) {
|
||||||
|
// // slither-disable-next-line unused-return
|
||||||
|
// IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// NOTE: SETUP FOR TESTING
|
||||||
|
|
||||||
|
// Record balances before swap to calculate amountOut
|
||||||
|
uint256 balanceBefore = tokenOut == address(0)
|
||||||
|
? order.receiver.balance
|
||||||
|
: IERC20(tokenOut).balanceOf(order.receiver);
|
||||||
|
|
||||||
|
// Execute the swap with ETH value if needed
|
||||||
|
uint256 ethValue = tokenIn == address(0) ? actualFilledTakerAmount : 0;
|
||||||
|
|
||||||
// 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
|
||||||
@@ -101,16 +120,12 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
|||||||
vm.startPrank(order.taker_address);
|
vm.startPrank(order.taker_address);
|
||||||
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
} else {
|
||||||
|
vm.stopPrank();
|
||||||
|
// For native ETH, send it to the taker address
|
||||||
|
payable(order.taker_address).transfer(actualFilledTakerAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record balances before swap to calculate amountOut
|
|
||||||
uint256 balanceBefore = tokenOut == address(0)
|
|
||||||
? order.receiver.balance
|
|
||||||
: IERC20(tokenOut).balanceOf(order.receiver);
|
|
||||||
|
|
||||||
// Execute the swap with ETH value if needed
|
|
||||||
uint256 ethValue = tokenIn == address(0) ? actualFilledTakerAmount : 0;
|
|
||||||
|
|
||||||
// IMPORTANT: Prank as the taker address to pass the settlement validation
|
// IMPORTANT: Prank as the taker address to pass the settlement validation
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
vm.startPrank(order.taker_address);
|
vm.startPrank(order.taker_address);
|
||||||
@@ -129,6 +144,8 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
|||||||
vm.warp(currentTimestamp);
|
vm.warp(currentTimestamp);
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
|
|
||||||
|
// NOTE: END SETUP FOR TESTING
|
||||||
|
|
||||||
// Calculate actual amount received
|
// Calculate actual amount received
|
||||||
uint256 balanceAfter = tokenOut == address(0)
|
uint256 balanceAfter = tokenOut == address(0)
|
||||||
? order.receiver.balance
|
? order.receiver.balance
|
||||||
@@ -146,80 +163,100 @@ contract BebopExecutorHarness is BebopExecutor, Test {
|
|||||||
uint256 filledTakerAmount,
|
uint256 filledTakerAmount,
|
||||||
bytes memory quoteData,
|
bytes memory quoteData,
|
||||||
bytes memory makerSignaturesData,
|
bytes memory makerSignaturesData,
|
||||||
bool approvalNeeded
|
bool // approvalNeeded - unused in test harness
|
||||||
) internal virtual override returns (uint256 amountOut) {
|
) internal virtual override returns (uint256 amountOut) {
|
||||||
// // Decode the Aggregate order
|
// Decode the Aggregate order
|
||||||
// IBebopSettlement.Aggregate memory order =
|
IBebopSettlement.Aggregate memory order =
|
||||||
// abi.decode(quoteData, (IBebopSettlement.Aggregate));
|
abi.decode(quoteData, (IBebopSettlement.Aggregate));
|
||||||
|
|
||||||
// // Decode the MakerSignature array (can contain multiple signatures for Aggregate orders)
|
// Decode the MakerSignature array (can contain multiple signatures for Aggregate orders)
|
||||||
// IBebopSettlement.MakerSignature[] memory signatures =
|
IBebopSettlement.MakerSignature[] memory signatures =
|
||||||
// abi.decode(makerSignaturesData, (IBebopSettlement.MakerSignature[]));
|
abi.decode(makerSignaturesData, (IBebopSettlement.MakerSignature[]));
|
||||||
|
|
||||||
// // Aggregate orders should have at least one signature
|
// Aggregate orders should have at least one signature
|
||||||
// if (signatures.length == 0) {
|
if (signatures.length == 0) {
|
||||||
// revert BebopExecutor__InvalidInput();
|
revert BebopExecutor__InvalidInput();
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // For aggregate orders, calculate total taker amount across all makers
|
// For aggregate orders, calculate total taker amount across all amounts of the 2D array
|
||||||
// uint256 totalTakerAmount = 0;
|
uint256 totalTakerAmount;
|
||||||
// for (uint256 i = 0; i < order.taker_amounts.length; i++) {
|
for (uint256 i = 0; i < order.taker_amounts.length; i++) {
|
||||||
// totalTakerAmount += order.taker_amounts[i][0];
|
for (uint256 j = 0; j < order.taker_amounts[i].length; j++) {
|
||||||
// }
|
totalTakerAmount += order.taker_amounts[i][j];
|
||||||
// uint256 actualFilledTakerAmount = _getActualFilledTakerAmount(
|
}
|
||||||
// givenAmount, totalTakerAmount, filledTakerAmount
|
}
|
||||||
// );
|
|
||||||
|
|
||||||
// // Transfer tokens to executor
|
uint256 actualFilledTakerAmount = _getActualFilledTakerAmount(
|
||||||
// _transfer(address(this), transferType, tokenIn, givenAmount);
|
givenAmount, totalTakerAmount, filledTakerAmount
|
||||||
|
);
|
||||||
|
|
||||||
// // For testing: transfer tokens from executor to taker address
|
if (tokenIn != address(0)) {
|
||||||
// // This simulates the taker having the tokens with approval
|
// Transfer tokens to executor
|
||||||
// if (tokenIn != address(0)) {
|
_transfer(address(this), transferType, tokenIn, givenAmount);
|
||||||
// IERC20(tokenIn).safeTransfer(
|
}
|
||||||
// order.taker_address, actualFilledTakerAmount
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // Approve settlement from taker's perspective
|
// NOTE: NOT NEEDED FOR TESTING
|
||||||
// // Stop any existing prank first
|
// // Approve Bebop settlement to spend tokens if needed
|
||||||
// vm.stopPrank();
|
// if (approvalNeeded) {
|
||||||
// vm.startPrank(order.taker_address);
|
// // slither-disable-next-line unused-return
|
||||||
// IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
// IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
||||||
// vm.stopPrank();
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // Record balances before swap to calculate amountOut
|
// NOTE: SETUP FOR TESTING
|
||||||
// uint256 balanceBefore = tokenOut == address(0)
|
|
||||||
// ? order.receiver.balance
|
|
||||||
// : IERC20(tokenOut).balanceOf(order.receiver);
|
|
||||||
|
|
||||||
// // Execute the swap with ETH value if needed
|
// Record balances before swap to calculate amountOut
|
||||||
// uint256 ethValue = tokenIn == address(0) ? actualFilledTakerAmount : 0;
|
uint256 balanceBefore = tokenOut == address(0)
|
||||||
|
? order.receiver.balance
|
||||||
|
: IERC20(tokenOut).balanceOf(order.receiver);
|
||||||
|
|
||||||
// // IMPORTANT: Prank as the taker address to pass the settlement validation
|
// Execute the swap with ETH value if needed
|
||||||
// vm.stopPrank();
|
uint256 ethValue = tokenIn == address(0) ? actualFilledTakerAmount : 0;
|
||||||
// vm.startPrank(order.taker_address);
|
|
||||||
|
|
||||||
// // Set block timestamp to ensure order is valid regardless of fork block
|
// For testing: transfer tokens from executor to taker address
|
||||||
// uint256 currentTimestamp = block.timestamp;
|
// This simulates the taker having the tokens with approval
|
||||||
// vm.warp(order.expiry - 1); // Set timestamp to just before expiry
|
if (tokenIn != address(0)) {
|
||||||
|
IERC20(tokenIn).safeTransfer(
|
||||||
|
order.taker_address, actualFilledTakerAmount
|
||||||
|
);
|
||||||
|
|
||||||
// // Execute the swap - tokens are now in taker's wallet with approval
|
// Approve settlement from taker's perspective
|
||||||
// // slither-disable-next-line arbitrary-send-eth
|
// Stop any existing prank first
|
||||||
// IBebopSettlement(bebopSettlement).swapAggregate{value: ethValue}(
|
vm.stopPrank();
|
||||||
// order, signatures, actualFilledTakerAmount
|
vm.startPrank(order.taker_address);
|
||||||
// );
|
IERC20(tokenIn).forceApprove(bebopSettlement, type(uint256).max);
|
||||||
|
vm.stopPrank();
|
||||||
|
} else {
|
||||||
|
vm.stopPrank();
|
||||||
|
// For native ETH, send it to the taker address
|
||||||
|
payable(order.taker_address).transfer(actualFilledTakerAmount);
|
||||||
|
}
|
||||||
|
|
||||||
// // Restore original timestamp
|
// IMPORTANT: Prank as the taker address to pass the settlement validation
|
||||||
// vm.warp(currentTimestamp);
|
vm.stopPrank();
|
||||||
// vm.stopPrank();
|
vm.startPrank(order.taker_address);
|
||||||
|
|
||||||
// // Calculate actual amount received
|
// Set block timestamp to ensure order is valid regardless of fork block
|
||||||
// uint256 balanceAfter = tokenOut == address(0)
|
uint256 currentTimestamp = block.timestamp;
|
||||||
// ? order.receiver.balance
|
vm.warp(order.expiry - 1); // Set timestamp to just before expiry
|
||||||
// : IERC20(tokenOut).balanceOf(order.receiver);
|
|
||||||
|
|
||||||
// amountOut = balanceAfter - balanceBefore;
|
// Use swapAggregate - tokens are now in taker's wallet with approval
|
||||||
|
// slither-disable-next-line arbitrary-send-eth
|
||||||
|
IBebopSettlement(bebopSettlement).swapAggregate{value: ethValue}(
|
||||||
|
order, signatures, actualFilledTakerAmount
|
||||||
|
);
|
||||||
|
|
||||||
|
// Restore original timestamp
|
||||||
|
vm.warp(currentTimestamp);
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
// NOTE: END SETUP FOR TESTING
|
||||||
|
|
||||||
|
// Calculate actual amount received
|
||||||
|
uint256 balanceAfter = tokenOut == address(0)
|
||||||
|
? order.receiver.balance
|
||||||
|
: IERC20(tokenOut).balanceOf(order.receiver);
|
||||||
|
|
||||||
|
amountOut = balanceAfter - balanceBefore;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,9 +299,6 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
// Fork will be created in individual tests to allow different fork blocks
|
// Fork will be created in individual tests to allow different fork blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow test contract to receive ETH
|
|
||||||
receive() external payable {}
|
|
||||||
|
|
||||||
function testDecodeParams() public {
|
function testDecodeParams() public {
|
||||||
// Fork to ensure consistent setup
|
// Fork to ensure consistent setup
|
||||||
vm.createSelectFork(vm.rpcUrl("mainnet"), 22667985);
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 22667985);
|
||||||
@@ -542,7 +576,286 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
|
|
||||||
// Aggregate Order Tests
|
// Aggregate Order Tests
|
||||||
function testAggregateOrder() public {
|
function testAggregateOrder() public {
|
||||||
vm.skip(true);
|
// Fork at a suitable block for aggregate order testing
|
||||||
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 21370890);
|
||||||
|
|
||||||
|
// Deploy Bebop executor harness that uses vm.prank
|
||||||
|
bebopExecutor =
|
||||||
|
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
|
||||||
|
|
||||||
|
// Store the initial ETH balance (dust from forked state)
|
||||||
|
uint256 initialExecutorBalance = address(bebopExecutor).balance;
|
||||||
|
|
||||||
|
// Create test data from real mainnet transaction
|
||||||
|
// https://etherscan.io/tx/0xec88410136c287280da87d0a37c1cb745f320406ca3ae55c678dec11996c1b1c
|
||||||
|
address originalTakerAddress =
|
||||||
|
0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6;
|
||||||
|
|
||||||
|
// Create the 2D arrays for tokens and amounts
|
||||||
|
address[][] memory takerTokens = new address[][](2);
|
||||||
|
takerTokens[0] = new address[](1);
|
||||||
|
takerTokens[0][0] = WETH_ADDR; // WETH for first maker
|
||||||
|
takerTokens[1] = new address[](1);
|
||||||
|
takerTokens[1][0] = WETH_ADDR; // WETH for second maker
|
||||||
|
|
||||||
|
address[][] memory makerTokens = new address[][](2);
|
||||||
|
makerTokens[0] = new address[](1);
|
||||||
|
makerTokens[0][0] = USDC_ADDR; // USDC from first maker
|
||||||
|
makerTokens[1] = new address[](1);
|
||||||
|
makerTokens[1][0] = USDC_ADDR; // USDC from second maker
|
||||||
|
|
||||||
|
uint256[][] memory takerAmounts = new uint256[][](2);
|
||||||
|
takerAmounts[0] = new uint256[](1);
|
||||||
|
takerAmounts[0][0] = 5812106401997138; // First maker takes ~0.0058 ETH
|
||||||
|
takerAmounts[1] = new uint256[](1);
|
||||||
|
takerAmounts[1][0] = 4037893598002862; // Second maker takes ~0.0040 ETH
|
||||||
|
|
||||||
|
uint256[][] memory makerAmounts = new uint256[][](2);
|
||||||
|
makerAmounts[0] = new uint256[](1);
|
||||||
|
makerAmounts[0][0] = 10607211; // First maker gives ~10.6 USDC
|
||||||
|
makerAmounts[1] = new uint256[](1);
|
||||||
|
makerAmounts[1][0] = 7362350; // Second maker gives ~7.36 USDC
|
||||||
|
|
||||||
|
// Create makers array
|
||||||
|
address[] memory makerAddresses = new address[](2);
|
||||||
|
makerAddresses[0] = 0x67336Cec42645F55059EfF241Cb02eA5cC52fF86;
|
||||||
|
makerAddresses[1] = 0xBF19CbF0256f19f39A016a86Ff3551ecC6f2aAFE;
|
||||||
|
|
||||||
|
// Create maker nonces array
|
||||||
|
uint256[] memory makerNonces = new uint256[](2);
|
||||||
|
makerNonces[0] = 1746367197308;
|
||||||
|
makerNonces[1] = 15460096;
|
||||||
|
|
||||||
|
// Create the aggregate order
|
||||||
|
IBebopSettlement.Aggregate memory order = IBebopSettlement.Aggregate({
|
||||||
|
expiry: 1746367285,
|
||||||
|
taker_address: originalTakerAddress,
|
||||||
|
maker_addresses: makerAddresses,
|
||||||
|
maker_nonces: makerNonces,
|
||||||
|
taker_tokens: takerTokens,
|
||||||
|
maker_tokens: makerTokens,
|
||||||
|
taker_amounts: takerAmounts,
|
||||||
|
maker_amounts: makerAmounts,
|
||||||
|
receiver: originalTakerAddress,
|
||||||
|
commands: hex"00040004",
|
||||||
|
flags: 95769172144825922628485191511070792431742484643425438763224908097896054784000
|
||||||
|
});
|
||||||
|
|
||||||
|
// Total amounts
|
||||||
|
uint256 totalTakerAmount = takerAmounts[0][0] + takerAmounts[1][0]; // 0.00985 ETH total
|
||||||
|
uint256 totalMakerAmount = makerAmounts[0][0] + makerAmounts[1][0]; // 17.969561 USDC total
|
||||||
|
|
||||||
|
// Fund makers with USDC and approve settlement
|
||||||
|
deal(USDC_ADDR, makerAddresses[0], makerAmounts[0][0]);
|
||||||
|
deal(USDC_ADDR, makerAddresses[1], makerAmounts[1][0]);
|
||||||
|
|
||||||
|
vm.prank(makerAddresses[0]);
|
||||||
|
USDC.approve(BEBOP_SETTLEMENT, makerAmounts[0][0]);
|
||||||
|
|
||||||
|
vm.prank(makerAddresses[1]);
|
||||||
|
USDC.approve(BEBOP_SETTLEMENT, makerAmounts[1][0]);
|
||||||
|
|
||||||
|
// ETH will be sent directly with the swap call
|
||||||
|
// Fund the test contract with ETH to send with the swap
|
||||||
|
vm.deal(address(this), totalTakerAmount);
|
||||||
|
|
||||||
|
// Record initial balances
|
||||||
|
uint256 usdcBefore = USDC.balanceOf(originalTakerAddress);
|
||||||
|
|
||||||
|
// Create maker signatures
|
||||||
|
IBebopSettlement.MakerSignature[] memory signatures =
|
||||||
|
new IBebopSettlement.MakerSignature[](2);
|
||||||
|
signatures[0] = IBebopSettlement.MakerSignature({
|
||||||
|
signatureBytes: hex"d5abb425f9bac1f44d48705f41a8ab9cae207517be8553d2c03b06a88995f2f351ab8ce7627a87048178d539dd64fd2380245531a0c8e43fdc614652b1f32fc71c",
|
||||||
|
flags: 0 // ETH_SIGN
|
||||||
|
});
|
||||||
|
signatures[1] = IBebopSettlement.MakerSignature({
|
||||||
|
signatureBytes: hex"f38c698e48a3eac48f184bc324fef0b135ee13705ab38cc0bbf5a792f21002f051e445b9e7d57cf24c35e17629ea35b3263591c4abf8ca87ffa44b41301b89c41b",
|
||||||
|
flags: 0 // ETH_SIGN
|
||||||
|
});
|
||||||
|
|
||||||
|
// Encode order and signatures
|
||||||
|
bytes memory quoteData = abi.encode(order);
|
||||||
|
bytes memory makerSignaturesData = abi.encode(signatures);
|
||||||
|
|
||||||
|
// Create packed params for executor with native ETH as input
|
||||||
|
bytes memory params = abi.encodePacked(
|
||||||
|
address(0), // tokenIn: native ETH
|
||||||
|
USDC_ADDR, // tokenOut
|
||||||
|
uint8(RestrictTransferFrom.TransferType.Transfer),
|
||||||
|
uint8(BebopExecutor.OrderType.Aggregate),
|
||||||
|
uint256(0), // filledTakerAmount: 0 for full fill
|
||||||
|
uint32(quoteData.length),
|
||||||
|
quoteData,
|
||||||
|
uint32(makerSignaturesData.length),
|
||||||
|
makerSignaturesData,
|
||||||
|
uint8(0) // approvalNeeded: false for native ETH
|
||||||
|
);
|
||||||
|
|
||||||
|
// Execute the aggregate swap with ETH value
|
||||||
|
uint256 amountOut = bebopExecutor.swap{value: totalTakerAmount}(
|
||||||
|
totalTakerAmount, params
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify results
|
||||||
|
assertEq(amountOut, totalMakerAmount, "Incorrect amount out");
|
||||||
|
assertEq(
|
||||||
|
USDC.balanceOf(originalTakerAddress) - usdcBefore,
|
||||||
|
totalMakerAmount,
|
||||||
|
"USDC balance mismatch"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
address(bebopExecutor).balance,
|
||||||
|
initialExecutorBalance,
|
||||||
|
"ETH left in executor should match initial dust amount"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAggregateOrder_PartialFill() public {
|
||||||
|
// Fork at a suitable block for aggregate order testing
|
||||||
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 21370890);
|
||||||
|
|
||||||
|
// Deploy Bebop executor harness that uses vm.prank
|
||||||
|
bebopExecutor =
|
||||||
|
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
|
||||||
|
|
||||||
|
// Store the initial ETH balance (dust from forked state)
|
||||||
|
uint256 initialExecutorBalance = address(bebopExecutor).balance;
|
||||||
|
|
||||||
|
// Same aggregate order as before, but with partial fill
|
||||||
|
address originalTakerAddress =
|
||||||
|
0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6;
|
||||||
|
|
||||||
|
// Create the 2D arrays for tokens and amounts
|
||||||
|
address[][] memory takerTokens = new address[][](2);
|
||||||
|
takerTokens[0] = new address[](1);
|
||||||
|
takerTokens[0][0] = WETH_ADDR;
|
||||||
|
takerTokens[1] = new address[](1);
|
||||||
|
takerTokens[1][0] = WETH_ADDR;
|
||||||
|
|
||||||
|
address[][] memory makerTokens = new address[][](2);
|
||||||
|
makerTokens[0] = new address[](1);
|
||||||
|
makerTokens[0][0] = USDC_ADDR;
|
||||||
|
makerTokens[1] = new address[](1);
|
||||||
|
makerTokens[1][0] = USDC_ADDR;
|
||||||
|
|
||||||
|
uint256[][] memory takerAmounts = new uint256[][](2);
|
||||||
|
takerAmounts[0] = new uint256[](1);
|
||||||
|
takerAmounts[0][0] = 5812106401997138;
|
||||||
|
takerAmounts[1] = new uint256[](1);
|
||||||
|
takerAmounts[1][0] = 4037893598002862;
|
||||||
|
|
||||||
|
uint256[][] memory makerAmounts = new uint256[][](2);
|
||||||
|
makerAmounts[0] = new uint256[](1);
|
||||||
|
makerAmounts[0][0] = 10607211;
|
||||||
|
makerAmounts[1] = new uint256[](1);
|
||||||
|
makerAmounts[1][0] = 7362350;
|
||||||
|
|
||||||
|
// Create makers array
|
||||||
|
address[] memory makerAddresses = new address[](2);
|
||||||
|
makerAddresses[0] = 0x67336Cec42645F55059EfF241Cb02eA5cC52fF86;
|
||||||
|
makerAddresses[1] = 0xBF19CbF0256f19f39A016a86Ff3551ecC6f2aAFE;
|
||||||
|
|
||||||
|
// Create maker nonces array
|
||||||
|
uint256[] memory makerNonces = new uint256[](2);
|
||||||
|
makerNonces[0] = 1746367197308;
|
||||||
|
makerNonces[1] = 15460096;
|
||||||
|
|
||||||
|
// Create the aggregate order
|
||||||
|
IBebopSettlement.Aggregate memory order = IBebopSettlement.Aggregate({
|
||||||
|
expiry: 1746367285,
|
||||||
|
taker_address: originalTakerAddress,
|
||||||
|
maker_addresses: makerAddresses,
|
||||||
|
maker_nonces: makerNonces,
|
||||||
|
taker_tokens: takerTokens,
|
||||||
|
maker_tokens: makerTokens,
|
||||||
|
taker_amounts: takerAmounts,
|
||||||
|
maker_amounts: makerAmounts,
|
||||||
|
receiver: originalTakerAddress,
|
||||||
|
commands: hex"00040004",
|
||||||
|
flags: 95769172144825922628485191511070792431742484643425438763224908097896054784000
|
||||||
|
});
|
||||||
|
|
||||||
|
// Total amounts
|
||||||
|
uint256 totalTakerAmount = takerAmounts[0][0] + takerAmounts[1][0];
|
||||||
|
uint256 totalMakerAmount = makerAmounts[0][0] + makerAmounts[1][0];
|
||||||
|
|
||||||
|
// We'll do a 50% partial fill
|
||||||
|
uint256 partialFillAmount = totalTakerAmount / 2;
|
||||||
|
uint256 expectedPartialOutput = totalMakerAmount / 2;
|
||||||
|
|
||||||
|
// Fund makers with FULL amounts (they need enough for any partial fill)
|
||||||
|
deal(USDC_ADDR, makerAddresses[0], makerAmounts[0][0]);
|
||||||
|
deal(USDC_ADDR, makerAddresses[1], makerAmounts[1][0]);
|
||||||
|
|
||||||
|
vm.prank(makerAddresses[0]);
|
||||||
|
USDC.approve(BEBOP_SETTLEMENT, makerAmounts[0][0]);
|
||||||
|
|
||||||
|
vm.prank(makerAddresses[1]);
|
||||||
|
USDC.approve(BEBOP_SETTLEMENT, makerAmounts[1][0]);
|
||||||
|
|
||||||
|
// ETH will be sent directly with the swap call
|
||||||
|
// Fund the test contract with ETH to send with the swap
|
||||||
|
vm.deal(address(this), partialFillAmount);
|
||||||
|
|
||||||
|
// Record initial balances
|
||||||
|
uint256 usdcBefore = USDC.balanceOf(originalTakerAddress);
|
||||||
|
|
||||||
|
// Create maker signatures
|
||||||
|
IBebopSettlement.MakerSignature[] memory signatures =
|
||||||
|
new IBebopSettlement.MakerSignature[](2);
|
||||||
|
signatures[0] = IBebopSettlement.MakerSignature({
|
||||||
|
signatureBytes: hex"d5abb425f9bac1f44d48705f41a8ab9cae207517be8553d2c03b06a88995f2f351ab8ce7627a87048178d539dd64fd2380245531a0c8e43fdc614652b1f32fc71c",
|
||||||
|
flags: 0
|
||||||
|
});
|
||||||
|
signatures[1] = IBebopSettlement.MakerSignature({
|
||||||
|
signatureBytes: hex"f38c698e48a3eac48f184bc324fef0b135ee13705ab38cc0bbf5a792f21002f051e445b9e7d57cf24c35e17629ea35b3263591c4abf8ca87ffa44b41301b89c41b",
|
||||||
|
flags: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// Encode order and signatures
|
||||||
|
bytes memory quoteData = abi.encode(order);
|
||||||
|
bytes memory makerSignaturesData = abi.encode(signatures);
|
||||||
|
|
||||||
|
// Create packed params for executor with partial fill amount
|
||||||
|
bytes memory params = abi.encodePacked(
|
||||||
|
address(0), // tokenIn: native ETH
|
||||||
|
USDC_ADDR,
|
||||||
|
uint8(RestrictTransferFrom.TransferType.Transfer),
|
||||||
|
uint8(BebopExecutor.OrderType.Aggregate),
|
||||||
|
partialFillAmount, // Specify partial fill amount
|
||||||
|
uint32(quoteData.length),
|
||||||
|
quoteData,
|
||||||
|
uint32(makerSignaturesData.length),
|
||||||
|
makerSignaturesData,
|
||||||
|
uint8(0) // approvalNeeded: false for native ETH
|
||||||
|
);
|
||||||
|
|
||||||
|
// Execute the partial aggregate swap with ETH value
|
||||||
|
uint256 amountOut = bebopExecutor.swap{value: partialFillAmount}(
|
||||||
|
partialFillAmount, params
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify results - should be proportional to the partial fill
|
||||||
|
assertEq(
|
||||||
|
amountOut, expectedPartialOutput, "Incorrect partial amount out"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
USDC.balanceOf(originalTakerAddress) - usdcBefore,
|
||||||
|
expectedPartialOutput,
|
||||||
|
"USDC balance mismatch for partial fill"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
address(bebopExecutor).balance,
|
||||||
|
initialExecutorBalance,
|
||||||
|
"ETH left in executor should match initial dust amount"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInvalidDataLength() public {
|
function testInvalidDataLength() public {
|
||||||
@@ -599,4 +912,114 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
vm.expectRevert(BebopExecutor.BebopExecutor__InvalidDataLength.selector);
|
vm.expectRevert(BebopExecutor.BebopExecutor__InvalidDataLength.selector);
|
||||||
bebopExecutor.decodeParams(tooShortParams);
|
bebopExecutor.decodeParams(tooShortParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Integration tests
|
||||||
|
function testSwapSingleIntegration() public {
|
||||||
|
// Fork at the right block first
|
||||||
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 22667985);
|
||||||
|
|
||||||
|
// Deploy Bebop executor harness
|
||||||
|
bebopExecutor =
|
||||||
|
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
|
||||||
|
|
||||||
|
// Load encoded data from test_encode_bebop_single (USDC → ONDO swap)
|
||||||
|
bytes memory protocolData =
|
||||||
|
loadCallDataFromFile("test_encode_bebop_single");
|
||||||
|
|
||||||
|
// Deal 200 USDC to the executor
|
||||||
|
uint256 amountIn = 200000000; // 200 USDC
|
||||||
|
deal(USDC_ADDR, address(bebopExecutor), amountIn);
|
||||||
|
|
||||||
|
// Fund the maker with ONDO and approve settlement
|
||||||
|
address maker = 0xCe79b081c0c924cb67848723ed3057234d10FC6b;
|
||||||
|
uint256 expectedAmountOut = 237212396774431060000; // 237.21 ONDO
|
||||||
|
deal(ONDO_ADDR, maker, expectedAmountOut);
|
||||||
|
vm.prank(maker);
|
||||||
|
ONDO.approve(BEBOP_SETTLEMENT, expectedAmountOut);
|
||||||
|
|
||||||
|
// Record receiver's initial ONDO balance
|
||||||
|
address receiver = 0xc5564C13A157E6240659fb81882A28091add8670;
|
||||||
|
uint256 ondoBefore = ONDO.balanceOf(receiver);
|
||||||
|
|
||||||
|
// Execute the swap
|
||||||
|
uint256 amountOut = bebopExecutor.swap(amountIn, protocolData);
|
||||||
|
|
||||||
|
// Verify results
|
||||||
|
assertEq(amountOut, expectedAmountOut, "Incorrect amount out");
|
||||||
|
assertEq(
|
||||||
|
ONDO.balanceOf(receiver) - ondoBefore,
|
||||||
|
expectedAmountOut,
|
||||||
|
"ONDO balance mismatch"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
USDC.balanceOf(address(bebopExecutor)), 0, "USDC left in executor"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
ONDO.balanceOf(address(bebopExecutor)), 0, "ONDO left in executor"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSwapAggregateIntegration() public {
|
||||||
|
// Fork at a suitable block for aggregate order testing
|
||||||
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 21370890);
|
||||||
|
|
||||||
|
// Deploy Bebop executor harness
|
||||||
|
bebopExecutor =
|
||||||
|
new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
|
||||||
|
|
||||||
|
// Store the initial ETH balance (dust from forked state)
|
||||||
|
uint256 initialExecutorBalance = address(bebopExecutor).balance;
|
||||||
|
|
||||||
|
// Based on real transaction: https://etherscan.io/tx/0xec88410136c287280da87d0a37c1cb745f320406ca3ae55c678dec11996c1b1c
|
||||||
|
address orderTaker = 0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6; // This is both taker and receiver in the order
|
||||||
|
uint256 ethAmount = 9850000000000000; // 0.00985 WETH
|
||||||
|
uint256 expAmountOut = 17969561; // 17.969561 USDC expected output
|
||||||
|
|
||||||
|
// Fund the two makers from the real transaction with USDC
|
||||||
|
address maker1 = 0x67336Cec42645F55059EfF241Cb02eA5cC52fF86;
|
||||||
|
address maker2 = 0xBF19CbF0256f19f39A016a86Ff3551ecC6f2aAFE;
|
||||||
|
|
||||||
|
deal(USDC_ADDR, maker1, 10607211); // Maker 1 provides 10.607211 USDC
|
||||||
|
deal(USDC_ADDR, maker2, 7362350); // Maker 2 provides 7.362350 USDC
|
||||||
|
|
||||||
|
// Makers approve settlement contract
|
||||||
|
vm.prank(maker1);
|
||||||
|
IERC20(USDC_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
||||||
|
vm.prank(maker2);
|
||||||
|
IERC20(USDC_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
||||||
|
|
||||||
|
// Fund ALICE with ETH as it will send the transaction
|
||||||
|
vm.deal(ALICE, ethAmount);
|
||||||
|
vm.startPrank(ALICE);
|
||||||
|
|
||||||
|
// Load encoded data from test_encode_bebop_aggregate (ETH → USDC multi-maker swap)
|
||||||
|
bytes memory protocolData =
|
||||||
|
loadCallDataFromFile("test_encode_bebop_aggregate");
|
||||||
|
|
||||||
|
// Record initial USDC balance
|
||||||
|
uint256 usdcBefore = 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");
|
||||||
|
assertEq(
|
||||||
|
IERC20(USDC_ADDR).balanceOf(orderTaker) - usdcBefore,
|
||||||
|
expAmountOut,
|
||||||
|
"USDC balance mismatch"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
IERC20(USDC_ADDR).balanceOf(address(bebopExecutor)),
|
||||||
|
0,
|
||||||
|
"USDC left in executor"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
address(bebopExecutor).balance,
|
||||||
|
initialExecutorBalance,
|
||||||
|
"ETH left in executor should match initial dust amount"
|
||||||
|
);
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2298,7 +2298,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let token_in = Bytes::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); // WETH
|
let token_in = Bytes::from(Address::ZERO.as_slice()); // Native ETH
|
||||||
let token_out = Bytes::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); // USDC
|
let token_out = Bytes::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); // USDC
|
||||||
let swap = Swap {
|
let swap = Swap {
|
||||||
component: bebop_component,
|
component: bebop_component,
|
||||||
@@ -2374,7 +2374,7 @@ mod tests {
|
|||||||
let expected_hex = format!(
|
let expected_hex = format!(
|
||||||
"{}{}{}{}{}{}{}{}{}{}",
|
"{}{}{}{}{}{}{}{}{}{}",
|
||||||
// token in
|
// token in
|
||||||
"c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
"0000000000000000000000000000000000000000",
|
||||||
// token out
|
// token out
|
||||||
"a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
"a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
||||||
// transfer type Transfer
|
// transfer type Transfer
|
||||||
@@ -2392,7 +2392,7 @@ mod tests {
|
|||||||
// abi-encoded maker signatures
|
// abi-encoded maker signatures
|
||||||
&encode(&encoded_maker_sigs),
|
&encode(&encoded_maker_sigs),
|
||||||
// approval needed
|
// approval needed
|
||||||
"01"
|
"00"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(hex_swap, expected_hex);
|
assert_eq!(hex_swap, expected_hex);
|
||||||
|
|||||||
Reference in New Issue
Block a user