From 0a0101cc4d64af8ea7becb3bab3bdbec6dc1374c Mon Sep 17 00:00:00 2001 From: royvardhan Date: Mon, 10 Mar 2025 21:52:14 +0530 Subject: [PATCH] test: add testCyclicSplitSwapIntegration --- foundry/test/TychoRouter.t.sol | 17 +++ .../evm/strategy_encoder/strategy_encoders.rs | 110 +++++++++++++++++- 2 files changed, 126 insertions(+), 1 deletion(-) diff --git a/foundry/test/TychoRouter.t.sol b/foundry/test/TychoRouter.t.sol index c760122..b53d088 100644 --- a/foundry/test/TychoRouter.t.sol +++ b/foundry/test/TychoRouter.t.sol @@ -1349,6 +1349,23 @@ contract TychoRouterTest is TychoRouterTestSetup { vm.stopPrank(); } + function testCyclicSplitSwapIntegration() public { + deal(USDC_ADDR, ALICE, 100000 * 10 ** 6); + + // Approve permit2 + vm.startPrank(ALICE); + IERC20(USDC_ADDR).approve(PERMIT2_ADDRESS, type(uint256).max); + // Encoded solution generated using `test_cyclic_split_swap` + // but manually replacing the executor address + // `dD8559c917393FC8DD2b4dD289c52Ff445fDE1B0` with the one in this test + // `2e234DAe75C793f67A35089C9d99245E1C58470b` + (bool success,) = tychoRouterAddr.call( + hex"d499aa880000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005ebe468000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000005f5e1000000000000000000000000000000000000000000000000000000000067f69de900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067cf17f1000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041f521cbb1d97ae14209faec0337cdb5b2e3691acd29ac2ef86ad2ac2c60350d9f5c39bb688be6305bd03288b69ba05d8bc066bd12e8585190f047c67f06b4ae4c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014d006d00019999992e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f43ede3eca2a72b3aecc820e955b36f38437d0139588e6a0c2ddd26feeb64f039a2c41296fcb3f564001006d01000000002e234dae75c793f67a35089c9d99245e1c58470bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d800006d00010000002e234dae75c793f67a35089c9d99245e1c58470ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb83ede3eca2a72b3aecc820e955b36f38437d013958ad599c3a0ff1de082011efddc58f1908eb6e6d80100000000000000000000000000000000000000" + ); + + vm.stopPrank(); + } + // Base Network Tests // Make sure to set the RPC_URL to base network function testSwapSingleBase() public { diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 336bd04..072a655 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -1303,5 +1303,113 @@ mod tests { } #[test] - + fn test_split_input_cyclic_swap() { + // This test has start and end tokens that are the same + // The flow is: + // ┌─── WETH (USV3 Pool 1) ───┐ + // │ │ + // USDC (60% split) ─┤ ├─> USDC + // │ │ + // └─── WETH (USV3 Pool 2) ───┘ + + // Set up a mock private key for signing (Alice's pk in our router tests) + let private_key = + "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string(); + + let weth = Bytes::from_str("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2").unwrap(); + let usdc = Bytes::from_str("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48").unwrap(); + + // USDC -> WETH (Pool 1) - 60% of input + let swap_usdc_weth_pool1 = Swap { + component: ProtocolComponent { + id: "0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640".to_string(), /* USDC-WETH USV3 + * Pool 1 */ + 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: usdc.clone(), + token_out: weth.clone(), + split: 0.6f64, // 60% of input + }; + + // USDC -> WETH (Pool 2) - 40% of input (remaining) + let swap_usdc_weth_pool2 = Swap { + component: ProtocolComponent { + id: "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8".to_string(), /* USDC-WETH USV3 + * Pool 2 */ + protocol_system: "uniswap_v3".to_string(), + static_attributes: { + let mut attrs = HashMap::new(); + attrs.insert( + "fee".to_string(), + Bytes::from(BigInt::from(3000).to_signed_bytes_be()), + ); + attrs + }, + ..Default::default() + }, + token_in: usdc.clone(), + token_out: weth.clone(), + split: 0f64, // Remaining 40% + }; + + // WETH -> USDC (Pool 2) + let swap_weth_usdc_pool2 = Swap { + component: ProtocolComponent { + id: "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8".to_string(), /* USDC-WETH USV3 + * Pool 2 */ + protocol_system: "uniswap_v3".to_string(), + static_attributes: { + let mut attrs = HashMap::new(); + attrs.insert( + "fee".to_string(), + Bytes::from(BigInt::from(3000).to_signed_bytes_be()), + ); + attrs + }, + ..Default::default() + }, + token_in: weth.clone(), + token_out: usdc.clone(), + split: 0.0f64, + }; + + let swap_encoder_registry = get_swap_encoder_registry(); + let encoder = SplitSwapStrategyEncoder::new( + eth_chain(), + swap_encoder_registry, + Some(private_key.clone()), + ) + .unwrap(); + + let solution = Solution { + exact_out: false, + given_token: usdc.clone(), + given_amount: BigUint::from_str("100000000").unwrap(), // 100 USDC (6 decimals) + checked_token: usdc.clone(), + expected_amount: None, + checked_amount: Some(BigUint::from_str("99345512").unwrap()), /* Expected output from + * test */ + router_address: Bytes::from_str("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395").unwrap(), + sender: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), + receiver: Bytes::from_str("0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2").unwrap(), + slippage: None, + swaps: vec![swap_usdc_weth_pool1, swap_weth_usdc_pool2, swap_usdc_weth_pool2], + ..Default::default() + }; + + let (calldata, _) = encoder + .encode_strategy(solution) + .unwrap(); + + println!("{}", hex::encode(&calldata)); + } }