Merge branch 'main' into router/hr/ENG-4280-gas-test
This commit is contained in:
@@ -25,7 +25,7 @@ permissions:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
ETH_RPC_URL: ${{ secrets.eth_rpc_url }}
|
RPC_URL: ${{ secrets.eth_rpc_url }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
compile_and_test:
|
compile_and_test:
|
||||||
|
|||||||
22
CHANGELOG.md
22
CHANGELOG.md
@@ -1,3 +1,25 @@
|
|||||||
|
## [0.58.1](https://github.com/propeller-heads/tycho-execution/compare/0.58.0...0.58.1) (2025-03-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add amountIn in error TychoRouter__AmountInDiffersFromConsumed ([a3bffd4](https://github.com/propeller-heads/tycho-execution/commit/a3bffd4f75e8644997970a45c6a8f2b896a30394))
|
||||||
|
* inequality check for amountConsumed and amountIn ([6f421eb](https://github.com/propeller-heads/tycho-execution/commit/6f421eb374b798e9521a2a345558fae53f77dae3))
|
||||||
|
|
||||||
|
## [0.58.0](https://github.com/propeller-heads/tycho-execution/compare/0.57.0...0.58.0) (2025-03-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Rename ETH_RPC_URL -> RPC_URL ([9bb0d9b](https://github.com/propeller-heads/tycho-execution/commit/9bb0d9bc8495f4fff9006d9ed7e353042c023c9c))
|
||||||
|
|
||||||
|
## [0.57.0](https://github.com/propeller-heads/tycho-execution/compare/0.56.0...0.57.0) (2025-03-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Rename shortcut methods of encoder builder ([6f572ee](https://github.com/propeller-heads/tycho-execution/commit/6f572eed01552f4a43181187cfef0c49d0fd9d80))
|
||||||
|
|
||||||
## [0.56.0](https://github.com/propeller-heads/tycho-execution/compare/0.55.0...0.56.0) (2025-02-28)
|
## [0.56.0](https://github.com/propeller-heads/tycho-execution/compare/0.55.0...0.56.0) (2025-02-28)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -4340,7 +4340,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tycho-execution"
|
name = "tycho-execution"
|
||||||
version = "0.56.0"
|
version = "0.58.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy",
|
"alloy",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tycho-execution"
|
name = "tycho-execution"
|
||||||
version = "0.56.0"
|
version = "0.58.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ fn main() {
|
|||||||
// Initialize the encoder
|
// Initialize the encoder
|
||||||
let encoder = EVMEncoderBuilder::new()
|
let encoder = EVMEncoderBuilder::new()
|
||||||
.chain(Chain::Ethereum)
|
.chain(Chain::Ethereum)
|
||||||
.tycho_router_with_permit2(None, swapper_pk)
|
.initialize_tycho_router_with_permit2(swapper_pk)
|
||||||
.expect("Failed to create encoder builder")
|
.expect("Failed to create encoder builder")
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to build encoder");
|
.expect("Failed to build encoder");
|
||||||
|
|||||||
@@ -59,7 +59,9 @@ error TychoRouter__AddressZero();
|
|||||||
error TychoRouter__AmountZero();
|
error TychoRouter__AmountZero();
|
||||||
error TychoRouter__EmptySwaps();
|
error TychoRouter__EmptySwaps();
|
||||||
error TychoRouter__NegativeSlippage(uint256 amount, uint256 minAmount);
|
error TychoRouter__NegativeSlippage(uint256 amount, uint256 minAmount);
|
||||||
error TychoRouter__AmountInNotFullySpent(uint256 leftoverAmount);
|
error TychoRouter__AmountInDiffersFromConsumed(
|
||||||
|
uint256 amountIn, uint256 amountConsumed
|
||||||
|
);
|
||||||
error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount);
|
error TychoRouter__MessageValueMismatch(uint256 value, uint256 amount);
|
||||||
error TychoRouter__InvalidDataLength();
|
error TychoRouter__InvalidDataLength();
|
||||||
|
|
||||||
@@ -163,9 +165,10 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard {
|
|||||||
|
|
||||||
uint256 amountConsumed = initialBalance - currentBalance;
|
uint256 amountConsumed = initialBalance - currentBalance;
|
||||||
|
|
||||||
if (amountConsumed < amountIn) {
|
if (amountConsumed != amountIn) {
|
||||||
uint256 leftoverAmount = amountIn - amountConsumed;
|
revert TychoRouter__AmountInDiffersFromConsumed(
|
||||||
revert TychoRouter__AmountInNotFullySpent(leftoverAmount);
|
amountIn, amountConsumed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fee > 0) {
|
if (fee > 0) {
|
||||||
|
|||||||
@@ -983,7 +983,9 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
|||||||
|
|
||||||
vm.expectRevert(
|
vm.expectRevert(
|
||||||
abi.encodeWithSelector(
|
abi.encodeWithSelector(
|
||||||
TychoRouter__AmountInNotFullySpent.selector, 400000000000000000
|
TychoRouter__AmountInDiffersFromConsumed.selector,
|
||||||
|
1000000000000000000,
|
||||||
|
600000000000000000
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -42,27 +42,21 @@ use tycho_execution::encoding::{
|
|||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: Commands,
|
pub command: Commands,
|
||||||
|
#[arg(short, long)]
|
||||||
|
executors_file_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
/// Use the Tycho router encoding strategy
|
/// Use the Tycho router encoding strategy
|
||||||
TychoRouter {
|
TychoRouter,
|
||||||
#[arg(short, long)]
|
|
||||||
config_path: Option<String>,
|
|
||||||
},
|
|
||||||
/// Use the Tycho router encoding strategy with Permit2 approval and token in transfer
|
/// Use the Tycho router encoding strategy with Permit2 approval and token in transfer
|
||||||
TychoRouterPermit2 {
|
TychoRouterPermit2 {
|
||||||
#[arg(short, long)]
|
|
||||||
config_path: Option<String>,
|
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
swapper_pk: String,
|
swapper_pk: String,
|
||||||
},
|
},
|
||||||
/// Use the direct execution encoding strategy
|
/// Use the direct execution encoding strategy
|
||||||
DirectExecution {
|
DirectExecution,
|
||||||
#[arg(short, long)]
|
|
||||||
config_path: Option<String>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -82,12 +76,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let mut builder = EVMEncoderBuilder::new().chain(chain);
|
let mut builder = EVMEncoderBuilder::new().chain(chain);
|
||||||
|
|
||||||
|
if let Some(config_path) = cli.executors_file_path {
|
||||||
|
builder = builder.executors_file_path(config_path);
|
||||||
|
}
|
||||||
|
|
||||||
builder = match cli.command {
|
builder = match cli.command {
|
||||||
Commands::TychoRouter { config_path } => builder.tycho_router(config_path)?,
|
Commands::TychoRouter => builder.initialize_tycho_router()?,
|
||||||
Commands::TychoRouterPermit2 { config_path, swapper_pk } => {
|
Commands::TychoRouterPermit2 { swapper_pk } => {
|
||||||
builder.tycho_router_with_permit2(config_path, swapper_pk)?
|
builder.initialize_tycho_router_with_permit2(swapper_pk)?
|
||||||
}
|
}
|
||||||
Commands::DirectExecution { config_path } => builder.direct_execution(config_path)?,
|
Commands::DirectExecution => builder.initialize_direct_execution()?,
|
||||||
};
|
};
|
||||||
let encoder = builder.build()?;
|
let encoder = builder.build()?;
|
||||||
let transactions = encoder.encode_router_calldata(vec![solution])?;
|
let transactions = encoder.encode_router_calldata(vec![solution])?;
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ mod tests {
|
|||||||
|
|
||||||
/// This test actually calls the permit method on the Permit2 contract to verify the encoded
|
/// This test actually calls the permit method on the Permit2 contract to verify the encoded
|
||||||
/// data works. It requires an Anvil fork, so please run with the following command: anvil
|
/// data works. It requires an Anvil fork, so please run with the following command: anvil
|
||||||
/// --fork-url <RPC-URL> And set up the following env var as ETH_RPC_URL=127.0.0.1:8545
|
/// --fork-url <RPC-URL> And set up the following env var as RPC_URL=127.0.0.1:8545
|
||||||
/// Use an account from anvil to fill the anvil_account and anvil_private_key variables
|
/// Use an account from anvil to fill the anvil_account and anvil_private_key variables
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(not(feature = "fork-tests"), ignore)]
|
#[cfg_attr(not(feature = "fork-tests"), ignore)]
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ impl ProtocolApprovalsManager {
|
|||||||
/// Gets the client used for interacting with the EVM-compatible network.
|
/// Gets the client used for interacting with the EVM-compatible network.
|
||||||
pub async fn get_client() -> Result<Arc<RootProvider<BoxTransport>>, EncodingError> {
|
pub async fn get_client() -> Result<Arc<RootProvider<BoxTransport>>, EncodingError> {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
let eth_rpc_url = env::var("ETH_RPC_URL")
|
let eth_rpc_url = env::var("RPC_URL")
|
||||||
.map_err(|_| EncodingError::FatalError("Missing ETH_RPC_URL in environment".to_string()))?;
|
.map_err(|_| EncodingError::FatalError("Missing RPC_URL in environment".to_string()))?;
|
||||||
let client = ProviderBuilder::new()
|
let client = ProviderBuilder::new()
|
||||||
.on_builtin(ð_rpc_url)
|
.on_builtin(ð_rpc_url)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use crate::encoding::{
|
|||||||
pub struct EVMEncoderBuilder {
|
pub struct EVMEncoderBuilder {
|
||||||
strategy: Option<Box<dyn StrategyEncoder>>,
|
strategy: Option<Box<dyn StrategyEncoder>>,
|
||||||
chain: Option<Chain>,
|
chain: Option<Chain>,
|
||||||
|
executors_file_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EVMEncoderBuilder {
|
impl Default for EVMEncoderBuilder {
|
||||||
@@ -26,13 +27,20 @@ impl Default for EVMEncoderBuilder {
|
|||||||
|
|
||||||
impl EVMEncoderBuilder {
|
impl EVMEncoderBuilder {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
EVMEncoderBuilder { chain: None, strategy: None }
|
EVMEncoderBuilder { chain: None, strategy: None, executors_file_path: None }
|
||||||
}
|
}
|
||||||
pub fn chain(mut self, chain: Chain) -> Self {
|
pub fn chain(mut self, chain: Chain) -> Self {
|
||||||
self.chain = Some(chain);
|
self.chain = Some(chain);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the `executors_file_path` manually.
|
||||||
|
/// If it's not set, the default path will be used (config/executor_addresses.json)
|
||||||
|
pub fn executors_file_path(mut self, executors_file_path: String) -> Self {
|
||||||
|
self.executors_file_path = Some(executors_file_path);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the `strategy_encoder` manually.
|
/// Sets the `strategy_encoder` manually.
|
||||||
///
|
///
|
||||||
/// **Note**: This method should not be used in combination with `tycho_router` or
|
/// **Note**: This method should not be used in combination with `tycho_router` or
|
||||||
@@ -44,12 +52,17 @@ impl EVMEncoderBuilder {
|
|||||||
|
|
||||||
/// Shortcut method to initialize a `SplitSwapStrategyEncoder` without any approval nor token in
|
/// Shortcut method to initialize a `SplitSwapStrategyEncoder` without any approval nor token in
|
||||||
/// transfer. **Note**: Should not be used at the same time as `strategy_encoder`.
|
/// transfer. **Note**: Should not be used at the same time as `strategy_encoder`.
|
||||||
pub fn tycho_router(self, executors_file_path: Option<String>) -> Result<Self, EncodingError> {
|
pub fn initialize_tycho_router(self) -> Result<Self, EncodingError> {
|
||||||
if let Some(chain) = self.chain {
|
if let Some(chain) = self.chain {
|
||||||
let swap_encoder_registry = SwapEncoderRegistry::new(executors_file_path, chain)?;
|
let swap_encoder_registry =
|
||||||
|
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?;
|
||||||
let strategy =
|
let strategy =
|
||||||
Box::new(SplitSwapStrategyEncoder::new(chain, swap_encoder_registry, None)?);
|
Box::new(SplitSwapStrategyEncoder::new(chain, swap_encoder_registry, None)?);
|
||||||
Ok(EVMEncoderBuilder { chain: Some(chain), strategy: Some(strategy) })
|
Ok(EVMEncoderBuilder {
|
||||||
|
chain: Some(chain),
|
||||||
|
strategy: Some(strategy),
|
||||||
|
executors_file_path: self.executors_file_path,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(EncodingError::FatalError(
|
Err(EncodingError::FatalError(
|
||||||
"Please set the chain before setting the tycho router".to_string(),
|
"Please set the chain before setting the tycho router".to_string(),
|
||||||
@@ -59,19 +72,23 @@ impl EVMEncoderBuilder {
|
|||||||
|
|
||||||
/// Shortcut method to initialize a `SplitSwapStrategyEncoder` with Permit2 approval and token
|
/// Shortcut method to initialize a `SplitSwapStrategyEncoder` with Permit2 approval and token
|
||||||
/// in transfer. **Note**: Should not be used at the same time as `strategy_encoder`.
|
/// in transfer. **Note**: Should not be used at the same time as `strategy_encoder`.
|
||||||
pub fn tycho_router_with_permit2(
|
pub fn initialize_tycho_router_with_permit2(
|
||||||
self,
|
self,
|
||||||
executors_file_path: Option<String>,
|
|
||||||
swapper_pk: String,
|
swapper_pk: String,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
if let Some(chain) = self.chain {
|
if let Some(chain) = self.chain {
|
||||||
let swap_encoder_registry = SwapEncoderRegistry::new(executors_file_path, chain)?;
|
let swap_encoder_registry =
|
||||||
|
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?;
|
||||||
let strategy = Box::new(SplitSwapStrategyEncoder::new(
|
let strategy = Box::new(SplitSwapStrategyEncoder::new(
|
||||||
chain,
|
chain,
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
Some(swapper_pk),
|
Some(swapper_pk),
|
||||||
)?);
|
)?);
|
||||||
Ok(EVMEncoderBuilder { chain: Some(chain), strategy: Some(strategy) })
|
Ok(EVMEncoderBuilder {
|
||||||
|
chain: Some(chain),
|
||||||
|
strategy: Some(strategy),
|
||||||
|
executors_file_path: self.executors_file_path,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(EncodingError::FatalError(
|
Err(EncodingError::FatalError(
|
||||||
"Please set the chain before setting the tycho router".to_string(),
|
"Please set the chain before setting the tycho router".to_string(),
|
||||||
@@ -81,14 +98,16 @@ impl EVMEncoderBuilder {
|
|||||||
|
|
||||||
/// Shortcut method to initialize an `ExecutorStrategyEncoder`.
|
/// Shortcut method to initialize an `ExecutorStrategyEncoder`.
|
||||||
/// **Note**: Should not be used at the same time as `strategy_encoder`.
|
/// **Note**: Should not be used at the same time as `strategy_encoder`.
|
||||||
pub fn direct_execution(
|
pub fn initialize_direct_execution(self) -> Result<Self, EncodingError> {
|
||||||
self,
|
|
||||||
executors_file_path: Option<String>,
|
|
||||||
) -> Result<Self, EncodingError> {
|
|
||||||
if let Some(chain) = self.chain {
|
if let Some(chain) = self.chain {
|
||||||
let swap_encoder_registry = SwapEncoderRegistry::new(executors_file_path, chain)?;
|
let swap_encoder_registry =
|
||||||
|
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?;
|
||||||
let strategy = Box::new(ExecutorStrategyEncoder::new(swap_encoder_registry));
|
let strategy = Box::new(ExecutorStrategyEncoder::new(swap_encoder_registry));
|
||||||
Ok(EVMEncoderBuilder { chain: Some(chain), strategy: Some(strategy) })
|
Ok(EVMEncoderBuilder {
|
||||||
|
chain: Some(chain),
|
||||||
|
strategy: Some(strategy),
|
||||||
|
executors_file_path: self.executors_file_path,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(EncodingError::FatalError(
|
Err(EncodingError::FatalError(
|
||||||
"Please set the chain before setting the strategy".to_string(),
|
"Please set the chain before setting the strategy".to_string(),
|
||||||
|
|||||||
Reference in New Issue
Block a user