Merge branch 'cyclic-route-0.123.0'
This commit is contained in:
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. ..
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Full error traceback**
|
||||||
|
Please provide the full error traceback/failed transaction/failed tenderly simulation
|
||||||
37
CHANGELOG.md
37
CHANGELOG.md
@@ -1,3 +1,40 @@
|
|||||||
|
## [0.128.0](https://github.com/propeller-heads/tycho-execution/compare/0.127.0...0.128.0) (2025-09-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Use tycho-common from crates.io ([89435b5](https://github.com/propeller-heads/tycho-execution/commit/89435b5c76bbd1fbf2c946686ede442c4647cd29))
|
||||||
|
|
||||||
|
## [0.127.0](https://github.com/propeller-heads/tycho-execution/compare/0.126.0...0.127.0) (2025-09-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Use tycho-common from github ([5d73e3b](https://github.com/propeller-heads/tycho-execution/commit/5d73e3b47c5cbff4fa0c88e71f15f48f3831f199))
|
||||||
|
|
||||||
|
## [0.126.0](https://github.com/propeller-heads/tycho-execution/compare/0.125.0...0.126.0) (2025-09-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Add historical_trade option to encoding ([c51c6f5](https://github.com/propeller-heads/tycho-execution/commit/c51c6f52a5c1a7e47caab3bfa721f7c373a8229e))
|
||||||
|
* Pass the file contents instead of the file path for executors ([e78a362](https://github.com/propeller-heads/tycho-execution/commit/e78a362894955a8b0e676bbcb189195d00815aad))
|
||||||
|
* Update tycho common to point to hooks feature branch ([a98e8d2](https://github.com/propeller-heads/tycho-execution/commit/a98e8d21ccd2eafeb42805acb6ce157b60374a0c))
|
||||||
|
|
||||||
|
## [0.125.0](https://github.com/propeller-heads/tycho-execution/compare/0.124.0...0.125.0) (2025-09-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* bump tycho-common version ([fa3bb6d](https://github.com/propeller-heads/tycho-execution/commit/fa3bb6daf74c6df254a4b65718663ec0ca7339d6))
|
||||||
|
|
||||||
|
## [0.124.0](https://github.com/propeller-heads/tycho-execution/compare/0.123.0...0.124.0) (2025-09-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* bump tycho-common version ([bbd732d](https://github.com/propeller-heads/tycho-execution/commit/bbd732d15a4405fc358eedbb3cbb3b98ec3f61b5))
|
||||||
|
|
||||||
## [0.123.0](https://github.com/propeller-heads/tycho-execution/compare/0.122.0...0.123.0) (2025-09-02)
|
## [0.123.0](https://github.com/propeller-heads/tycho-execution/compare/0.122.0...0.123.0) (2025-09-02)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -4634,9 +4634,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tycho-common"
|
name = "tycho-common"
|
||||||
version = "0.82.0"
|
version = "0.88.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "096c87ebe011785fcd7ed59ec501ac12b465a64fbd2914b8c0c57125c253682b"
|
checksum = "ac0c309443e15797f3b713f10b8f00e79067abe91ea7c58421e4ce345b022e0d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -4659,7 +4659,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tycho-execution"
|
name = "tycho-execution"
|
||||||
version = "0.123.0"
|
version = "0.128.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy",
|
"alloy",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
16
Cargo.toml
16
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tycho-execution"
|
name = "tycho-execution"
|
||||||
version = "0.123.0"
|
version = "0.128.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors."
|
description = "Provides tools for encoding and executing swaps against Tycho router and protocol executors."
|
||||||
repository = "https://github.com/propeller-heads/tycho-execution"
|
repository = "https://github.com/propeller-heads/tycho-execution"
|
||||||
@@ -11,12 +11,12 @@ license = "MIT"
|
|||||||
categories = ["finance", "cryptography::cryptocurrencies"]
|
categories = ["finance", "cryptography::cryptocurrencies"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
exclude = [
|
exclude = [
|
||||||
"foundry/*",
|
"foundry/*",
|
||||||
"foundry",
|
"foundry",
|
||||||
"tests/*",
|
"tests/*",
|
||||||
"tests/common",
|
"tests/common",
|
||||||
".github/*",
|
".github/*",
|
||||||
".gitmodules",
|
".gitmodules",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
@@ -37,7 +37,7 @@ tokio = { version = "1.38.0", features = ["full"] }
|
|||||||
chrono = "0.4.39"
|
chrono = "0.4.39"
|
||||||
clap = { version = "4.5.3", features = ["derive"] }
|
clap = { version = "4.5.3", features = ["derive"] }
|
||||||
once_cell = "1.20.2"
|
once_cell = "1.20.2"
|
||||||
tycho-common = "0.82.0"
|
tycho-common = "0.88.0"
|
||||||
alloy = { version = "1.0.6", features = ["providers", "rpc-types-eth", "eip712", "signer-local", "node-bindings"], optional = true }
|
alloy = { version = "1.0.6", features = ["providers", "rpc-types-eth", "eip712", "signer-local", "node-bindings"], optional = true }
|
||||||
async-trait = { version = "0.1.88", optional = true }
|
async-trait = { version = "0.1.88", optional = true }
|
||||||
|
|
||||||
|
|||||||
1
foundry/test/.gitignore
vendored
Normal file
1
foundry/test/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.runtime.json
|
||||||
@@ -136,7 +136,6 @@ contract BalancerV2ExecutorTest is Constants, TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function testExportContract() public {
|
function testExportContract() public {
|
||||||
vm.skip(true);
|
|
||||||
exportRuntimeBytecode(address(balancerV2Exposed), "BalancerV2");
|
exportRuntimeBytecode(address(balancerV2Exposed), "BalancerV2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,10 @@ contract BalancerV3ExecutorTest is Constants, TestUtils {
|
|||||||
assertGt(balanceAfter, balanceBefore);
|
assertGt(balanceAfter, balanceBefore);
|
||||||
assertEq(balanceAfter - balanceBefore, amountOut);
|
assertEq(balanceAfter - balanceBefore, amountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testExportContract() public {
|
||||||
|
exportRuntimeBytecode(address(balancerV3Exposed), "BalancerV3");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ contract CurveExecutorExposed is CurveExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract CurveExecutorTest is Test, Constants {
|
contract CurveExecutorTest is Test, TestUtils, Constants {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
CurveExecutorExposed curveExecutorExposed;
|
CurveExecutorExposed curveExecutorExposed;
|
||||||
@@ -393,6 +393,10 @@ contract CurveExecutorTest is Test, Constants {
|
|||||||
metaRegistry.get_coin_indices(pool, tokenIn, tokenOut);
|
metaRegistry.get_coin_indices(pool, tokenIn, tokenOut);
|
||||||
return (coinInIndex, coinOutIndex);
|
return (coinInIndex, coinOutIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testExportContract() public {
|
||||||
|
exportRuntimeBytecode(address(curveExecutorExposed), "Curve");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
||||||
|
|||||||
@@ -202,6 +202,10 @@ contract EkuboExecutorTest is Constants, TestUtils {
|
|||||||
function testMultiHopSwapIntegration() public setUpFork(22082754) {
|
function testMultiHopSwapIntegration() public setUpFork(22082754) {
|
||||||
multiHopSwap(loadCallDataFromFile("test_ekubo_encode_swap_multi"));
|
multiHopSwap(loadCallDataFromFile("test_ekubo_encode_swap_multi"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testExportContract() public {
|
||||||
|
exportRuntimeBytecode(address(executor), "Ekubo");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ contract HashflowUtils is Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract HashflowExecutorECR20Test is Constants, HashflowUtils {
|
contract HashflowExecutorECR20Test is Constants, TestUtils, HashflowUtils {
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
HashflowExecutorExposed executor;
|
HashflowExecutorExposed executor;
|
||||||
|
|||||||
@@ -126,6 +126,10 @@ contract MaverickV2ExecutorTest is TestUtils, Constants {
|
|||||||
assertGt(balanceAfter, balanceBefore);
|
assertGt(balanceAfter, balanceBefore);
|
||||||
assertEq(balanceAfter - balanceBefore, amountOut);
|
assertEq(balanceAfter - balanceBefore, amountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testExportContract() public {
|
||||||
|
exportRuntimeBytecode(address(maverickV2Exposed), "MaverickV2");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
||||||
|
|||||||
@@ -263,4 +263,8 @@ contract UniswapV2ExecutorTest is Constants, Permit2TestHelper, TestUtils {
|
|||||||
|
|
||||||
assertEq(IERC20(BASE_MAG7).balanceOf(BOB), 1379830606);
|
assertEq(IERC20(BASE_MAG7).balanceOf(BOB), 1379830606);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testExportContract() public {
|
||||||
|
exportRuntimeBytecode(address(uniswapV2Exposed), "UniswapV2");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,12 @@ contract UniswapV3ExecutorExposed is UniswapV3Executor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper {
|
contract UniswapV3ExecutorTest is
|
||||||
|
Test,
|
||||||
|
TestUtils,
|
||||||
|
Constants,
|
||||||
|
Permit2TestHelper
|
||||||
|
{
|
||||||
using SafeERC20 for IERC20;
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
UniswapV3ExecutorExposed uniswapV3Exposed;
|
UniswapV3ExecutorExposed uniswapV3Exposed;
|
||||||
@@ -210,6 +215,10 @@ contract UniswapV3ExecutorTest is Test, Constants, Permit2TestHelper {
|
|||||||
transferType
|
transferType
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testExportContract() public {
|
||||||
|
exportRuntimeBytecode(address(uniswapV3Exposed), "UniswapV3");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
||||||
|
|||||||
@@ -261,6 +261,10 @@ contract UniswapV4ExecutorTest is Constants, TestUtils {
|
|||||||
);
|
);
|
||||||
assertTrue(IERC20(WETH_ADDR).balanceOf(ALICE) == amountOut);
|
assertTrue(IERC20(WETH_ADDR).balanceOf(ALICE) == amountOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testExportContract() public {
|
||||||
|
exportRuntimeBytecode(address(uniswapV4Exposed), "UniswapV4");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
contract TychoRouterForBalancerV3Test is TychoRouterTestSetup {
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
use std::io::{self, Read};
|
use std::{
|
||||||
|
fs,
|
||||||
|
io::{self, Read},
|
||||||
|
};
|
||||||
|
|
||||||
use alloy::sol_types::SolValue;
|
use alloy::sol_types::SolValue;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use tycho_common::{hex_bytes::Bytes, models::Chain};
|
use tycho_common::{hex_bytes::Bytes, models::Chain};
|
||||||
use tycho_execution::encoding::{
|
use tycho_execution::encoding::{
|
||||||
|
errors::EncodingError,
|
||||||
evm::{
|
evm::{
|
||||||
approvals::permit2::PermitSingle,
|
approvals::permit2::PermitSingle,
|
||||||
encoder_builders::{TychoExecutorEncoderBuilder, TychoRouterEncoderBuilder},
|
encoder_builders::{TychoExecutorEncoderBuilder, TychoRouterEncoderBuilder},
|
||||||
@@ -83,7 +87,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Commands::TychoRouter => {
|
Commands::TychoRouter => {
|
||||||
let mut builder = TychoRouterEncoderBuilder::new().chain(chain);
|
let mut builder = TychoRouterEncoderBuilder::new().chain(chain);
|
||||||
if let Some(config_path) = cli.executors_file_path {
|
if let Some(config_path) = cli.executors_file_path {
|
||||||
builder = builder.executors_file_path(config_path);
|
let executors_addresses = fs::read_to_string(&config_path).map_err(|e| {
|
||||||
|
EncodingError::FatalError(format!(
|
||||||
|
"Error reading executors file from {config_path:?}: {e}",
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
builder = builder.executors_addresses(executors_addresses);
|
||||||
}
|
}
|
||||||
if let Some(router_address) = cli.router_address {
|
if let Some(router_address) = cli.router_address {
|
||||||
builder = builder.router_address(router_address);
|
builder = builder.router_address(router_address);
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ use crate::encoding::{
|
|||||||
pub struct TychoRouterEncoderBuilder {
|
pub struct TychoRouterEncoderBuilder {
|
||||||
chain: Option<Chain>,
|
chain: Option<Chain>,
|
||||||
user_transfer_type: Option<UserTransferType>,
|
user_transfer_type: Option<UserTransferType>,
|
||||||
executors_file_path: Option<String>,
|
executors_addresses: Option<String>,
|
||||||
router_address: Option<Bytes>,
|
router_address: Option<Bytes>,
|
||||||
swapper_pk: Option<String>,
|
swapper_pk: Option<String>,
|
||||||
|
historical_trade: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TychoRouterEncoderBuilder {
|
impl Default for TychoRouterEncoderBuilder {
|
||||||
@@ -35,10 +36,11 @@ impl TychoRouterEncoderBuilder {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
TychoRouterEncoderBuilder {
|
TychoRouterEncoderBuilder {
|
||||||
chain: None,
|
chain: None,
|
||||||
executors_file_path: None,
|
executors_addresses: None,
|
||||||
router_address: None,
|
router_address: None,
|
||||||
swapper_pk: None,
|
swapper_pk: None,
|
||||||
user_transfer_type: None,
|
user_transfer_type: None,
|
||||||
|
historical_trade: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn chain(mut self, chain: Chain) -> Self {
|
pub fn chain(mut self, chain: Chain) -> Self {
|
||||||
@@ -51,10 +53,10 @@ impl TychoRouterEncoderBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the `executors_file_path` manually.
|
/// Sets the `executors_addresses` manually.
|
||||||
/// If it's not set, the default path will be used (config/executor_addresses.json)
|
/// If it's not set, the default value will be used (contents of config/executor_addresses.json)
|
||||||
pub fn executors_file_path(mut self, executors_file_path: String) -> Self {
|
pub fn executors_addresses(mut self, executors_addresses: String) -> Self {
|
||||||
self.executors_file_path = Some(executors_file_path);
|
self.executors_addresses = Some(executors_addresses);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +67,15 @@ impl TychoRouterEncoderBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the `historical_trade` manually to true.
|
||||||
|
/// If set to true, it means that the encoded trade will be used in an historical block (as a
|
||||||
|
/// test) and not in the current one. This is relevant for checking token approvals in some
|
||||||
|
/// protocols (like Balancer v2).
|
||||||
|
pub fn historical_trade(mut self) -> Self {
|
||||||
|
self.historical_trade = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the `swapper_pk` for the encoder. This is used to sign permit2 objects. This is only
|
/// Sets the `swapper_pk` for the encoder. This is used to sign permit2 objects. This is only
|
||||||
/// needed if you intend to get the full calldata for the transfer. We do not recommend
|
/// needed if you intend to get the full calldata for the transfer. We do not recommend
|
||||||
/// using this option, you should sign and create the function calldata entirely on your
|
/// using this option, you should sign and create the function calldata entirely on your
|
||||||
@@ -96,7 +107,7 @@ impl TychoRouterEncoderBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let swap_encoder_registry =
|
let swap_encoder_registry =
|
||||||
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?;
|
SwapEncoderRegistry::new(self.executors_addresses.clone(), chain)?;
|
||||||
|
|
||||||
let signer = if let Some(pk) = self.swapper_pk {
|
let signer = if let Some(pk) = self.swapper_pk {
|
||||||
let pk = B256::from_str(&pk).map_err(|_| {
|
let pk = B256::from_str(&pk).map_err(|_| {
|
||||||
@@ -115,6 +126,7 @@ impl TychoRouterEncoderBuilder {
|
|||||||
tycho_router_address,
|
tycho_router_address,
|
||||||
user_transfer_type,
|
user_transfer_type,
|
||||||
signer,
|
signer,
|
||||||
|
self.historical_trade,
|
||||||
)?))
|
)?))
|
||||||
} else {
|
} else {
|
||||||
Err(EncodingError::FatalError(
|
Err(EncodingError::FatalError(
|
||||||
@@ -128,7 +140,7 @@ impl TychoRouterEncoderBuilder {
|
|||||||
/// Builder pattern for constructing a `TychoExecutorEncoder` with customizable options.
|
/// Builder pattern for constructing a `TychoExecutorEncoder` with customizable options.
|
||||||
pub struct TychoExecutorEncoderBuilder {
|
pub struct TychoExecutorEncoderBuilder {
|
||||||
chain: Option<Chain>,
|
chain: Option<Chain>,
|
||||||
executors_file_path: Option<String>,
|
executors_addresses: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TychoExecutorEncoderBuilder {
|
impl Default for TychoExecutorEncoderBuilder {
|
||||||
@@ -139,17 +151,17 @@ impl Default for TychoExecutorEncoderBuilder {
|
|||||||
|
|
||||||
impl TychoExecutorEncoderBuilder {
|
impl TychoExecutorEncoderBuilder {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
TychoExecutorEncoderBuilder { chain: None, executors_file_path: None }
|
TychoExecutorEncoderBuilder { chain: None, executors_addresses: 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.
|
/// Sets the `executors_addresses` manually.
|
||||||
/// If it's not set, the default path will be used (config/executor_addresses.json)
|
/// 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 {
|
pub fn executors_addresses(mut self, executors_addresses: String) -> Self {
|
||||||
self.executors_file_path = Some(executors_file_path);
|
self.executors_addresses = Some(executors_addresses);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +170,7 @@ impl TychoExecutorEncoderBuilder {
|
|||||||
pub fn build(self) -> Result<Box<dyn TychoEncoder>, EncodingError> {
|
pub fn build(self) -> Result<Box<dyn TychoEncoder>, EncodingError> {
|
||||||
if let Some(chain) = self.chain {
|
if let Some(chain) = self.chain {
|
||||||
let swap_encoder_registry =
|
let swap_encoder_registry =
|
||||||
SwapEncoderRegistry::new(self.executors_file_path.clone(), chain)?;
|
SwapEncoderRegistry::new(self.executors_addresses.clone(), chain)?;
|
||||||
Ok(Box::new(TychoExecutorEncoder::new(swap_encoder_registry)?))
|
Ok(Box::new(TychoExecutorEncoder::new(swap_encoder_registry)?))
|
||||||
} else {
|
} else {
|
||||||
Err(EncodingError::FatalError(
|
Err(EncodingError::FatalError(
|
||||||
|
|||||||
@@ -58,11 +58,12 @@ use crate::encoding::{
|
|||||||
/// funds.
|
/// funds.
|
||||||
///
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
|
/// - `chain_id`: Chain ID
|
||||||
/// - `encoded_solution`: The solution already encoded by Tycho.
|
/// - `encoded_solution`: The solution already encoded by Tycho.
|
||||||
/// - `solution`: The high-level solution including tokens, amounts, and receiver info.
|
/// - `solution`: The high-level solution including tokens, amounts, and receiver info.
|
||||||
/// - `token_in_already_in_router`: Whether the input token is already present in the router.
|
/// - `user_transfer_type`: The desired transfer method.
|
||||||
/// - `router_address`: The address of the Tycho Router contract.
|
|
||||||
/// - `native_address`: The address used to represent the native token
|
/// - `native_address`: The address used to represent the native token
|
||||||
|
/// - `signer`: Optional signer for permit2
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A `Result<Transaction, EncodingError>` that either contains the full transaction data (to,
|
/// A `Result<Transaction, EncodingError>` that either contains the full transaction data (to,
|
||||||
|
|||||||
@@ -26,12 +26,15 @@ use crate::encoding::{
|
|||||||
/// * `function_signature`: String, the signature for the swap function in the router contract
|
/// * `function_signature`: String, the signature for the swap function in the router contract
|
||||||
/// * `router_address`: Address of the router to be used to execute swaps
|
/// * `router_address`: Address of the router to be used to execute swaps
|
||||||
/// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers
|
/// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers
|
||||||
|
/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical
|
||||||
|
/// one. This is relevant for checking token approvals in some protocols (like Balancer v2).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SingleSwapStrategyEncoder {
|
pub struct SingleSwapStrategyEncoder {
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
function_signature: String,
|
function_signature: String,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
transfer_optimization: TransferOptimization,
|
transfer_optimization: TransferOptimization,
|
||||||
|
historical_trade: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SingleSwapStrategyEncoder {
|
impl SingleSwapStrategyEncoder {
|
||||||
@@ -40,6 +43,7 @@ impl SingleSwapStrategyEncoder {
|
|||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
user_transfer_type: UserTransferType,
|
user_transfer_type: UserTransferType,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
|
historical_trade: bool,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
||||||
"singleSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)"
|
"singleSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)"
|
||||||
@@ -57,6 +61,7 @@ impl SingleSwapStrategyEncoder {
|
|||||||
user_transfer_type,
|
user_transfer_type,
|
||||||
router_address,
|
router_address,
|
||||||
),
|
),
|
||||||
|
historical_trade,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +124,7 @@ impl StrategyEncoder for SingleSwapStrategyEncoder {
|
|||||||
group_token_in: grouped_swap.token_in.clone(),
|
group_token_in: grouped_swap.token_in.clone(),
|
||||||
group_token_out: grouped_swap.token_out.clone(),
|
group_token_out: grouped_swap.token_out.clone(),
|
||||||
transfer_type: transfer,
|
transfer_type: transfer,
|
||||||
|
historical_trade: self.historical_trade,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
||||||
@@ -171,6 +177,8 @@ impl StrategyEncoder for SingleSwapStrategyEncoder {
|
|||||||
/// * `sequential_swap_validator`: SequentialSwapValidator, responsible for checking validity of
|
/// * `sequential_swap_validator`: SequentialSwapValidator, responsible for checking validity of
|
||||||
/// sequential swap solutions
|
/// sequential swap solutions
|
||||||
/// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers
|
/// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers
|
||||||
|
/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical
|
||||||
|
/// one. This is relevant for checking token approvals in some protocols (like Balancer v2).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SequentialSwapStrategyEncoder {
|
pub struct SequentialSwapStrategyEncoder {
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
@@ -180,6 +188,7 @@ pub struct SequentialSwapStrategyEncoder {
|
|||||||
wrapped_address: Bytes,
|
wrapped_address: Bytes,
|
||||||
sequential_swap_validator: SequentialSwapValidator,
|
sequential_swap_validator: SequentialSwapValidator,
|
||||||
transfer_optimization: TransferOptimization,
|
transfer_optimization: TransferOptimization,
|
||||||
|
historical_trade: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SequentialSwapStrategyEncoder {
|
impl SequentialSwapStrategyEncoder {
|
||||||
@@ -188,6 +197,7 @@ impl SequentialSwapStrategyEncoder {
|
|||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
user_transfer_type: UserTransferType,
|
user_transfer_type: UserTransferType,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
|
historical_trade: bool,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
||||||
"sequentialSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)"
|
"sequentialSwapPermit2(uint256,address,address,uint256,bool,bool,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)"
|
||||||
@@ -210,6 +220,7 @@ impl SequentialSwapStrategyEncoder {
|
|||||||
user_transfer_type,
|
user_transfer_type,
|
||||||
router_address,
|
router_address,
|
||||||
),
|
),
|
||||||
|
historical_trade,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,6 +290,7 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
|||||||
group_token_in: grouped_swap.token_in.clone(),
|
group_token_in: grouped_swap.token_in.clone(),
|
||||||
group_token_out: grouped_swap.token_out.clone(),
|
group_token_out: grouped_swap.token_out.clone(),
|
||||||
transfer_type: transfer,
|
transfer_type: transfer,
|
||||||
|
historical_trade: self.historical_trade,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
||||||
@@ -336,6 +348,8 @@ impl StrategyEncoder for SequentialSwapStrategyEncoder {
|
|||||||
/// solutions
|
/// solutions
|
||||||
/// * `router_address`: Address of the router to be used to execute swaps
|
/// * `router_address`: Address of the router to be used to execute swaps
|
||||||
/// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers
|
/// * `transfer_optimization`: TransferOptimization, responsible for optimizing the token transfers
|
||||||
|
/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical
|
||||||
|
/// one. This is relevant for checking token approvals in some protocols (like Balancer v2).
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SplitSwapStrategyEncoder {
|
pub struct SplitSwapStrategyEncoder {
|
||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
@@ -345,6 +359,7 @@ pub struct SplitSwapStrategyEncoder {
|
|||||||
split_swap_validator: SplitSwapValidator,
|
split_swap_validator: SplitSwapValidator,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
transfer_optimization: TransferOptimization,
|
transfer_optimization: TransferOptimization,
|
||||||
|
historical_trade: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SplitSwapStrategyEncoder {
|
impl SplitSwapStrategyEncoder {
|
||||||
@@ -353,6 +368,7 @@ impl SplitSwapStrategyEncoder {
|
|||||||
swap_encoder_registry: SwapEncoderRegistry,
|
swap_encoder_registry: SwapEncoderRegistry,
|
||||||
user_transfer_type: UserTransferType,
|
user_transfer_type: UserTransferType,
|
||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
|
historical_trade: bool,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
let function_signature = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
||||||
"splitSwapPermit2(uint256,address,address,uint256,bool,bool,uint256,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)"
|
"splitSwapPermit2(uint256,address,address,uint256,bool,bool,uint256,address,((address,uint160,uint48,uint48),address,uint256),bytes,bytes)"
|
||||||
@@ -374,6 +390,7 @@ impl SplitSwapStrategyEncoder {
|
|||||||
user_transfer_type,
|
user_transfer_type,
|
||||||
router_address,
|
router_address,
|
||||||
),
|
),
|
||||||
|
historical_trade,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,6 +496,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
|||||||
group_token_in: grouped_swap.token_in.clone(),
|
group_token_in: grouped_swap.token_in.clone(),
|
||||||
group_token_out: grouped_swap.token_out.clone(),
|
group_token_out: grouped_swap.token_out.clone(),
|
||||||
transfer_type: transfer,
|
transfer_type: transfer,
|
||||||
|
historical_trade: self.historical_trade,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
||||||
@@ -535,7 +553,7 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use std::{collections::HashMap, fs, str::FromStr};
|
||||||
|
|
||||||
use alloy::{hex::encode, primitives::hex};
|
use alloy::{hex::encode, primitives::hex};
|
||||||
use num_bigint::{BigInt, BigUint};
|
use num_bigint::{BigInt, BigUint};
|
||||||
@@ -555,9 +573,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_swap_encoder_registry() -> SwapEncoderRegistry {
|
fn get_swap_encoder_registry() -> SwapEncoderRegistry {
|
||||||
|
let executors_addresses =
|
||||||
|
fs::read_to_string("config/test_executor_addresses.json").unwrap();
|
||||||
let eth_chain = eth_chain();
|
let eth_chain = eth_chain();
|
||||||
SwapEncoderRegistry::new(Some("config/test_executor_addresses.json".to_string()), eth_chain)
|
SwapEncoderRegistry::new(Some(executors_addresses), eth_chain).unwrap()
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn router_address() -> Bytes {
|
fn router_address() -> Bytes {
|
||||||
@@ -591,6 +610,7 @@ mod tests {
|
|||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
UserTransferType::TransferFromPermit2,
|
UserTransferType::TransferFromPermit2,
|
||||||
router_address(),
|
router_address(),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -651,6 +671,7 @@ mod tests {
|
|||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
UserTransferType::None,
|
UserTransferType::None,
|
||||||
router_address(),
|
router_address(),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -732,6 +753,7 @@ mod tests {
|
|||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
UserTransferType::TransferFrom,
|
UserTransferType::TransferFrom,
|
||||||
router_address(),
|
router_address(),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let solution = Solution {
|
let solution = Solution {
|
||||||
@@ -867,6 +889,7 @@ mod tests {
|
|||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
UserTransferType::TransferFromPermit2,
|
UserTransferType::TransferFromPermit2,
|
||||||
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -1015,6 +1038,7 @@ mod tests {
|
|||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
UserTransferType::TransferFrom,
|
UserTransferType::TransferFrom,
|
||||||
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
Bytes::from("0x3Ede3eCa2a72B3aeCC820E955B36f38437D01395"),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashMap, fs};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use tycho_common::models::Chain;
|
use tycho_common::models::Chain;
|
||||||
|
|
||||||
@@ -21,13 +21,9 @@ pub struct SwapEncoderRegistry {
|
|||||||
impl SwapEncoderRegistry {
|
impl SwapEncoderRegistry {
|
||||||
/// Populates the registry with the `SwapEncoders` for the given blockchain by parsing the
|
/// Populates the registry with the `SwapEncoders` for the given blockchain by parsing the
|
||||||
/// executors' addresses in the file at the given path.
|
/// executors' addresses in the file at the given path.
|
||||||
pub fn new(executors_file_path: Option<String>, chain: Chain) -> Result<Self, EncodingError> {
|
pub fn new(executors_addresses: Option<String>, chain: Chain) -> Result<Self, EncodingError> {
|
||||||
let config_str = if let Some(ref path) = executors_file_path {
|
let config_str = if let Some(addresses) = executors_addresses {
|
||||||
fs::read_to_string(path).map_err(|e| {
|
addresses
|
||||||
EncodingError::FatalError(format!(
|
|
||||||
"Error reading executors file from {executors_file_path:?}: {e}",
|
|
||||||
))
|
|
||||||
})?
|
|
||||||
} else {
|
} else {
|
||||||
DEFAULT_EXECUTORS_JSON.to_string()
|
DEFAULT_EXECUTORS_JSON.to_string()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -280,19 +280,20 @@ impl SwapEncoder for BalancerV2SwapEncoder {
|
|||||||
) -> Result<Vec<u8>, EncodingError> {
|
) -> Result<Vec<u8>, EncodingError> {
|
||||||
let token_approvals_manager = ProtocolApprovalsManager::new()?;
|
let token_approvals_manager = ProtocolApprovalsManager::new()?;
|
||||||
let token = bytes_to_address(&swap.token_in)?;
|
let token = bytes_to_address(&swap.token_in)?;
|
||||||
let approval_needed: bool;
|
let mut approval_needed: bool = true;
|
||||||
|
|
||||||
if let Some(router_address) = &encoding_context.router_address {
|
if let Some(router_address) = &encoding_context.router_address {
|
||||||
let tycho_router_address = bytes_to_address(router_address)?;
|
if !encoding_context.historical_trade {
|
||||||
approval_needed = token_approvals_manager.approval_needed(
|
let tycho_router_address = bytes_to_address(router_address)?;
|
||||||
token,
|
approval_needed = token_approvals_manager.approval_needed(
|
||||||
tycho_router_address,
|
token,
|
||||||
Address::from_str(&self.vault_address)
|
tycho_router_address,
|
||||||
.map_err(|_| EncodingError::FatalError("Invalid vault address".to_string()))?,
|
Address::from_str(&self.vault_address).map_err(|_| {
|
||||||
)?;
|
EncodingError::FatalError("Invalid vault address".to_string())
|
||||||
} else {
|
})?,
|
||||||
approval_needed = true;
|
)?;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let component_id = AlloyBytes::from_str(&swap.component.id)
|
let component_id = AlloyBytes::from_str(&swap.component.id)
|
||||||
.map_err(|_| EncodingError::FatalError("Invalid component ID".to_string()))?;
|
.map_err(|_| EncodingError::FatalError("Invalid component ID".to_string()))?;
|
||||||
@@ -1026,6 +1027,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = UniswapV2SwapEncoder::new(
|
let encoder = UniswapV2SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -1081,6 +1083,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = UniswapV3SwapEncoder::new(
|
let encoder = UniswapV3SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -1138,6 +1141,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::None,
|
transfer_type: TransferType::None,
|
||||||
|
historical_trade: true,
|
||||||
};
|
};
|
||||||
let encoder = BalancerV2SwapEncoder::new(
|
let encoder = BalancerV2SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -1207,6 +1211,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = UniswapV4SwapEncoder::new(
|
let encoder = UniswapV4SwapEncoder::new(
|
||||||
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
String::from("0xF62849F9A0B5Bf2913b396098F7c7019b51A820a"),
|
||||||
@@ -1275,6 +1280,7 @@ mod tests {
|
|||||||
// Token out is the same as the group token out
|
// Token out is the same as the group token out
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder = UniswapV4SwapEncoder::new(
|
let encoder = UniswapV4SwapEncoder::new(
|
||||||
@@ -1318,6 +1324,7 @@ mod tests {
|
|||||||
group_token_in: usde_address.clone(),
|
group_token_in: usde_address.clone(),
|
||||||
group_token_out: wbtc_address.clone(),
|
group_token_out: wbtc_address.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup - First sequence: USDE -> USDT
|
// Setup - First sequence: USDE -> USDT
|
||||||
@@ -1448,6 +1455,7 @@ mod tests {
|
|||||||
exact_out: false,
|
exact_out: false,
|
||||||
router_address: Some(Bytes::default()),
|
router_address: Some(Bytes::default()),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder = EkuboSwapEncoder::new(String::default(), Chain::Ethereum, None).unwrap();
|
let encoder = EkuboSwapEncoder::new(String::default(), Chain::Ethereum, None).unwrap();
|
||||||
@@ -1490,6 +1498,7 @@ mod tests {
|
|||||||
exact_out: false,
|
exact_out: false,
|
||||||
router_address: Some(Bytes::default()),
|
router_address: Some(Bytes::default()),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_swap = SwapBuilder::new(
|
let first_swap = SwapBuilder::new(
|
||||||
@@ -1687,6 +1696,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::None,
|
transfer_type: TransferType::None,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = CurveSwapEncoder::new(
|
let encoder = CurveSwapEncoder::new(
|
||||||
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
||||||
@@ -1753,6 +1763,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::None,
|
transfer_type: TransferType::None,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = CurveSwapEncoder::new(
|
let encoder = CurveSwapEncoder::new(
|
||||||
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
||||||
@@ -1820,6 +1831,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::None,
|
transfer_type: TransferType::None,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = CurveSwapEncoder::new(
|
let encoder = CurveSwapEncoder::new(
|
||||||
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
String::from("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f"),
|
||||||
@@ -1888,6 +1900,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = BalancerV3SwapEncoder::new(
|
let encoder = BalancerV3SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -1940,6 +1953,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let encoder = MaverickV2SwapEncoder::new(
|
let encoder = MaverickV2SwapEncoder::new(
|
||||||
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
String::from("0x543778987b293C7E8Cf0722BB2e935ba6f4068D4"),
|
||||||
@@ -2033,6 +2047,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder = BebopSwapEncoder::new(
|
let encoder = BebopSwapEncoder::new(
|
||||||
@@ -2107,6 +2122,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder = HashflowSwapEncoder::new(
|
let encoder = HashflowSwapEncoder::new(
|
||||||
@@ -2200,6 +2216,7 @@ mod tests {
|
|||||||
group_token_in: token_in.clone(),
|
group_token_in: token_in.clone(),
|
||||||
group_token_out: token_out.clone(),
|
group_token_out: token_out.clone(),
|
||||||
transfer_type: TransferType::Transfer,
|
transfer_type: TransferType::Transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoder = HashflowSwapEncoder::new(
|
let encoder = HashflowSwapEncoder::new(
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ impl TychoRouterEncoder {
|
|||||||
router_address: Bytes,
|
router_address: Bytes,
|
||||||
user_transfer_type: UserTransferType,
|
user_transfer_type: UserTransferType,
|
||||||
signer: Option<PrivateKeySigner>,
|
signer: Option<PrivateKeySigner>,
|
||||||
|
historical_trade: bool,
|
||||||
) -> Result<Self, EncodingError> {
|
) -> Result<Self, EncodingError> {
|
||||||
let permit2 = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
let permit2 = if user_transfer_type == UserTransferType::TransferFromPermit2 {
|
||||||
Some(Permit2::new()?)
|
Some(Permit2::new()?)
|
||||||
@@ -66,18 +67,21 @@ impl TychoRouterEncoder {
|
|||||||
swap_encoder_registry.clone(),
|
swap_encoder_registry.clone(),
|
||||||
user_transfer_type.clone(),
|
user_transfer_type.clone(),
|
||||||
router_address.clone(),
|
router_address.clone(),
|
||||||
|
historical_trade,
|
||||||
)?,
|
)?,
|
||||||
sequential_swap_strategy: SequentialSwapStrategyEncoder::new(
|
sequential_swap_strategy: SequentialSwapStrategyEncoder::new(
|
||||||
chain,
|
chain,
|
||||||
swap_encoder_registry.clone(),
|
swap_encoder_registry.clone(),
|
||||||
user_transfer_type.clone(),
|
user_transfer_type.clone(),
|
||||||
router_address.clone(),
|
router_address.clone(),
|
||||||
|
historical_trade,
|
||||||
)?,
|
)?,
|
||||||
split_swap_strategy: SplitSwapStrategyEncoder::new(
|
split_swap_strategy: SplitSwapStrategyEncoder::new(
|
||||||
chain,
|
chain,
|
||||||
swap_encoder_registry,
|
swap_encoder_registry,
|
||||||
user_transfer_type.clone(),
|
user_transfer_type.clone(),
|
||||||
router_address.clone(),
|
router_address.clone(),
|
||||||
|
historical_trade,
|
||||||
)?,
|
)?,
|
||||||
router_address,
|
router_address,
|
||||||
permit2,
|
permit2,
|
||||||
@@ -333,6 +337,7 @@ impl TychoExecutorEncoder {
|
|||||||
group_token_in: grouped_swap.token_in.clone(),
|
group_token_in: grouped_swap.token_in.clone(),
|
||||||
group_token_out: grouped_swap.token_out.clone(),
|
group_token_out: grouped_swap.token_out.clone(),
|
||||||
transfer_type: transfer,
|
transfer_type: transfer,
|
||||||
|
historical_trade: false,
|
||||||
};
|
};
|
||||||
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
let mut grouped_protocol_data: Vec<Vec<u8>> = vec![];
|
||||||
let mut initial_protocol_data: Vec<u8> = vec![];
|
let mut initial_protocol_data: Vec<u8> = vec![];
|
||||||
@@ -402,7 +407,7 @@ impl TychoEncoder for TychoExecutorEncoder {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use std::{collections::HashMap, fs, str::FromStr};
|
||||||
|
|
||||||
use num_bigint::{BigInt, BigUint};
|
use num_bigint::{BigInt, BigUint};
|
||||||
use tycho_common::models::{protocol::ProtocolComponent, Chain};
|
use tycho_common::models::{protocol::ProtocolComponent, Chain};
|
||||||
@@ -486,11 +491,9 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_swap_encoder_registry() -> SwapEncoderRegistry {
|
fn get_swap_encoder_registry() -> SwapEncoderRegistry {
|
||||||
SwapEncoderRegistry::new(
|
let executors_addresses =
|
||||||
Some("config/test_executor_addresses.json".to_string()),
|
fs::read_to_string("config/test_executor_addresses.json").unwrap();
|
||||||
eth_chain(),
|
SwapEncoderRegistry::new(Some(executors_addresses), eth_chain()).unwrap()
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tycho_router_encoder(user_transfer_type: UserTransferType) -> TychoRouterEncoder {
|
fn get_tycho_router_encoder(user_transfer_type: UserTransferType) -> TychoRouterEncoder {
|
||||||
@@ -500,6 +503,7 @@ mod tests {
|
|||||||
router_address(),
|
router_address(),
|
||||||
user_transfer_type,
|
user_transfer_type,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,6 +273,8 @@ impl PartialEq for PermitDetails {
|
|||||||
/// * `group_token_in`: Token to be used as the input for the group swap.
|
/// * `group_token_in`: Token to be used as the input for the group swap.
|
||||||
/// * `group_token_out`: Token to be used as the output for the group swap.
|
/// * `group_token_out`: Token to be used as the output for the group swap.
|
||||||
/// * `transfer`: Type of transfer to be performed. See `TransferType` for more details.
|
/// * `transfer`: Type of transfer to be performed. See `TransferType` for more details.
|
||||||
|
/// * `historical_trade`: Whether the swap is to be done in the current block or in an historical
|
||||||
|
/// one. This is relevant for checking token approvals in some protocols (like Balancer v2).
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct EncodingContext {
|
pub struct EncodingContext {
|
||||||
pub receiver: Bytes,
|
pub receiver: Bytes,
|
||||||
@@ -281,6 +283,7 @@ pub struct EncodingContext {
|
|||||||
pub group_token_in: Bytes,
|
pub group_token_in: Bytes,
|
||||||
pub group_token_out: Bytes,
|
pub group_token_out: Bytes,
|
||||||
pub transfer_type: TransferType,
|
pub transfer_type: TransferType,
|
||||||
|
pub historical_trade: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the type of transfer to be performed into the pool.
|
/// Represents the type of transfer to be performed into the pool.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
pub mod encoding;
|
pub mod encoding;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::{fs, str::FromStr};
|
||||||
|
|
||||||
use alloy::{
|
use alloy::{
|
||||||
primitives::{B256, U256},
|
primitives::{B256, U256},
|
||||||
@@ -71,10 +71,11 @@ pub fn get_signer() -> PrivateKeySigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tycho_router_encoder(user_transfer_type: UserTransferType) -> Box<dyn TychoEncoder> {
|
pub fn get_tycho_router_encoder(user_transfer_type: UserTransferType) -> Box<dyn TychoEncoder> {
|
||||||
|
let executors_addresses = fs::read_to_string("config/test_executor_addresses.json").unwrap();
|
||||||
TychoRouterEncoderBuilder::new()
|
TychoRouterEncoderBuilder::new()
|
||||||
.chain(Chain::Ethereum)
|
.chain(Chain::Ethereum)
|
||||||
.user_transfer_type(user_transfer_type)
|
.user_transfer_type(user_transfer_type)
|
||||||
.executors_file_path("config/test_executor_addresses.json".to_string())
|
.executors_addresses(executors_addresses)
|
||||||
.router_address(router_address())
|
.router_address(router_address())
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to build encoder")
|
.expect("Failed to build encoder")
|
||||||
|
|||||||
Reference in New Issue
Block a user