diff --git a/crates/driver/src/boundary/liquidity/uniswap/v3.rs b/crates/driver/src/boundary/liquidity/uniswap/v3.rs index 60a2b2fc5f..859b76105d 100644 --- a/crates/driver/src/boundary/liquidity/uniswap/v3.rs +++ b/crates/driver/src/boundary/liquidity/uniswap/v3.rs @@ -13,7 +13,6 @@ use { anyhow::Context, contracts::{GPv2Settlement, UniswapV3SwapRouter}, ethrpc::current_block::BlockRetrieving, - itertools::Itertools, shared::{ http_solver::model::TokenAmount, interaction::Interaction, @@ -92,16 +91,12 @@ pub fn to_interaction( TokenAmount::new(output.0.token.into(), output.0.amount), ); - interaction - .encode() - .into_iter() - .map(|(target, value, call_data)| eth::Interaction { - target: eth::Address(target), - value: eth::Ether(value), - call_data: call_data.0.into(), - }) - .exactly_one() - .unwrap() + let encoded = interaction.encode(); + eth::Interaction { + target: eth::Address(encoded.0), + value: eth::Ether(encoded.1), + call_data: crate::util::Bytes(encoded.2 .0), + } } pub fn collector( diff --git a/crates/shared/src/http_solver/model.rs b/crates/shared/src/http_solver/model.rs index de59281fd6..843eae0c43 100644 --- a/crates/shared/src/http_solver/model.rs +++ b/crates/shared/src/http_solver/model.rs @@ -188,8 +188,8 @@ pub struct InteractionData { } impl Interaction for InteractionData { - fn encode(&self) -> Vec { - vec![(self.target, self.value, Bytes(self.call_data.clone()))] + fn encode(&self) -> EncodedInteraction { + (self.target, self.value, Bytes(self.call_data.clone())) } } diff --git a/crates/shared/src/interaction.rs b/crates/shared/src/interaction.rs index ef5735fc40..e6431f6c31 100644 --- a/crates/shared/src/interaction.rs +++ b/crates/shared/src/interaction.rs @@ -10,11 +10,11 @@ pub trait Interaction: std::fmt::Debug + Send + Sync { // Write::write returns a result but we know we write to a vector in memory so // we know it will never fail. Then the question becomes whether // interactions should be allowed to fail encoding for other reasons. - fn encode(&self) -> Vec; + fn encode(&self) -> EncodedInteraction; } impl Interaction for Box { - fn encode(&self) -> Vec { + fn encode(&self) -> EncodedInteraction { self.as_ref().encode() } } @@ -26,14 +26,14 @@ pub type EncodedInteraction = ( ); impl Interaction for EncodedInteraction { - fn encode(&self) -> Vec { - vec![self.clone()] + fn encode(&self) -> EncodedInteraction { + self.clone() } } impl Interaction for InteractionData { - fn encode(&self) -> Vec { - vec![(self.target, self.value, Bytes(self.call_data.clone()))] + fn encode(&self) -> EncodedInteraction { + (self.target, self.value, Bytes(self.call_data.clone())) } } diff --git a/crates/shared/src/oneinch_api.rs b/crates/shared/src/oneinch_api.rs index ae40a7d2f8..782f5d480b 100644 --- a/crates/shared/src/oneinch_api.rs +++ b/crates/shared/src/oneinch_api.rs @@ -402,8 +402,8 @@ pub struct Swap { } impl Interaction for Swap { - fn encode(&self) -> Vec { - vec![(self.tx.to, self.tx.value, Bytes(self.tx.data.clone()))] + fn encode(&self) -> EncodedInteraction { + (self.tx.to, self.tx.value, Bytes(self.tx.data.clone())) } } diff --git a/crates/shared/src/paraswap_api.rs b/crates/shared/src/paraswap_api.rs index b45e3d33c7..21181c61f4 100644 --- a/crates/shared/src/paraswap_api.rs +++ b/crates/shared/src/paraswap_api.rs @@ -385,8 +385,8 @@ pub struct TransactionBuilderResponse { } impl Interaction for TransactionBuilderResponse { - fn encode(&self) -> Vec { - vec![(self.to, self.value, Bytes(self.data.clone()))] + fn encode(&self) -> EncodedInteraction { + (self.to, self.value, Bytes(self.data.clone())) } } diff --git a/crates/shared/src/zeroex_api.rs b/crates/shared/src/zeroex_api.rs index f8fa5225cd..90e0d75ea4 100644 --- a/crates/shared/src/zeroex_api.rs +++ b/crates/shared/src/zeroex_api.rs @@ -327,8 +327,8 @@ pub struct SwapResponse { } impl Interaction for SwapResponse { - fn encode(&self) -> Vec { - vec![(self.to, self.value, Bytes(self.data.clone()))] + fn encode(&self) -> EncodedInteraction { + (self.to, self.value, Bytes(self.data.clone())) } } diff --git a/crates/solver/src/interactions/allowances.rs b/crates/solver/src/interactions/allowances.rs index d16089a16a..c8e73a7d51 100644 --- a/crates/solver/src/interactions/allowances.rs +++ b/crates/solver/src/interactions/allowances.rs @@ -115,7 +115,7 @@ pub struct Approval { } impl Interaction for Approval { - fn encode(&self) -> Vec { + fn encode(&self) -> EncodedInteraction { // Use a "dummy" contract - unfortunately `ethcontract` doesn't // allow you use the generated contract intances to encode // transaction data without a `Web3` instance. Hopefully, this @@ -365,7 +365,7 @@ mod tests { let spender = H160([0x02; 20]); assert_eq!( Approval { token, spender }.encode(), - vec![( + ( token, 0.into(), Bytes( @@ -376,7 +376,7 @@ mod tests { ) .unwrap() ) - )] + ) ); } diff --git a/crates/solver/src/interactions/balancer_v2.rs b/crates/solver/src/interactions/balancer_v2.rs index c97a746d86..abf6f2b4c1 100644 --- a/crates/solver/src/interactions/balancer_v2.rs +++ b/crates/solver/src/interactions/balancer_v2.rs @@ -51,8 +51,8 @@ impl BalancerSwapGivenOutInteraction { } impl Interaction for BalancerSwapGivenOutInteraction { - fn encode(&self) -> Vec { - vec![self.encode_swap()] + fn encode(&self) -> EncodedInteraction { + self.encode_swap() } } @@ -95,7 +95,7 @@ mod tests { // ``` assert_eq!( interaction.encode(), - vec![( + ( vault.address(), 0.into(), Bytes( @@ -118,7 +118,7 @@ mod tests { ) .unwrap() ), - )] + ) ); } } diff --git a/crates/solver/src/interactions/erc20.rs b/crates/solver/src/interactions/erc20.rs index 26285f6b21..96dbd249e5 100644 --- a/crates/solver/src/interactions/erc20.rs +++ b/crates/solver/src/interactions/erc20.rs @@ -23,8 +23,8 @@ impl Erc20ApproveInteraction { } impl Interaction for Erc20ApproveInteraction { - fn encode(&self) -> Vec { - vec![self.as_encoded()] + fn encode(&self) -> EncodedInteraction { + self.as_encoded() } } diff --git a/crates/solver/src/interactions/uniswap_v2.rs b/crates/solver/src/interactions/uniswap_v2.rs index f11f6760fa..8e08507107 100644 --- a/crates/solver/src/interactions/uniswap_v2.rs +++ b/crates/solver/src/interactions/uniswap_v2.rs @@ -16,8 +16,8 @@ pub struct UniswapInteraction { } impl Interaction for UniswapInteraction { - fn encode(&self) -> Vec { - vec![self.encode_swap()] + fn encode(&self) -> EncodedInteraction { + self.encode_swap() } } @@ -68,13 +68,9 @@ mod tests { token_in, token_out: H160::from_low_u64_be(token_out as u64), }; - let interactions = interaction.encode(); - - // Single interaction - assert_eq!(interactions.len(), 1); + let swap_call = interaction.encode(); // Verify Swap - let swap_call = &interactions[0]; assert_eq!(swap_call.0, router.address()); let call = &swap_call.2 .0; let swap_signature = hex!("8803dbee"); diff --git a/crates/solver/src/interactions/uniswap_v3.rs b/crates/solver/src/interactions/uniswap_v3.rs index 5313fe6ece..02d97a0690 100644 --- a/crates/solver/src/interactions/uniswap_v3.rs +++ b/crates/solver/src/interactions/uniswap_v3.rs @@ -24,7 +24,7 @@ pub struct ExactOutputSingleParams { pub sqrt_price_limit_x96: U256, } impl Interaction for UniswapV3Interaction { - fn encode(&self) -> Vec { + fn encode(&self) -> EncodedInteraction { let method = self.router.exact_output_single(( self.params.token_amount_in_max.token, self.params.token_amount_out.token, @@ -36,7 +36,7 @@ impl Interaction for UniswapV3Interaction { self.params.sqrt_price_limit_x96, )); let calldata = method.tx.data.expect("no calldata").0; - vec![(self.router.address(), 0.into(), Bytes(calldata))] + (self.router.address(), 0.into(), Bytes(calldata)) } } @@ -81,13 +81,9 @@ mod tests { sqrt_price_limit_x96: U256::zero(), }, }; - let interactions = interaction.encode(); - - // Single interaction - assert_eq!(interactions.len(), 1); + let swap_call = interaction.encode(); // Verify Swap - let swap_call = &interactions[0]; assert_eq!(swap_call.0, router.address()); let call = &swap_call.2 .0; let swap_signature = hex!("db3e2198"); diff --git a/crates/solver/src/interactions/weth.rs b/crates/solver/src/interactions/weth.rs index 40ed5e1518..921275f7aa 100644 --- a/crates/solver/src/interactions/weth.rs +++ b/crates/solver/src/interactions/weth.rs @@ -32,10 +32,10 @@ impl UnwrapWethInteraction { } impl Interaction for UnwrapWethInteraction { - fn encode(&self) -> Vec { + fn encode(&self) -> EncodedInteraction { let method = self.weth.withdraw(self.amount); let calldata = method.tx.data.expect("no calldata").0; - vec![(self.weth.address(), 0.into(), Bytes(calldata))] + (self.weth.address(), 0.into(), Bytes(calldata)) } } @@ -51,9 +51,8 @@ mod tests { weth: weth.clone(), amount, }; - let encoded_interactions = interaction.encode(); + let withdraw_call = interaction.encode(); - let withdraw_call = &encoded_interactions[0]; assert_eq!(withdraw_call.0, weth.address()); assert_eq!(withdraw_call.1, U256::from(0)); let call = &withdraw_call.2 .0; diff --git a/crates/solver/src/interactions/zeroex.rs b/crates/solver/src/interactions/zeroex.rs index 1c77e90652..b2345e2fdd 100644 --- a/crates/solver/src/interactions/zeroex.rs +++ b/crates/solver/src/interactions/zeroex.rs @@ -15,7 +15,7 @@ pub struct ZeroExInteraction { } impl Interaction for ZeroExInteraction { - fn encode(&self) -> Vec { + fn encode(&self) -> EncodedInteraction { let method = self.zeroex.fill_or_kill_limit_order( ( self.order.maker_token, @@ -40,6 +40,6 @@ impl Interaction for ZeroExInteraction { self.taker_token_fill_amount, ); let calldata = method.tx.data.expect("no calldata").0; - vec![(self.zeroex.address(), 0.into(), Bytes(calldata))] + (self.zeroex.address(), 0.into(), Bytes(calldata)) } } diff --git a/crates/solver/src/liquidity/balancer_v2.rs b/crates/solver/src/liquidity/balancer_v2.rs index cf7df80f65..c56cefb504 100644 --- a/crates/solver/src/liquidity/balancer_v2.rs +++ b/crates/solver/src/liquidity/balancer_v2.rs @@ -515,8 +515,7 @@ mod tests { user_data: Default::default(), } .encode(), - ] - .concat(), + ], ); } } diff --git a/crates/solver/src/liquidity/zeroex.rs b/crates/solver/src/liquidity/zeroex.rs index c50fdfa10c..7458808591 100644 --- a/crates/solver/src/liquidity/zeroex.rs +++ b/crates/solver/src/liquidity/zeroex.rs @@ -387,8 +387,7 @@ pub mod tests { zeroex } .encode(), - ] - .concat(), + ], ); } @@ -420,8 +419,7 @@ pub mod tests { taker_token_fill_amount: 100, zeroex } - .encode(),] - .concat(), + .encode()], ); } } diff --git a/crates/solver/src/settlement.rs b/crates/solver/src/settlement.rs index 3df284f283..2cab9f37d9 100644 --- a/crates/solver/src/settlement.rs +++ b/crates/solver/src/settlement.rs @@ -213,19 +213,7 @@ impl Trade { } } -#[cfg(test)] -use shared::interaction::{EncodedInteraction, Interaction}; use shared::{external_prices::ExternalPrices, http_solver::model::Score}; -#[cfg(test)] -#[derive(Debug)] -pub struct NoopInteraction; - -#[cfg(test)] -impl Interaction for NoopInteraction { - fn encode(&self) -> Vec { - Vec::new() - } -} #[derive(Debug, Clone, Default)] pub struct Settlement { diff --git a/crates/solver/src/settlement/settlement_encoder.rs b/crates/solver/src/settlement/settlement_encoder.rs index bb3f522b07..1ea38faaf1 100644 --- a/crates/solver/src/settlement/settlement_encoder.rs +++ b/crates/solver/src/settlement/settlement_encoder.rs @@ -583,7 +583,7 @@ impl SettlementEncoder { interactions: [ self.pre_interactions .into_iter() - .flat_map(|interaction| interaction.encode()) + .map(|interaction| interaction.encode()) .collect(), iter::empty() .chain( @@ -601,13 +601,13 @@ impl SettlementEncoder { Some(interaction) } }) - .flat_map(|interaction| interaction.encode()), + .map(|interaction| interaction.encode()), ) - .chain(self.unwraps.iter().flat_map(|unwrap| unwrap.encode())) + .chain(self.unwraps.iter().map(|unwrap| unwrap.encode())) .collect(), self.post_interactions .into_iter() - .flat_map(|interaction| interaction.encode()) + .map(|interaction| interaction.encode()) .collect(), ], } @@ -738,7 +738,6 @@ pub fn verify_executed_amount(order: &Order, executed: U256) -> Result<()> { pub mod tests { use { super::*, - crate::settlement::NoopInteraction, contracts::{dummy_contract, WETH9}, ethcontract::Bytes, maplit::hashmap, @@ -798,11 +797,11 @@ pub mod tests { encoder .finish(InternalizationStrategy::SkipInternalizableInteraction) .interactions[1], - UnwrapWethInteraction { + [UnwrapWethInteraction { weth, amount: 3.into(), } - .encode(), + .encode()], ); } @@ -927,7 +926,7 @@ pub mod tests { encoder .finish(InternalizationStrategy::SkipInternalizableInteraction) .interactions[1], - [interaction.encode(), unwrap.encode()].concat(), + [interaction.encode(), unwrap.encode()], ); } @@ -1031,7 +1030,7 @@ pub mod tests { encoder0 .add_trade(order12.clone(), 11.into(), 0.into()) .unwrap(); - encoder0.append_to_execution_plan(Arc::new(NoopInteraction {})); + encoder0.append_to_execution_plan(Arc::new(TestInteraction)); encoder0.add_unwrap(UnwrapWethInteraction { weth: weth.clone(), amount: 1.into(), @@ -1060,7 +1059,7 @@ pub mod tests { encoder1 .add_trade(order23.clone(), 11.into(), 0.into()) .unwrap(); - encoder1.append_to_execution_plan(Arc::new(NoopInteraction {})); + encoder1.append_to_execution_plan(Arc::new(TestInteraction)); encoder1.add_unwrap(UnwrapWethInteraction { weth, amount: 2.into(), @@ -1424,8 +1423,8 @@ pub mod tests { #[derive(Debug)] pub struct TestInteraction; impl Interaction for TestInteraction { - fn encode(&self) -> Vec { - vec![(H160::zero(), U256::zero(), Bytes::default())] + fn encode(&self) -> EncodedInteraction { + (H160::zero(), U256::zero(), Bytes::default()) } } diff --git a/crates/solver/src/settlement_submission/submitter/public_mempool_api.rs b/crates/solver/src/settlement_submission/submitter/public_mempool_api.rs index 6e4a67a732..817498e379 100644 --- a/crates/solver/src/settlement_submission/submitter/public_mempool_api.rs +++ b/crates/solver/src/settlement_submission/submitter/public_mempool_api.rs @@ -211,7 +211,21 @@ pub async fn validate_submission_node(node: &Web3, expected_network_id: &String) } #[cfg(test)] mod tests { - use {super::*, crate::settlement::NoopInteraction, std::sync::Arc}; + use { + super::*, + ethcontract::Bytes, + primitive_types::{H160, U256}, + shared::interaction::{EncodedInteraction, Interaction}, + std::sync::Arc, + }; + + #[derive(Debug)] + pub struct TestInteraction; + impl Interaction for TestInteraction { + fn encode(&self) -> EncodedInteraction { + (H160::zero(), U256::zero(), Bytes::default()) + } + } #[test] fn submission_status_configuration() { @@ -219,7 +233,7 @@ mod tests { let mut settlement = Settlement::new(Default::default()); settlement .encoder - .append_to_execution_plan(Arc::new(NoopInteraction)); + .append_to_execution_plan(Arc::new(TestInteraction)); assert_eq!(settlement.revertable(), Revertable::HighRisk); settlement };