Files
tycho-execution/src/encoding/evm/router_encoder.rs
Diana Carvalho feb91cc639 feat: Implement SplitSwapStrategyEncoder
The strategy works as follows:
- Manage approvals needed
- Compute min amount (if check amount is any):
  - if slippage is defined, apply slippage on the expected amount and take the min value between that and the check amount
  - if not, it's just the check amount
- Iterate through the swaps
  - call the corresponding swap encoder to encode the swap
  - add swap header (tokens indexes and split)
  - ple encode the swaps
- Add extra inputs (amounts, token addresses, min amount, (un)wrap, number of tokens and receiver)

Misc:
- Move executor address and selector encoding inside the SwapEncoder
- Add default executor_selector to SwapEncoder
- Pass router address inside the SplitSwapStrategyEncoder
- Move Permit2 inside the SplitSwapStrategyEncoder. It is a responsibility and a specificity of the strategy to need permit2 approvals

--- don't change below this line ---
ENG-4081 Took 1 hour 21 minutes
2025-01-30 11:23:32 +00:00

73 lines
2.3 KiB
Rust

use std::str::FromStr;
use alloy::signers::local::PrivateKeySigner;
use alloy_primitives::ChainId;
use num_bigint::BigUint;
use tycho_core::Bytes;
use crate::encoding::{
errors::EncodingError,
evm::utils::encode_input,
models::{NativeAction, Solution, Transaction},
router_encoder::RouterEncoder,
strategy_encoder::StrategySelector,
};
#[allow(dead_code)]
pub struct EVMRouterEncoder<S: StrategySelector> {
strategy_selector: S,
signer: Option<PrivateKeySigner>,
chain_id: ChainId,
router_address: String,
}
#[allow(dead_code)]
impl<S: StrategySelector> EVMRouterEncoder<S> {
pub fn new(
strategy_selector: S,
router_address: String,
signer: Option<PrivateKeySigner>,
chain_id: ChainId,
) -> Result<Self, EncodingError> {
Ok(EVMRouterEncoder { strategy_selector, signer, chain_id, router_address })
}
}
impl<S: StrategySelector> RouterEncoder<S> for EVMRouterEncoder<S> {
fn encode_router_calldata(
&self,
solutions: Vec<Solution>,
) -> Result<Vec<Transaction>, EncodingError> {
let mut transactions: Vec<Transaction> = Vec::new();
for solution in solutions.iter() {
let exact_out = solution.exact_out;
let straight_to_pool = solution.straight_to_pool;
let router_address = solution
.router_address
.clone()
.unwrap_or(Bytes::from_str(&self.router_address).map_err(|_| {
EncodingError::FatalError("Invalid router address".to_string())
})?);
let strategy = self.strategy_selector.select_strategy(
solution,
self.signer.clone(),
self.chain_id,
)?;
let method_calldata = strategy.encode_strategy(solution.clone(), router_address)?;
let contract_interaction = if straight_to_pool {
method_calldata
} else {
encode_input(strategy.selector(exact_out), method_calldata)
};
let value = if solution.native_action.clone().unwrap() == NativeAction::Wrap {
solution.given_amount.clone()
} else {
BigUint::ZERO
};
transactions.push(Transaction { value, data: contract_interaction });
}
Ok(transactions)
}
}