fix(Bebop): Fix AggregateOrder tests
Delete BebopExecutionHarness.t.sol Took 53 minutes
This commit is contained in:
@@ -9,55 +9,6 @@ import {
|
|||||||
SafeERC20
|
SafeERC20
|
||||||
} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
import "@openzeppelin/contracts/utils/Address.sol";
|
import "@openzeppelin/contracts/utils/Address.sol";
|
||||||
import {console} from "forge-std/Test.sol";
|
|
||||||
|
|
||||||
/// @dev Bebop settlement interface for PMM RFQ swaps
|
|
||||||
interface IBebopSettlement {
|
|
||||||
struct Single {
|
|
||||||
uint256 expiry;
|
|
||||||
address taker_address;
|
|
||||||
address maker_address;
|
|
||||||
uint256 maker_nonce;
|
|
||||||
address taker_token;
|
|
||||||
address maker_token;
|
|
||||||
uint256 taker_amount;
|
|
||||||
uint256 maker_amount;
|
|
||||||
address receiver;
|
|
||||||
uint256 packed_commands;
|
|
||||||
uint256 flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Aggregate {
|
|
||||||
uint256 expiry;
|
|
||||||
address taker_address;
|
|
||||||
address[] maker_addresses;
|
|
||||||
uint256[] maker_nonces;
|
|
||||||
address[][] taker_tokens;
|
|
||||||
address[][] maker_tokens;
|
|
||||||
uint256[][] taker_amounts;
|
|
||||||
uint256[][] maker_amounts;
|
|
||||||
address receiver;
|
|
||||||
bytes commands;
|
|
||||||
uint256 flags; // `hashAggregateOrder` doesn't use this field for AggregateOrder hash
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MakerSignature {
|
|
||||||
bytes signatureBytes;
|
|
||||||
uint256 flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
function swapSingle(
|
|
||||||
Single calldata order,
|
|
||||||
MakerSignature calldata makerSignature,
|
|
||||||
uint256 filledTakerAmount
|
|
||||||
) external payable;
|
|
||||||
|
|
||||||
function swapAggregate(
|
|
||||||
Aggregate calldata order,
|
|
||||||
MakerSignature[] calldata makerSignatures,
|
|
||||||
uint256 filledTakerAmount
|
|
||||||
) external payable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @title BebopExecutor
|
/// @title BebopExecutor
|
||||||
/// @notice Executor for Bebop PMM RFQ (Request for Quote) swaps
|
/// @notice Executor for Bebop PMM RFQ (Request for Quote) swaps
|
||||||
@@ -69,7 +20,6 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
using Address for address;
|
using Address for address;
|
||||||
|
|
||||||
/// @notice Function selectors for Bebop settlement methods
|
/// @notice Function selectors for Bebop settlement methods
|
||||||
bytes4 public constant SWAP_SINGLE_SELECTOR = 0x4dcebcba;
|
|
||||||
bytes4 public constant SWAP_AGGREGATE_SELECTOR = 0xa2f74893;
|
bytes4 public constant SWAP_AGGREGATE_SELECTOR = 0xa2f74893;
|
||||||
|
|
||||||
/// @notice Bebop-specific errors
|
/// @notice Bebop-specific errors
|
||||||
@@ -100,14 +50,6 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
override
|
override
|
||||||
returns (uint256 calculatedAmount)
|
returns (uint256 calculatedAmount)
|
||||||
{
|
{
|
||||||
calculatedAmount = _swap(givenAmount, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _swap(uint256 givenAmount, bytes calldata data)
|
|
||||||
internal
|
|
||||||
returns (uint256 calculatedAmount)
|
|
||||||
{
|
|
||||||
// Decode the packed data
|
|
||||||
(
|
(
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
address tokenOut,
|
address tokenOut,
|
||||||
@@ -142,40 +84,9 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
// 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;
|
||||||
|
|
||||||
// Debug: Check msg.sender before settlement call
|
|
||||||
console.log(
|
|
||||||
"BebopExecutor: About to call settlement, msg.sender:", msg.sender
|
|
||||||
);
|
|
||||||
|
|
||||||
// Debug: Let's check what's in the calldata
|
|
||||||
bytes4 selector = _getSelector(finalCalldata);
|
|
||||||
if (selector == SWAP_AGGREGATE_SELECTOR) {
|
|
||||||
// Try to extract taker_address from the aggregate order
|
|
||||||
if (finalCalldata.length > 100) {
|
|
||||||
// Read the offset to the order struct
|
|
||||||
uint256 orderOffset;
|
|
||||||
assembly {
|
|
||||||
orderOffset := mload(add(finalCalldata, 0x24))
|
|
||||||
}
|
|
||||||
// The taker_address is at orderOffset + 4 (selector) + 32 (after expiry)
|
|
||||||
address orderTaker;
|
|
||||||
assembly {
|
|
||||||
orderTaker :=
|
|
||||||
mload(add(finalCalldata, add(0x24, add(orderOffset, 32))))
|
|
||||||
}
|
|
||||||
console.log("Order taker_address in calldata:", orderTaker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use OpenZeppelin's Address library for safe call with value
|
// Use OpenZeppelin's Address library for safe call with value
|
||||||
// This will revert if the call fails
|
// This will revert if the call fails
|
||||||
bytes memory returnData =
|
bebopSettlement.functionCallWithValue(finalCalldata, ethValue);
|
||||||
bebopSettlement.functionCallWithValue(finalCalldata, ethValue);
|
|
||||||
|
|
||||||
// Check if any tokens were actually transferred
|
|
||||||
if (returnData.length > 0) {
|
|
||||||
// Bebop might return some data, log it for debugging
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate actual amount received by the receiver
|
// Calculate actual amount received by the receiver
|
||||||
uint256 balanceAfter = _balanceOf(tokenOut, receiver);
|
uint256 balanceAfter = _balanceOf(tokenOut, receiver);
|
||||||
@@ -184,7 +95,7 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
|
|
||||||
/// @dev Decodes the packed calldata
|
/// @dev Decodes the packed calldata
|
||||||
function _decodeData(bytes calldata data)
|
function _decodeData(bytes calldata data)
|
||||||
public
|
internal
|
||||||
pure
|
pure
|
||||||
returns (
|
returns (
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
@@ -201,24 +112,13 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
// 20 + 20 + 1 + 1 (offset) + 32 (original amount) + 1 (approval) + 20 (receiver) = 95
|
// 20 + 20 + 1 + 1 (offset) + 32 (original amount) + 1 (approval) + 20 (receiver) = 95
|
||||||
if (data.length < 95) revert BebopExecutor__InvalidDataLength();
|
if (data.length < 95) revert BebopExecutor__InvalidDataLength();
|
||||||
|
|
||||||
// Decode fixed fields
|
|
||||||
tokenIn = address(bytes20(data[0:20]));
|
tokenIn = address(bytes20(data[0:20]));
|
||||||
tokenOut = address(bytes20(data[20:40]));
|
tokenOut = address(bytes20(data[20:40]));
|
||||||
transferType = TransferType(uint8(data[40]));
|
transferType = TransferType(uint8(data[40]));
|
||||||
|
|
||||||
// Extract partial fill offset
|
|
||||||
partialFillOffset = uint8(data[41]);
|
partialFillOffset = uint8(data[41]);
|
||||||
|
|
||||||
// Extract original amount in
|
|
||||||
originalFilledTakerAmount = uint256(bytes32(data[42:74]));
|
originalFilledTakerAmount = uint256(bytes32(data[42:74]));
|
||||||
|
|
||||||
// Extract approval flag
|
|
||||||
approvalNeeded = data[74] != 0;
|
approvalNeeded = data[74] != 0;
|
||||||
|
|
||||||
// Extract receiver address
|
|
||||||
receiver = address(bytes20(data[75:95]));
|
receiver = address(bytes20(data[75:95]));
|
||||||
|
|
||||||
// Extract bebop calldata (all remaining bytes)
|
|
||||||
bebopCalldata = data[95:];
|
bebopCalldata = data[95:];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +133,7 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
uint256 givenAmount,
|
uint256 givenAmount,
|
||||||
uint256 originalFilledTakerAmount,
|
uint256 originalFilledTakerAmount,
|
||||||
uint8 partialFillOffset
|
uint8 partialFillOffset
|
||||||
) public pure returns (bytes memory) {
|
) internal pure returns (bytes memory) {
|
||||||
// Use the offset from Bebop API to locate filledTakerAmount
|
// Use the offset from Bebop API to locate filledTakerAmount
|
||||||
// Position = 4 bytes (selector) + offset * 32 bytes
|
// Position = 4 bytes (selector) + offset * 32 bytes
|
||||||
uint256 filledTakerAmountPos = 4 + uint256(partialFillOffset) * 32;
|
uint256 filledTakerAmountPos = 4 + uint256(partialFillOffset) * 32;
|
||||||
@@ -261,14 +161,6 @@ contract BebopExecutor is IExecutor, IExecutorErrors, RestrictTransferFrom {
|
|||||||
return bebopCalldata;
|
return bebopCalldata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Helper function to extract selector from bytes
|
|
||||||
function _getSelector(bytes memory data) internal pure returns (bytes4) {
|
|
||||||
return bytes4(
|
|
||||||
uint32(uint8(data[0])) << 24 | uint32(uint8(data[1])) << 16
|
|
||||||
| uint32(uint8(data[2])) << 8 | uint32(uint8(data[3]))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Returns the balance of a token or ETH for an account
|
/// @dev Returns the balance of a token or ETH for an account
|
||||||
/// @param token The token address, or address(0) for ETH
|
/// @param token The token address, or address(0) for ETH
|
||||||
/// @param account The account to get the balance of
|
/// @param account The account to get the balance of
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -3,7 +3,6 @@ pragma solidity ^0.8.26;
|
|||||||
|
|
||||||
import "../TestUtils.sol";
|
import "../TestUtils.sol";
|
||||||
import "../TychoRouterTestSetup.sol";
|
import "../TychoRouterTestSetup.sol";
|
||||||
import "./BebopExecutionHarness.t.sol";
|
|
||||||
import "@src/executors/BebopExecutor.sol";
|
import "@src/executors/BebopExecutor.sol";
|
||||||
import {Constants} from "../Constants.sol";
|
import {Constants} from "../Constants.sol";
|
||||||
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
@@ -114,6 +113,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
|
|
||||||
// Single Order Tests
|
// Single Order Tests
|
||||||
function testSingleOrder() public {
|
function testSingleOrder() public {
|
||||||
|
// 1 WETH -> WBTC
|
||||||
vm.createSelectFork(vm.rpcUrl("mainnet"), 23124275);
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 23124275);
|
||||||
|
|
||||||
bebopExecutor =
|
bebopExecutor =
|
||||||
@@ -164,6 +164,7 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function testSingleOrder_PartialFill() public {
|
function testSingleOrder_PartialFill() public {
|
||||||
|
// 0.5 WETH -> WBTC with a quote for 1 WETH
|
||||||
vm.createSelectFork(vm.rpcUrl("mainnet"), 23124275);
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 23124275);
|
||||||
|
|
||||||
bebopExecutor =
|
bebopExecutor =
|
||||||
@@ -177,9 +178,64 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
RestrictTransferFrom.TransferType transferType =
|
RestrictTransferFrom.TransferType transferType =
|
||||||
RestrictTransferFrom.TransferType.None;
|
RestrictTransferFrom.TransferType.None;
|
||||||
uint8 partialFillOffset = 12;
|
uint8 partialFillOffset = 12;
|
||||||
uint256 amountIn = 1000000000000000000;
|
// filling only half of the quote
|
||||||
|
uint256 amountIn = 1000000000000000000 / 2;
|
||||||
bool approvalNeeded = true;
|
bool approvalNeeded = true;
|
||||||
uint256 expectedAmountOut = 3617660;
|
uint256 expectedAmountOut = 3617660 / 2;
|
||||||
|
|
||||||
|
deal(tokenIn, address(bebopExecutor), amountIn);
|
||||||
|
|
||||||
|
bytes memory params = abi.encodePacked(
|
||||||
|
tokenIn,
|
||||||
|
tokenOut,
|
||||||
|
transferType,
|
||||||
|
partialFillOffset,
|
||||||
|
amountIn * 2, // this is the original amount in
|
||||||
|
approvalNeeded,
|
||||||
|
address(bebopExecutor),
|
||||||
|
bebopCalldata
|
||||||
|
);
|
||||||
|
|
||||||
|
uint256 initialTokenOutBalance =
|
||||||
|
IERC20(tokenOut).balanceOf(address(bebopExecutor));
|
||||||
|
|
||||||
|
uint256 amountOut = bebopExecutor.swap(amountIn, params);
|
||||||
|
|
||||||
|
assertEq(amountOut, expectedAmountOut, "Incorrect partial amount out");
|
||||||
|
assertEq(
|
||||||
|
IERC20(tokenOut).balanceOf(address(bebopExecutor))
|
||||||
|
- initialTokenOutBalance,
|
||||||
|
expectedAmountOut,
|
||||||
|
"WETH should be at receiver"
|
||||||
|
);
|
||||||
|
assertEq(
|
||||||
|
IERC20(tokenIn).balanceOf(address(bebopExecutor)),
|
||||||
|
0,
|
||||||
|
"WBTC left in executor"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate Order Tests
|
||||||
|
function testAggregateOrder() public {
|
||||||
|
// 20k USDC -> ONDO
|
||||||
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 23126278);
|
||||||
|
bebopExecutor =
|
||||||
|
new BebopExecutorExposed(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
|
||||||
|
|
||||||
|
// Quote made manually using the BebopExecutor as the taker and receiver
|
||||||
|
bytes memory bebopCalldata =
|
||||||
|
hex"a2f7489300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000689b715d0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000005a0e0c07568b14a2d2c1b4d196000fc12bc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f000000000000000000000000ce79b081c0c924cb67848723ed3057234d10fc6b00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000002a65384e777abcfe0000000000000000000000000000000000000000000000002a65384e777abcff0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be30000000000000000000000000000000000000000000000000000000000000001000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000236ddb7a7000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000002713a105900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000001e7dc63f0c1d9d93df4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000021960567af238bcfd0000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000041275c4b7c3df4bfa5c33da3443d817cc6ab568ec8b0fddc30445adff2e870cdcd7d8738e23b795c2fb1ee112e12716bcef1cf648bd1ded17ef10ae493d687322e1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004187ef3d632a640b09df5f39b2fb4c5b9afb7ab4f2782fee450b17e2363d27303b45ec55b154a63993106bfc28bb4accc10fb40f7927509fed554fac01a5d88bae1c00000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
address tokenIn = USDC_ADDR;
|
||||||
|
address tokenOut = ONDO_ADDR;
|
||||||
|
RestrictTransferFrom.TransferType transferType =
|
||||||
|
RestrictTransferFrom.TransferType.None;
|
||||||
|
uint8 partialFillOffset = 2;
|
||||||
|
// filling only half of the quote
|
||||||
|
uint256 amountIn = 20000000000;
|
||||||
|
bool approvalNeeded = true;
|
||||||
|
// maker amounts from quote
|
||||||
|
uint256 expectedAmountOut =
|
||||||
|
(8999445165322964385268 + 9912843438638420000000);
|
||||||
|
|
||||||
deal(tokenIn, address(bebopExecutor), amountIn);
|
deal(tokenIn, address(bebopExecutor), amountIn);
|
||||||
|
|
||||||
@@ -197,307 +253,76 @@ contract BebopExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
uint256 initialTokenOutBalance =
|
uint256 initialTokenOutBalance =
|
||||||
IERC20(tokenOut).balanceOf(address(bebopExecutor));
|
IERC20(tokenOut).balanceOf(address(bebopExecutor));
|
||||||
|
|
||||||
// filling only half of the order
|
uint256 amountOut = bebopExecutor.swap(amountIn, params);
|
||||||
uint256 amountOut = bebopExecutor.swap(amountIn / 2, params);
|
|
||||||
|
assertEq(amountOut, expectedAmountOut, "Incorrect amount out");
|
||||||
|
|
||||||
assertEq(
|
|
||||||
amountOut, expectedAmountOut / 2, "Incorrect partial amount out"
|
|
||||||
);
|
|
||||||
assertEq(
|
assertEq(
|
||||||
IERC20(tokenOut).balanceOf(address(bebopExecutor))
|
IERC20(tokenOut).balanceOf(address(bebopExecutor))
|
||||||
- initialTokenOutBalance,
|
- initialTokenOutBalance,
|
||||||
expectedAmountOut / 2,
|
expectedAmountOut,
|
||||||
"WETH should be at receiver"
|
"ONDO should be at receiver"
|
||||||
);
|
);
|
||||||
// half of the amount in should remain in the executor
|
|
||||||
assertEq(
|
assertEq(
|
||||||
IERC20(tokenIn).balanceOf(address(bebopExecutor)),
|
IERC20(tokenIn).balanceOf(address(bebopExecutor)),
|
||||||
amountIn / 2,
|
0,
|
||||||
"Wrong amount of WBTC left in executor"
|
"USDC left in executor"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aggregate Order Tests
|
function testAggregateOrder_PartialFill() public {
|
||||||
// function testAggregateOrder() public {
|
// 10k USDC -> ONDO with a quote for 20k USDC
|
||||||
// // Fork at the block just before the actual transaction
|
vm.createSelectFork(vm.rpcUrl("mainnet"), 23126278);
|
||||||
// vm.createSelectFork(vm.rpcUrl("mainnet"), 22410851);
|
bebopExecutor =
|
||||||
//
|
new BebopExecutorExposed(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
|
||||||
// // Deploy Bebop executor harness that uses vm.prank
|
|
||||||
// bebopExecutor =
|
// Quote made manually using the BebopExecutor as the taker and receiver
|
||||||
// new BebopExecutorHarness(BEBOP_SETTLEMENT, PERMIT2_ADDRESS);
|
bytes memory bebopCalldata =
|
||||||
//
|
hex"a2f7489300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000689b715d0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000005a0e0c07568b14a2d2c1b4d196000fc12bc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f000000000000000000000000ce79b081c0c924cb67848723ed3057234d10fc6b00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000002a65384e777abcfe0000000000000000000000000000000000000000000000002a65384e777abcff0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be30000000000000000000000000000000000000000000000000000000000000001000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be300000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000236ddb7a7000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000002713a105900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000001e7dc63f0c1d9d93df4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000021960567af238bcfd0000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000041275c4b7c3df4bfa5c33da3443d817cc6ab568ec8b0fddc30445adff2e870cdcd7d8738e23b795c2fb1ee112e12716bcef1cf648bd1ded17ef10ae493d687322e1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004187ef3d632a640b09df5f39b2fb4c5b9afb7ab4f2782fee450b17e2363d27303b45ec55b154a63993106bfc28bb4accc10fb40f7927509fed554fac01a5d88bae1c00000000000000000000000000000000000000000000000000000000000000";
|
||||||
// // Store the initial ETH balance (dust from forked state)
|
address tokenIn = USDC_ADDR;
|
||||||
// uint256 initialExecutorBalance = address(bebopExecutor).balance;
|
address tokenOut = ONDO_ADDR;
|
||||||
//
|
RestrictTransferFrom.TransferType transferType =
|
||||||
// // Create test data from real mainnet transaction
|
RestrictTransferFrom.TransferType.None;
|
||||||
// // https://etherscan.io/tx/0xec88410136c287280da87d0a37c1cb745f320406ca3ae55c678dec11996c1b1c
|
uint8 partialFillOffset = 2;
|
||||||
// address originalTakerAddress =
|
// filling only half of the quote
|
||||||
// 0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6;
|
uint256 amountIn = 20000000000 / 2;
|
||||||
//
|
bool approvalNeeded = true;
|
||||||
// // Create the 2D arrays for tokens and amounts
|
// maker amounts from quote
|
||||||
// address[][] memory takerTokens = new address[][](2);
|
uint256 expectedAmountOut =
|
||||||
// takerTokens[0] = new address[](1);
|
(8999445165322964385268 + 9912843438638420000000) / 2;
|
||||||
// takerTokens[0][0] = WETH_ADDR; // WETH for first maker
|
|
||||||
// takerTokens[1] = new address[](1);
|
deal(tokenIn, address(bebopExecutor), amountIn);
|
||||||
// takerTokens[1][0] = WETH_ADDR; // WETH for second maker
|
|
||||||
//
|
bytes memory params = abi.encodePacked(
|
||||||
// address[][] memory makerTokens = new address[][](2);
|
tokenIn,
|
||||||
// makerTokens[0] = new address[](1);
|
tokenOut,
|
||||||
// makerTokens[0][0] = USDC_ADDR; // USDC from first maker
|
transferType,
|
||||||
// makerTokens[1] = new address[](1);
|
partialFillOffset,
|
||||||
// makerTokens[1][0] = USDC_ADDR; // USDC from second maker
|
amountIn * 2, // this is the original amount from the quote
|
||||||
//
|
approvalNeeded,
|
||||||
// uint256[][] memory takerAmounts = new uint256[][](2);
|
address(bebopExecutor),
|
||||||
// takerAmounts[0] = new uint256[](1);
|
bebopCalldata
|
||||||
// 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 initialTokenOutBalance =
|
||||||
//
|
IERC20(tokenOut).balanceOf(address(bebopExecutor));
|
||||||
// uint256[][] memory makerAmounts = new uint256[][](2);
|
|
||||||
// makerAmounts[0] = new uint256[](1);
|
uint256 amountOut = bebopExecutor.swap(amountIn, params);
|
||||||
// makerAmounts[0][0] = 10607211; // First maker gives ~10.6 USDC
|
|
||||||
// makerAmounts[1] = new uint256[](1);
|
assertEq(amountOut, expectedAmountOut, "Incorrect amount out");
|
||||||
// makerAmounts[1][0] = 7362350; // Second maker gives ~7.36 USDC
|
|
||||||
//
|
assertEq(
|
||||||
// // Create makers array
|
IERC20(tokenOut).balanceOf(address(bebopExecutor))
|
||||||
// address[] memory makerAddresses = new address[](2);
|
- initialTokenOutBalance,
|
||||||
// makerAddresses[0] = 0x67336Cec42645F55059EfF241Cb02eA5cC52fF86;
|
expectedAmountOut,
|
||||||
// makerAddresses[1] = 0xBF19CbF0256f19f39A016a86Ff3551ecC6f2aAFE;
|
"ONDO should be at receiver"
|
||||||
//
|
);
|
||||||
// // Create maker nonces array
|
assertEq(
|
||||||
// uint256[] memory makerNonces = new uint256[](2);
|
IERC20(tokenIn).balanceOf(address(bebopExecutor)),
|
||||||
// makerNonces[0] = 1746367197308;
|
1, // because of integer division, there is 1 USDC left in the executor
|
||||||
// makerNonces[1] = 15460096;
|
"USDC left in executor"
|
||||||
//
|
);
|
||||||
// // Create the aggregate order
|
}
|
||||||
// IBebopSettlement.Aggregate memory order = IBebopSettlement.Aggregate({
|
|
||||||
// expiry: 1746367285, // Original expiry that matches the signatures
|
|
||||||
// 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]);
|
|
||||||
//
|
|
||||||
// // For native ETH, settlement pulls from taker; fund taker with ETH
|
|
||||||
// vm.deal(originalTakerAddress, totalTakerAmount + 1 ether);
|
|
||||||
//
|
|
||||||
// // 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
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// // Build the bebop calldata for swapAggregate
|
|
||||||
// // Manually encode with correct selector since abi.encodeCall generates wrong selector
|
|
||||||
// bytes memory bebopCalldata = abi.encodePacked(
|
|
||||||
// bytes4(0xa2f74893), // swapAggregate selector
|
|
||||||
// abi.encode(order, signatures, totalTakerAmount) // Use totalTakerAmount when filledTakerAmount would be 0
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // 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(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
|
|
||||||
// totalTakerAmount, // originalAmountIn
|
|
||||||
// uint8(0), // approvalNeeded: false for native ETH
|
|
||||||
// originalTakerAddress, // receiver from order
|
|
||||||
// bebopCalldata
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // 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
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // Verify results
|
|
||||||
// assertEq(amountOut, totalMakerAmount, "Incorrect amount out");
|
|
||||||
// // Since we're using real order data, tokens go to the original receiver
|
|
||||||
// assertEq(
|
|
||||||
// USDC.balanceOf(originalTakerAddress) - initialUsdcBalance,
|
|
||||||
// totalMakerAmount,
|
|
||||||
// "USDC should be at receiver"
|
|
||||||
// );
|
|
||||||
// // With pranking, settlement pulls ETH from taker; executor keeps msg.value on top of initial dust
|
|
||||||
// assertEq(
|
|
||||||
// address(bebopExecutor).balance,
|
|
||||||
// initialExecutorBalance + totalTakerAmount,
|
|
||||||
// "Executor ETH balance should be initial + msg.value for aggregate ETH flow"
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// function testAggregateOrder_PartialFill() public {
|
|
||||||
// // Fork at the block just before the actual transaction
|
|
||||||
// vm.createSelectFork(vm.rpcUrl("mainnet"), 22410851);
|
|
||||||
//
|
|
||||||
// // 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, // Original expiry that matches the signatures
|
|
||||||
// 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]);
|
|
||||||
//
|
|
||||||
// // For native ETH, settlement pulls from taker; fund taker with ETH
|
|
||||||
// vm.deal(originalTakerAddress, partialFillAmount + 1 ether);
|
|
||||||
//
|
|
||||||
// // 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
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// // Build the bebop calldata for swapAggregate with partial fill
|
|
||||||
// // Manually encode with correct selector since abi.encodeCall generates wrong selector
|
|
||||||
// bytes memory bebopCalldata = abi.encodePacked(
|
|
||||||
// bytes4(0xa2f74893), // swapAggregate selector
|
|
||||||
// abi.encode(order, signatures, partialFillAmount) // Specify partial fill amount
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // 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(2), // partialFillOffset for swapAggregate (68 = 4 + 2*32)
|
|
||||||
// totalTakerAmount, // originalAmountIn (full order amount)
|
|
||||||
// uint8(0), // approvalNeeded: false for native ETH
|
|
||||||
// originalTakerAddress, // receiver from order
|
|
||||||
// bebopCalldata
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // 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
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// // Verify results - should be proportional to the partial fill
|
|
||||||
// assertEq(
|
|
||||||
// amountOut, expectedPartialOutput, "Incorrect partial amount out"
|
|
||||||
// );
|
|
||||||
// // Since we're using real order data, tokens go to the original receiver
|
|
||||||
// assertEq(
|
|
||||||
// USDC.balanceOf(originalTakerAddress) - initialUsdcBalance,
|
|
||||||
// expectedPartialOutput,
|
|
||||||
// "USDC should be at receiver"
|
|
||||||
// );
|
|
||||||
// // With pranking, settlement pulls ETH from taker; executor keeps msg.value on top of initial dust
|
|
||||||
// assertEq(
|
|
||||||
// address(bebopExecutor).balance,
|
|
||||||
// initialExecutorBalance + partialFillAmount,
|
|
||||||
// "Executor ETH balance should be initial + msg.value for aggregate ETH flow"
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
function testInvalidDataLength() public {
|
function testInvalidDataLength() public {
|
||||||
// Fork to ensure consistent setup
|
// Fork to ensure consistent setup
|
||||||
@@ -581,41 +406,32 @@ contract TychoRouterForBebopTest is TychoRouterTestSetup {
|
|||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
}
|
}
|
||||||
|
|
||||||
// function testBebopAggregateIntegration() public {
|
function testBebopAggregateIntegration() public {
|
||||||
// // Test aggregate order integration
|
// The calldata swaps 20k USDC for ONDO using multiple market makers
|
||||||
// address orderTaker = 0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6;
|
address user = 0xd2068e04Cf586f76EEcE7BA5bEB779D7bB1474A1;
|
||||||
// uint256 ethAmount = 9850000000000000; // 0.00985 WETH
|
deal(USDC_ADDR, user, 20000000000); // 20k USDC
|
||||||
// uint256 expAmountOut = 17969561; // 17.969561 USDC expected output
|
uint256 expAmountOut = 18699321819466078474202; // Expected ONDO amount from quote
|
||||||
//
|
|
||||||
// // Fund makers with USDC
|
uint256 ondoBefore = IERC20(ONDO_ADDR).balanceOf(user);
|
||||||
// address maker1 = 0x67336Cec42645F55059EfF241Cb02eA5cC52fF86;
|
vm.startPrank(user);
|
||||||
// address maker2 = 0xBF19CbF0256f19f39A016a86Ff3551ecC6f2aAFE;
|
IERC20(USDC_ADDR).approve(tychoRouterAddr, type(uint256).max);
|
||||||
// deal(USDC_ADDR, maker1, 10607211);
|
|
||||||
// deal(USDC_ADDR, maker2, 7362350);
|
bytes memory callData = loadCallDataFromFile(
|
||||||
//
|
"test_single_encoding_strategy_bebop_aggregate"
|
||||||
// vm.prank(maker1);
|
);
|
||||||
// IERC20(USDC_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
|
||||||
// vm.prank(maker2);
|
(bool success,) = tychoRouterAddr.call(callData);
|
||||||
// IERC20(USDC_ADDR).approve(BEBOP_SETTLEMENT, type(uint256).max);
|
|
||||||
//
|
assertTrue(success, "Call Failed");
|
||||||
// // Fund taker with WETH
|
|
||||||
// deal(WETH_ADDR, orderTaker, ethAmount);
|
uint256 ondoReceived = IERC20(ONDO_ADDR).balanceOf(user) - ondoBefore;
|
||||||
//
|
assertEq(ondoReceived, expAmountOut);
|
||||||
// vm.startPrank(orderTaker);
|
assertEq(
|
||||||
// IERC20(WETH_ADDR).approve(tychoRouterAddr, ethAmount);
|
IERC20(USDC_ADDR).balanceOf(tychoRouterAddr),
|
||||||
//
|
0,
|
||||||
// // Load calldata from file
|
"USDC left in router"
|
||||||
// bytes memory callData = loadCallDataFromFile(
|
);
|
||||||
// "test_single_encoding_strategy_bebop_aggregate"
|
|
||||||
// );
|
vm.stopPrank();
|
||||||
//
|
}
|
||||||
// (bool success,) = tychoRouterAddr.call(callData);
|
|
||||||
//
|
|
||||||
// uint256 finalBalance = IERC20(USDC_ADDR).balanceOf(orderTaker);
|
|
||||||
//
|
|
||||||
// assertTrue(success, "Call Failed");
|
|
||||||
// assertEq(finalBalance, expAmountOut);
|
|
||||||
//
|
|
||||||
// vm.stopPrank();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,181 +0,0 @@
|
|||||||
// SPDX-License-Identifier: BUSL-1.1
|
|
||||||
pragma solidity ^0.8.10;
|
|
||||||
|
|
||||||
import "../../src/executors/BebopExecutor.sol";
|
|
||||||
import {Test, console, Vm} from "forge-std/Test.sol";
|
|
||||||
import {VmSafe} from "forge-std/Vm.sol";
|
|
||||||
import "@openzeppelin/contracts/utils/Address.sol";
|
|
||||||
|
|
||||||
contract BebopExecutorHarness is BebopExecutor, Test {
|
|
||||||
using SafeERC20 for IERC20;
|
|
||||||
using Address for address;
|
|
||||||
|
|
||||||
constructor(address _bebopSettlement, address _permit2)
|
|
||||||
BebopExecutor(_bebopSettlement, _permit2)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/// @dev Helper function to strip selector from bytes using assembly
|
|
||||||
function _stripSelector(bytes memory data)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (bytes memory bebopCalldataWithoutSelector)
|
|
||||||
{
|
|
||||||
require(data.length >= 4, "BE: data too short for selector");
|
|
||||||
uint256 outLen = data.length - 4;
|
|
||||||
bebopCalldataWithoutSelector = new bytes(outLen);
|
|
||||||
// Safe byte-by-byte copy to avoid writing past the end of the target bytes array
|
|
||||||
for (uint256 i = 0; i < outLen; i++) {
|
|
||||||
bebopCalldataWithoutSelector[i] = data[i + 4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose the internal decodeData function for testing
|
|
||||||
function decodeParams(bytes calldata data)
|
|
||||||
external
|
|
||||||
pure
|
|
||||||
returns (
|
|
||||||
address tokenIn,
|
|
||||||
address tokenOut,
|
|
||||||
TransferType transferType,
|
|
||||||
uint8 partialFillOffset,
|
|
||||||
uint256 originalFilledTakerAmount,
|
|
||||||
bool approvalNeeded,
|
|
||||||
address receiver,
|
|
||||||
bytes memory bebopCalldata
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return _decodeData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose the internal modifyFilledTakerAmount function for testing
|
|
||||||
function exposed_modifyFilledTakerAmount(
|
|
||||||
bytes memory bebopCalldata,
|
|
||||||
uint256 givenAmount,
|
|
||||||
uint256 originalFilledTakerAmount,
|
|
||||||
uint8 partialFillOffset
|
|
||||||
) external pure returns (bytes memory) {
|
|
||||||
return _modifyFilledTakerAmount(
|
|
||||||
bebopCalldata,
|
|
||||||
givenAmount,
|
|
||||||
originalFilledTakerAmount,
|
|
||||||
partialFillOffset
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override swap so router integration tests impersonate the taker when calling settlement
|
|
||||||
function swap(uint256 givenAmount, bytes calldata data)
|
|
||||||
external
|
|
||||||
payable
|
|
||||||
override
|
|
||||||
returns (uint256 calculatedAmount)
|
|
||||||
{
|
|
||||||
console.log("BebopExecutorHarness::swap called");
|
|
||||||
console.log(" Given amount:", givenAmount);
|
|
||||||
console.log(" Data length:", data.length);
|
|
||||||
console.log(" Msg.sender:", msg.sender);
|
|
||||||
// Decode the data to get the bebop calldata
|
|
||||||
(
|
|
||||||
address tokenIn,
|
|
||||||
address tokenOut,
|
|
||||||
TransferType transferType,
|
|
||||||
uint8 partialFillOffset,
|
|
||||||
uint256 originalFilledTakerAmount,
|
|
||||||
bool approvalNeeded,
|
|
||||||
address receiver,
|
|
||||||
bytes memory bebopCalldata
|
|
||||||
) = _decodeData(data);
|
|
||||||
|
|
||||||
// Extract the selector to determine order type
|
|
||||||
bytes4 selector = bytes4(bebopCalldata);
|
|
||||||
|
|
||||||
// Extract taker address from the order - Bebop validates msg.sender == order.taker_address
|
|
||||||
address takerAddress = receiver;
|
|
||||||
|
|
||||||
// For ERC20 tokens, we need to handle the flow differently
|
|
||||||
// The taker needs to have the tokens and approve the settlement
|
|
||||||
if (tokenIn != address(0)) {
|
|
||||||
// When called via delegatecall from the router, address(this) is the router
|
|
||||||
// So we check the balance of address(this) which will be the router
|
|
||||||
uint256 balance = IERC20(tokenIn).balanceOf(address(this));
|
|
||||||
console.log("Balance of tokenIn at address(this):", balance);
|
|
||||||
console.log("Address(this):", address(this));
|
|
||||||
|
|
||||||
// If we don't have tokens, the taker should have them
|
|
||||||
if (balance < givenAmount) {
|
|
||||||
// Try to transfer from the taker (who should have approved the router)
|
|
||||||
console.log("Transferring from taker to address(this)");
|
|
||||||
IERC20(tokenIn).transferFrom(
|
|
||||||
takerAddress, address(this), givenAmount
|
|
||||||
);
|
|
||||||
balance = IERC20(tokenIn).balanceOf(address(this));
|
|
||||||
console.log("Balance after transfer:", balance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the modified filledTakerAmount (what will actually be used)
|
|
||||||
bytes memory modifiedCalldata = _modifyFilledTakerAmount(
|
|
||||||
bebopCalldata,
|
|
||||||
givenAmount,
|
|
||||||
originalFilledTakerAmount,
|
|
||||||
partialFillOffset
|
|
||||||
);
|
|
||||||
|
|
||||||
// Extract the actual filledTakerAmount that will be used
|
|
||||||
uint256 actualFilledAmount = originalFilledTakerAmount > givenAmount
|
|
||||||
? givenAmount
|
|
||||||
: originalFilledTakerAmount;
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
"Original filled taker amount:", originalFilledTakerAmount
|
|
||||||
);
|
|
||||||
console.log("Actual filled amount to use:", actualFilledAmount);
|
|
||||||
|
|
||||||
// Only transfer what's needed to the taker, keep the rest in router
|
|
||||||
IERC20(tokenIn).transfer(takerAddress, actualFilledAmount);
|
|
||||||
console.log("Transferred tokens to taker:", actualFilledAmount);
|
|
||||||
|
|
||||||
// Check balances after transfer
|
|
||||||
uint256 takerBalance = IERC20(tokenIn).balanceOf(takerAddress);
|
|
||||||
uint256 routerBalance = IERC20(tokenIn).balanceOf(address(this));
|
|
||||||
console.log("After transfer - Taker balance:", takerBalance);
|
|
||||||
console.log(
|
|
||||||
"After transfer - Router balance (dust):", routerBalance
|
|
||||||
);
|
|
||||||
|
|
||||||
// Impersonate the taker and approve settlement for what they have
|
|
||||||
vm.startPrank(takerAddress);
|
|
||||||
IERC20(tokenIn).approve(bebopSettlement, actualFilledAmount);
|
|
||||||
console.log("Taker approved settlement for:", actualFilledAmount);
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
// Check if taker still has the tokens
|
|
||||||
takerBalance = IERC20(tokenIn).balanceOf(takerAddress);
|
|
||||||
console.log("After approval - Taker balance:", takerBalance);
|
|
||||||
|
|
||||||
// Start pranking as taker for the actual swap
|
|
||||||
vm.startPrank(takerAddress);
|
|
||||||
} else {
|
|
||||||
// For ETH, start pranking as taker
|
|
||||||
vm.startPrank(takerAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the actual bebop call details
|
|
||||||
console.log("Calling Bebop settlement with:");
|
|
||||||
console.log(" Taker address:", takerAddress);
|
|
||||||
console.log(" Token in:", tokenIn);
|
|
||||||
console.log(" Token out:", tokenOut);
|
|
||||||
console.log(" Given amount:", givenAmount);
|
|
||||||
console.log(" Receiver:", receiver);
|
|
||||||
console.log(" Bebop calldata length:", bebopCalldata.length);
|
|
||||||
console.log(" Natural msg.sender (no prank):", msg.sender);
|
|
||||||
|
|
||||||
// Call the parent implementation which handles the actual swap
|
|
||||||
// The taker prank is already active from above
|
|
||||||
console.log("About to call _swap, msg.sender is:", msg.sender);
|
|
||||||
console.log("Pranked as taker:", takerAddress);
|
|
||||||
calculatedAmount = _swap(givenAmount, data);
|
|
||||||
|
|
||||||
vm.stopPrank();
|
|
||||||
|
|
||||||
console.log("Calculated amount returned:", calculatedAmount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -586,7 +586,8 @@ fn test_single_encoding_strategy_balancer_v3() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_single_encoding_strategy_bebop() {
|
fn test_single_encoding_strategy_bebop() {
|
||||||
// The quote was done separately where the sender is the router and the receiver is a random
|
// The quote was done separately where the sender is the router and the receiver is a random
|
||||||
// user let _router = Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap();
|
// user
|
||||||
|
let _router = Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap();
|
||||||
let user = Bytes::from_str("0xd2068e04cf586f76eece7ba5beb779d7bb1474a1").unwrap();
|
let user = Bytes::from_str("0xd2068e04cf586f76eece7ba5beb779d7bb1474a1").unwrap();
|
||||||
|
|
||||||
let token_in = usdc();
|
let token_in = usdc();
|
||||||
@@ -595,10 +596,7 @@ fn test_single_encoding_strategy_bebop() {
|
|||||||
let amount_out = BigUint::from_str("194477331556159832309").unwrap(); // 203.8 ONDO
|
let amount_out = BigUint::from_str("194477331556159832309").unwrap(); // 203.8 ONDO
|
||||||
let partial_fill_offset = 12;
|
let partial_fill_offset = 12;
|
||||||
|
|
||||||
// Encode using standard ABI encoding (not packed)
|
|
||||||
let calldata = Bytes::from_str("0x4dcebcba00000000000000000000000000000000000000000000000000000000689b548f0000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000067336cec42645f55059eff241cb02ea5cc52ff86000000000000000000000000000000000000000000000000279ead5d9685f25b000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be3000000000000000000000000000000000000000000000000000000000bebc20000000000000000000000000000000000000000000000000a8aea46aa4ec5c0f5000000000000000000000000d2068e04cf586f76eece7ba5beb779d7bb1474a100000000000000000000000000000000000000000000000000000000000000005230bcb979c81cebf94a3b5c08bcfa300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000414ce40058ff07f11d9224c2c8d1e58369e4a90173856202d8d2a17da48058ad683dedb742eda0d4c0cf04cf1c09138898dd7fd06f97268ea7f74ef9b42d29bf4c1b00000000000000000000000000000000000000000000000000000000000000").unwrap();
|
let calldata = Bytes::from_str("0x4dcebcba00000000000000000000000000000000000000000000000000000000689b548f0000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d0139500000000000000000000000067336cec42645f55059eff241cb02ea5cc52ff86000000000000000000000000000000000000000000000000279ead5d9685f25b000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be3000000000000000000000000000000000000000000000000000000000bebc20000000000000000000000000000000000000000000000000a8aea46aa4ec5c0f5000000000000000000000000d2068e04cf586f76eece7ba5beb779d7bb1474a100000000000000000000000000000000000000000000000000000000000000005230bcb979c81cebf94a3b5c08bcfa300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000414ce40058ff07f11d9224c2c8d1e58369e4a90173856202d8d2a17da48058ad683dedb742eda0d4c0cf04cf1c09138898dd7fd06f97268ea7f74ef9b42d29bf4c1b00000000000000000000000000000000000000000000000000000000000000").unwrap();
|
||||||
|
|
||||||
// Build user_data with the quote and signature using new calldata format
|
|
||||||
let user_data = build_bebop_calldata(&calldata, partial_fill_offset);
|
let user_data = build_bebop_calldata(&calldata, partial_fill_offset);
|
||||||
|
|
||||||
let bebop_component = ProtocolComponent {
|
let bebop_component = ProtocolComponent {
|
||||||
@@ -649,138 +647,69 @@ fn test_single_encoding_strategy_bebop() {
|
|||||||
let hex_calldata = hex::encode(&calldata);
|
let hex_calldata = hex::encode(&calldata);
|
||||||
write_calldata_to_file("test_single_encoding_strategy_bebop", hex_calldata.as_str());
|
write_calldata_to_file("test_single_encoding_strategy_bebop", hex_calldata.as_str());
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn test_single_encoding_strategy_bebop_aggregate() {
|
fn test_single_encoding_strategy_bebop_aggregate() {
|
||||||
// // Use real mainnet aggregate order data from CLAUDE.md
|
// The quote was done separately where the sender is the router and the receiver is a random
|
||||||
// // Transaction: https://etherscan.io/tx/0xec88410136c287280da87d0a37c1cb745f320406ca3ae55c678dec11996c1b1c
|
// user
|
||||||
// // Use native ETH as tycho's token_in
|
let _router = Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap();
|
||||||
// let token_in = eth();
|
let user = Bytes::from_str("0xd2068e04cf586f76eece7ba5beb779d7bb1474a1").unwrap();
|
||||||
// let token_out = usdc();
|
|
||||||
// let amount_in = BigUint::from_str("9850000000000000").unwrap(); // 0.00985 WETH
|
let token_in = usdc();
|
||||||
// let amount_out = BigUint::from_str("17969561").unwrap(); // 17.969561 USDC
|
let token_out = ondo();
|
||||||
//
|
let amount_in = BigUint::from_str("20000000000").unwrap(); // 20k USDC
|
||||||
// // Create the exact aggregate order from mainnet
|
let amount_out = BigUint::from_str("18699321819466078474202").unwrap(); // 203.8 ONDO
|
||||||
// let expiry = 1746367285u64;
|
let partial_fill_offset = 2;
|
||||||
// let taker_address = Address::from_str("0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6").unwrap();
|
|
||||||
// let receiver = Address::from_str("0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6").unwrap();
|
let calldata = Bytes::from_str("0xa2f7489300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000689b78880000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000d2068e04cf586f76eece7ba5beb779d7bb1474a100000000000000000000000000000000000000000000000000000000000005a060a5c2aaaaa2fe2cda34423cac76a84c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000051c72848c68a965f66fa7a88855f9f7784502a7f000000000000000000000000ce79b081c0c924cb67848723ed3057234d10fc6b00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000002901f2d62bb356ca0000000000000000000000000000000000000000000000002901f2d62bb356cb0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be30000000000000000000000000000000000000000000000000000000000000001000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be30000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000044f83c726000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000589400da00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000003aa5f96046644f6e37a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000004b51a26526ddbeec60000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000417ab4332f2b091d87d56d04eee35dd49452782c782de71608c0425c5ae41f1d7e147173851c870d76720ce07d45cd8622352716b1c7965819ee2bf8c573c499ae1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410c8da2637aa929e11caff9afdfc4c489320c6dba77cc934d88ba8956e365fd1d48983087c6e474bbb828181cdfdd17317c4c9c3ee4bc98e3769d0c05cc7a285e1c00000000000000000000000000000000000000000000000000000000000000").unwrap();
|
||||||
//
|
let user_data = build_bebop_calldata(&calldata, partial_fill_offset);
|
||||||
// // Set up makers
|
|
||||||
// let maker_addresses = vec![
|
let bebop_component = ProtocolComponent {
|
||||||
// Address::from_str("0x67336Cec42645F55059EfF241Cb02eA5cC52fF86").unwrap(),
|
id: String::from("bebop-rfq"),
|
||||||
// Address::from_str("0xBF19CbF0256f19f39A016a86Ff3551ecC6f2aAFE").unwrap(),
|
protocol_system: String::from("rfq:bebop"),
|
||||||
// ];
|
static_attributes: HashMap::new(),
|
||||||
// let maker_nonces = vec![U256::from(1746367197308u64), U256::from(15460096u64)];
|
..Default::default()
|
||||||
//
|
};
|
||||||
// // 2D arrays for tokens
|
|
||||||
// // We use WETH as a taker token even when handling native ETH
|
let swap = Swap {
|
||||||
// let taker_tokens = vec![vec![Address::from_slice(&weth())],
|
component: bebop_component,
|
||||||
// vec![Address::from_slice(&weth())]]; let maker_tokens =
|
token_in: token_in.clone(),
|
||||||
// vec![vec![Address::from_slice(&token_out)], vec![Address::from_slice(&token_out)]];
|
token_out: token_out.clone(),
|
||||||
//
|
split: 0f64,
|
||||||
// // 2D arrays for amounts
|
user_data: Some(user_data),
|
||||||
// let taker_amounts = vec![
|
protocol_state: None,
|
||||||
// vec![U256::from_str("5812106401997138").unwrap()],
|
};
|
||||||
// vec![U256::from_str("4037893598002862").unwrap()],
|
|
||||||
// ];
|
let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
|
||||||
// let maker_amounts =
|
|
||||||
// vec![vec![U256::from_str("10607211").unwrap()],
|
let solution = Solution {
|
||||||
// vec![U256::from_str("7362350").unwrap()]];
|
exact_out: false,
|
||||||
//
|
given_token: token_in.clone(),
|
||||||
// // Commands and flags from the real transaction
|
given_amount: amount_in,
|
||||||
// let commands = AlloyBytes::from(hex!("00040004").to_vec());
|
checked_token: token_out,
|
||||||
// let flags = U256::from_str(
|
checked_amount: amount_out,
|
||||||
// "95769172144825922628485191511070792431742484643425438763224908097896054784000",
|
sender: user.clone(),
|
||||||
// )
|
receiver: user,
|
||||||
// .unwrap();
|
swaps: vec![swap],
|
||||||
//
|
..Default::default()
|
||||||
// // Encode Aggregate order - must match IBebopSettlement.Aggregate struct exactly
|
};
|
||||||
// let quote_data = (
|
|
||||||
// U256::from(expiry), // expiry as U256
|
let encoded_solution = encoder
|
||||||
// taker_address,
|
.encode_solutions(vec![solution.clone()])
|
||||||
// maker_addresses,
|
.unwrap()[0]
|
||||||
// maker_nonces, // Array of maker nonces
|
.clone();
|
||||||
// taker_tokens, // 2D array
|
|
||||||
// maker_tokens,
|
let calldata = encode_tycho_router_call(
|
||||||
// taker_amounts, // 2D array
|
eth_chain().id(),
|
||||||
// maker_amounts,
|
encoded_solution,
|
||||||
// receiver,
|
&solution,
|
||||||
// commands,
|
&UserTransferType::TransferFrom,
|
||||||
// flags,
|
ð(),
|
||||||
// )
|
None,
|
||||||
// .abi_encode();
|
)
|
||||||
//
|
.unwrap()
|
||||||
// // Use real signatures from the mainnet transaction
|
.data;
|
||||||
// let sig1 =
|
let hex_calldata = hex::encode(&calldata);
|
||||||
// hex::decode("
|
|
||||||
// d5abb425f9bac1f44d48705f41a8ab9cae207517be8553d2c03b06a88995f2f351ab8ce7627a87048178d539dd64fd2380245531a0c8e43fdc614652b1f32fc71c"
|
write_calldata_to_file("test_single_encoding_strategy_bebop_aggregate", hex_calldata.as_str());
|
||||||
// ).unwrap(); let sig2 =
|
}
|
||||||
// hex::decode("
|
|
||||||
// f38c698e48a3eac48f184bc324fef0b135ee13705ab38cc0bbf5a792f21002f051e445b9e7d57cf24c35e17629ea35b3263591c4abf8ca87ffa44b41301b89c41b"
|
|
||||||
// ).unwrap();
|
|
||||||
//
|
|
||||||
// // Build user_data with ETH_SIGN flag (0) for both signatures
|
|
||||||
// let signatures = vec![
|
|
||||||
// (sig1, 0u8), // ETH_SIGN for maker 1
|
|
||||||
// (sig2, 0u8), // ETH_SIGN for maker 2
|
|
||||||
// ];
|
|
||||||
//
|
|
||||||
// let user_data = build_bebop_calldata(
|
|
||||||
// BebopOrderType::Aggregate,
|
|
||||||
// U256::ZERO, // 0 means fill entire order
|
|
||||||
// "e_data,
|
|
||||||
// signatures,
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// let bebop_component = ProtocolComponent {
|
|
||||||
// id: String::from("bebop-rfq"),
|
|
||||||
// protocol_system: String::from("rfq:bebop"),
|
|
||||||
// static_attributes: HashMap::new(),
|
|
||||||
// ..Default::default()
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// let swap = Swap {
|
|
||||||
// component: bebop_component,
|
|
||||||
// token_in: token_in.clone(),
|
|
||||||
// token_out: token_out.clone(),
|
|
||||||
// split: 0f64,
|
|
||||||
// user_data: Some(user_data),
|
|
||||||
// protocol_state: None,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// // Use TransferFrom for WETH token transfer
|
|
||||||
// let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom);
|
|
||||||
//
|
|
||||||
// let solution = Solution {
|
|
||||||
// exact_out: false,
|
|
||||||
// given_token: token_in.clone(),
|
|
||||||
// given_amount: amount_in,
|
|
||||||
// checked_token: token_out,
|
|
||||||
// checked_amount: amount_out,
|
|
||||||
// // Use order taker as both sender and receiver to match the test setup
|
|
||||||
// sender: Bytes::from_str("0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6").unwrap(), /* Order
|
|
||||||
// taker */ receiver:
|
|
||||||
// Bytes::from_str("0x7078B12Ca5B294d95e9aC16D90B7D38238d8F4E6").unwrap(), /* Order receiver */
|
|
||||||
// swaps: vec![swap],
|
|
||||||
// ..Default::default()
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// let encoded_solution = encoder
|
|
||||||
// .encode_solutions(vec![solution.clone()])
|
|
||||||
// .unwrap()[0]
|
|
||||||
// .clone();
|
|
||||||
//
|
|
||||||
// let calldata = encode_tycho_router_call(
|
|
||||||
// eth_chain().id(),
|
|
||||||
// encoded_solution,
|
|
||||||
// &solution,
|
|
||||||
// &UserTransferType::TransferFrom,
|
|
||||||
// ð(),
|
|
||||||
// None,
|
|
||||||
// )
|
|
||||||
// .unwrap()
|
|
||||||
// .data;
|
|
||||||
// let hex_calldata = hex::encode(&calldata);
|
|
||||||
//
|
|
||||||
// write_calldata_to_file("test_single_encoding_strategy_bebop_aggregate",
|
|
||||||
// hex_calldata.as_str()); }
|
|
||||||
|
|||||||
Reference in New Issue
Block a user