From 68d4d083c3060146d06497f44e4b48ffd9e6604e Mon Sep 17 00:00:00 2001 From: pedrobergamini <41773103+pedrobergamini@users.noreply.github.com> Date: Sat, 7 Jun 2025 18:36:01 -0300 Subject: [PATCH] test: add uniswap v3 => bebop sequential swap --- foundry/test/TychoRouterSequentialSwap.t.sol | 35 ++--- foundry/test/assets/calldata.txt | 5 +- src/encoding/evm/constants.rs | 1 + .../evm/swap_encoder/swap_encoders.rs | 12 +- src/encoding/evm/tycho_encoders.rs | 130 +++++++++++++++++- 5 files changed, 156 insertions(+), 27 deletions(-) diff --git a/foundry/test/TychoRouterSequentialSwap.t.sol b/foundry/test/TychoRouterSequentialSwap.t.sol index f43a666..4e8b87e 100644 --- a/foundry/test/TychoRouterSequentialSwap.t.sol +++ b/foundry/test/TychoRouterSequentialSwap.t.sol @@ -495,25 +495,26 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); } - // function testBebopUSV2Integration() public { - // // Performs a sequential swap from USDC to WETH though Bebop and USV2 pools - // // - // // USDC ──(bebop)──> WETH ───(USV2)──> USDC - // deal(USDC_ADDR, ALICE, 1000 * 10 ** 6); - // uint256 balanceBefore = IERC20(USDC_ADDR).balanceOf(ALICE); + function testUSV3BebopIntegration() public { + // Performs a sequential swap from WETH to DAI through USDC using USV3 and Bebop RFQ + // + // WETH ──(USV3)──> USDC ───(Bebop RFQ)──> DAI + deal(WETH_ADDR, ALICE, 1 ether); + uint256 balanceBefore = IERC20(DAI_ADDR).balanceOf(ALICE); - // // Approve permit2 - // vm.startPrank(ALICE); - // IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); - // bytes memory callData = loadCallDataFromFile("test_encode_bebop_single"); - // (bool success,) = tychoRouterAddr.call(callData); + // Approve router + vm.startPrank(ALICE); + IERC20(WETH_ADDR).approve(tychoRouterAddr, type(uint256).max); + bytes memory callData = loadCallDataFromFile("test_uniswapv3_bebop"); + (bool success,) = tychoRouterAddr.call(callData); - // vm.stopPrank(); + vm.stopPrank(); - // uint256 balanceAfter = IERC20(USDC_ADDR).balanceOf(ALICE); + uint256 balanceAfter = IERC20(DAI_ADDR).balanceOf(ALICE); - // assertTrue(success, "Call Failed"); - // assertGt(balanceAfter, balanceBefore, "Should receive some tokens"); - // assertEq(IERC20(USDC_ADDR).balanceOf(tychoRouterAddr), 0); - // } + assertTrue(success, "Call Failed"); + // Expecting ~2021.75 DAI from 1 WETH through USDC + assertEq(balanceAfter - balanceBefore, 2021750881000000000000); + assertEq(IERC20(WETH_ADDR).balanceOf(tychoRouterAddr), 0); + } } diff --git a/foundry/test/assets/calldata.txt b/foundry/test/assets/calldata.txt index eabb44d..db9efe5 100644 --- a/foundry/test/assets/calldata.txt +++ b/foundry/test/assets/calldata.txt @@ -21,7 +21,7 @@ test_split_output_cyclic_swap:7c553846000000000000000000000000000000000000000000 test_split_input_cyclic_swap:7c5538460000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ef619b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e10000000000000000000000000000000000000000000000000000000000686c362900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006844b03100000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000004130f5e8d8d53706946f9057435ee51079418bb8d44de7bea9bf4a23d771f01855558dd6b5033df2613f2de15e5ce4465c794b30d3047d7261924231283661689b1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000139006e00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f56400100006e00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80100005701000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2b4e16d0168e52d35cacd2c6185b44281ec28c9dccd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000100000000000000 test_split_swap_strategy_encoder:7c5538460000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000018f61ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000686c362900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006844b031000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041d5255095cb813c96212c0046719e644c4b345b2151ac01be7dfe7ec17ed3858f43e6d1dd28c89a7ab91beae23c0d737a991a8a8112cde17f48e6a94213cf81931c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164005700028000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d013950000005700010000005615deb798bb3e4dfa0139dfa1b3d433cc23b72fc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2bb2b8038a1640196fbe3e38816f3e67cba72d9403ede3eca2a72b3aecc820e955b36f38437d013950000005702030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fae461ca67b15dc8dc81ce7615e0320da1a9ab8d5cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20101005701030000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f2260fac5e5542a773aa44fbcfedf7c193bc2c599004375dff511095cc5a197a54140a24efef3a416cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2010100000000000000000000000000000000000000000000000000000000 test_uniswap_v3_curve:e21dd0d30000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000018f61ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000d600692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599000bb83ede3eca2a72b3aecc820e955b36f38437d01395cbcdf9626bc03e24f779434178a73a0b4bad62ed000000691d1499e622d69689cdf9004d05ec547d650ff2112260fac5e5542a773aa44fbcfedf7c193bc2c599dac17f958d2ee523a2206206994597c13d831ec7d51a44d3fae010294c616388b506acda1bfaae460301000102cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000 -test_multi_protocol:51bcc7b600000000000000000000000000000000000000000000005150ae84a8cdf000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2958f36da71a9200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000005150ae84a8cdf0000000000000000000000000000000000000000000000000000000000000686c362a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006844b03200000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000041d2da31d902b0972f172a6fea8d51746dfd55a6e1f768674d2d0ee4e56d1ec7f4557e916494a3df6e661faab6927f1ef430722426012865298efe285a5911c8c31b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021400525615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139501000072c7183455a4c133ae270771860664b6b7ec320bb1c02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599a6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e3ede3eca2a72b3aecc820e955b36f38437d01395010200691d1499e622d69689cdf9004d05ec547d650ff2112260fac5e5542a773aa44fbcfedf7c193bc2c599dac17f958d2ee523a2206206994597c13d831ec7d51a44d3fae010294c616388b506acda1bfaae4603010001023ede3eca2a72b3aecc820e955b36f38437d013950071a0cb889707d426a7a386870a03bc70d1b0697598013ede3eca2a72b3aecc820e955b36f38437d01395dac17f958d2ee523a2206206994597c13d831ec7a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000001a36e2eb1c43200000032006cf62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000001cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c000000000000000000000000 +test_multi_protocol:51bcc7b600000000000000000000000000000000000000000000005150ae84a8cdf000000000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2958f36da71a9200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000005150ae84a8cdf0000000000000000000000000000000000000000000000000000000000000686c3aa200000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d01395000000000000000000000000000000000000000000000000000000006844b4aa00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000415d43808fbf3af0d8bb23a38fe5ea0d85b1446b6a70ab55de4c276f726a1ddab06d01a2a3a0ad46ff9297acfc52ac811a3a19d3d3abea08eb9c66fa834b3560f91c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021400525615deb798bb3e4dfa0139dfa1b3d433cc23b72f6b175474e89094c44da98b954eedeac495271d0fa478c2975ab1ea89e8196811f51a7b7ade33eb113ede3eca2a72b3aecc820e955b36f38437d0139501000072c7183455a4c133ae270771860664b6b7ec320bb1c02aaa39b223fe8d0a0e5c4f27ead9083c756cc22260fac5e5542a773aa44fbcfedf7c193bc2c599a6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e3ede3eca2a72b3aecc820e955b36f38437d01395010200691d1499e622d69689cdf9004d05ec547d650ff2112260fac5e5542a773aa44fbcfedf7c193bc2c599dac17f958d2ee523a2206206994597c13d831ec7d51a44d3fae010294c616388b506acda1bfaae4603010001023ede3eca2a72b3aecc820e955b36f38437d013950071a0cb889707d426a7a386870a03bc70d1b0697598013ede3eca2a72b3aecc820e955b36f38437d01395dac17f958d2ee523a2206206994597c13d831ec7a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000001a36e2eb1c43200000032006cf62849f9a0b5bf2913b396098f7c7019b51a820aa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000001cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000bb800003c000000000000000000000000 test_encode_balancer_v2:c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2ba100000625a3754423978a60c9317c58a424e3d5c6ee304399dbdb9c8ef030ab642b10820db8f560002000000000000000000141d96f2f6bef1202e4ce1ff6dad0c2cb002861d3e0102 test_ekubo_encode_swap_multi:01ca4f73fe97d0b987a0d12b39bbd562c779bab6f60000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4851d02a5948496a67827242eabc5725531342527c000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000001a36e2eb1c43200000032 test_encode_uniswap_v4_sequential_swap:4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990101cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c @@ -36,4 +36,5 @@ test_single_swap_strategy_encoder:30ace1b100000000000000000000000000000000000000 test_encode_bebop_aggregate:6b175474e89094c44da98b954eedeac495271d0f2260fac5e5542a773aa44fbcfedf7c193bc2c599000200000004deadbeef00000000140000000200000004aabbccdd00000004eeff001101 test_encode_bebop_single:a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20100000000081234567890abcdef0000000004aabbccdd01 test_encode_bebop_multi:c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48010100000008abcdef123456789000000000041122334401 -test_single_encoding_strategy_bebop:5c4b639c000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000058d15e17628000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001acd6bbde9174b1cdaa358d2cf4d57d1a9f7178fbffa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000160000000000000000000000000000000000000000000000000000000006844b7380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bbbbbbb520d69a9775e85b458c58c648259fad5f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000058d15e176280000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004aabbccdd010000000000000000000000000000000000000000 +test_single_encoding_strategy_bebop:5c4b639c000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000058d15e17628000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc20000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001acd6bbde9174b1cdaa358d2cf4d57d1a9f7178fbffa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000160000000000000000000000000000000000000000000000000000000006844be050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bbbbbbb520d69a9775e85b458c58c648259fad5f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000058d15e176280000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004aabbccdd010000000000000000000000000000000000000000 +test_uniswapv3_bebop:e21dd0d30000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000006d996e0293020b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000021900692e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f5640000001acd6bbde9174b1cdaa358d2cf4d57d1a9f7178fbffa0b86991c6218b36c1d19d4a2e9eb0ce3606eb486b175474e89094c44da98b954eedeac495271d0f010000000160000000000000000000000000000000000000000000000000000000006844bbb10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bbbbbbb520d69a9775e85b458c58c648259fad5f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000000000000000000000000000000000007881786100000000000000000000000000000000000000000000006d996e0293020b1000000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004aabbccdd0100000000000000 diff --git a/src/encoding/evm/constants.rs b/src/encoding/evm/constants.rs index 1c9b8bf..c77b088 100644 --- a/src/encoding/evm/constants.rs +++ b/src/encoding/evm/constants.rs @@ -47,5 +47,6 @@ pub static CALLBACK_CONSTRAINED_PROTOCOLS: LazyLock> = Laz set.insert("pancakeswap_v3"); set.insert("uniswap_v4"); set.insert("ekubo_v2"); + set.insert("rfq:bebop"); set }); diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index 269cf07..1c12ef0 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -585,11 +585,11 @@ pub struct BebopSwapEncoder { impl BebopSwapEncoder { /// Validates the component ID format - /// Component format: "bebop" + /// Component format: "bebop-rfq" fn validate_component_id(component_id: &str) -> Result<(), EncodingError> { - if component_id != "bebop" { + if component_id != "bebop-rfq" { return Err(EncodingError::FatalError( - "Invalid Bebop component ID format. Expected 'bebop'".to_string(), + "Invalid Bebop component ID format. Expected 'bebop-rfq'".to_string(), )); } Ok(()) @@ -1678,7 +1678,7 @@ mod tests { .insert("signature".into(), Bytes::from(hex::decode("aabbccdd").unwrap())); let bebop_component = ProtocolComponent { - id: String::from("bebop"), + id: String::from("bebop-rfq"), protocol_system: String::from("rfq:bebop"), static_attributes, ..Default::default() @@ -1759,7 +1759,7 @@ mod tests { static_attributes.insert("order_type".into(), Bytes::from(vec![1u8])); // Multi order let bebop_component = ProtocolComponent { - id: String::from("bebop"), + id: String::from("bebop-rfq"), protocol_system: String::from("rfq:bebop"), static_attributes, ..Default::default() @@ -1843,7 +1843,7 @@ mod tests { static_attributes.insert("order_type".into(), Bytes::from(vec![2u8])); // Aggregate order let bebop_component = ProtocolComponent { - id: String::from("bebop"), + id: String::from("bebop-rfq"), protocol_system: String::from("rfq:bebop"), static_attributes, ..Default::default() diff --git a/src/encoding/evm/tycho_encoders.rs b/src/encoding/evm/tycho_encoders.rs index 631ac0d..81fa10a 100644 --- a/src/encoding/evm/tycho_encoders.rs +++ b/src/encoding/evm/tycho_encoders.rs @@ -1917,6 +1917,7 @@ mod tests { // In this module we test the ability to chain swaps or not. Different protocols are // tested. The encoded data is used for solidity tests as well use super::*; + use std::time::{SystemTime, UNIX_EPOCH}; #[test] fn test_uniswap_v3_uniswap_v2() { @@ -2260,6 +2261,131 @@ mod tests { write_calldata_to_file("test_balancer_v2_uniswap_v2", hex_calldata.as_str()); } + #[test] + fn test_uniswap_v3_bebop() { + // Note: This test does not assert anything. It is only used to obtain + // integration test data for our router solidity test. + // + // Performs a sequential swap from WETH to DAI through USDC using USV3 and Bebop RFQ + // + // WETH ───(USV3)──> USDC ───(Bebop RFQ)──> DAI + + let weth = weth(); + let usdc = Bytes::from_str("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48").unwrap(); + let dai = Bytes::from_str("0x6b175474e89094c44da98b954eedeac495271d0f").unwrap(); + + // First swap: WETH -> USDC via UniswapV3 + let swap_weth_usdc = Swap { + component: ProtocolComponent { + id: "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640".to_string(), // WETH-USDC USV3 Pool 0.05% + protocol_system: "uniswap_v3".to_string(), + static_attributes: { + let mut attrs = HashMap::new(); + attrs.insert( + "fee".to_string(), + Bytes::from(BigInt::from(500).to_signed_bytes_be()), + ); + attrs + }, + ..Default::default() + }, + token_in: weth.clone(), + token_out: usdc.clone(), + split: 0f64, + }; + + // Second swap: USDC -> DAI via Bebop RFQ + // Create a valid Bebop Single order struct + let expiry = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + 3600; // Current time + 1 hour + let taker_address = Address::ZERO; + let maker_address = + Address::from_str("0xbbbbbBB520d69a9775E85b458C58c648259FAD5F").unwrap(); + let maker_nonce = 1u64; + let taker_token = Address::from_str(&usdc.to_string()).unwrap(); + let maker_token = Address::from_str(&dai.to_string()).unwrap(); + // For ~2021.75 USDC input (what 1 ETH gives us via USV3), expecting ~2021.75 DAI output + let taker_amount = U256::from_str("2021750881").unwrap(); // 2021.75 USDC (6 decimals) + let maker_amount = U256::from_str("2021750881000000000000").unwrap(); // 2021.75 DAI (18 decimals) + let receiver = + Address::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(); // Alice's address + let packed_commands = U256::ZERO; + + // Encode using standard ABI encoding (not packed) + let quote_data = ( + expiry, + taker_address, + maker_address, + maker_nonce, + taker_token, + maker_token, + taker_amount, + maker_amount, + receiver, + packed_commands, + U256::from(0u64), // flags as uint256 + ) + .abi_encode(); + + let quote_data = Bytes::from(quote_data); + let signature = Bytes::from(hex::decode("aabbccdd").unwrap()); + + // Create static attributes for the Bebop component + let mut static_attributes: HashMap = HashMap::new(); + static_attributes.insert("quote_data".into(), quote_data); + static_attributes.insert("signature".into(), signature); + + let bebop_component = ProtocolComponent { + id: String::from("bebop-rfq"), + protocol_system: String::from("rfq:bebop"), + static_attributes, + ..Default::default() + }; + + let swap_usdc_dai = Swap { + component: bebop_component, + token_in: usdc.clone(), + token_out: dai.clone(), + split: 0f64, + }; + + let encoder = get_tycho_router_encoder(UserTransferType::TransferFrom); + + let solution = Solution { + exact_out: false, + given_token: weth, + given_amount: BigUint::from_str("1_000000000000000000").unwrap(), // 1 WETH + checked_token: dai, + checked_amount: BigUint::from_str("2021750881000000000000").unwrap(), // Expected ~2021.75 DAI + sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), + receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2") + .unwrap(), + swaps: vec![swap_weth_usdc, swap_usdc_dai], + ..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, + eth(), + None, + ) + .unwrap() + .data; + + let hex_calldata = encode(&calldata); + write_calldata_to_file("test_uniswapv3_bebop", hex_calldata.as_str()); + } + #[test] fn test_multi_protocol() { // Note: This test does not assert anything. It is only used to obtain @@ -3397,7 +3523,7 @@ mod tests { #[test] fn test_single_encoding_strategy_bebop() { - // USDC -> (bebop) -> WETH + // USDC -> (Bebop RFQ) -> WETH let token_in = Bytes::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); // USDC let token_out = Bytes::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); // WETH let amount_in = BigUint::from_str("1000_000000").unwrap(); // 1000 USDC @@ -3447,7 +3573,7 @@ mod tests { static_attributes.insert("signature".into(), signature); let bebop_component = ProtocolComponent { - id: String::from("bebop"), + id: String::from("bebop-rfq"), protocol_system: String::from("rfq:bebop"), static_attributes, ..Default::default()