Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions bin/onlyswaps-solver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,39 @@ It is also possible to configure the solver with an external omnievent endpoint
[omnievent]
endpoint = "https://omnievent:3284"
```

## Initial setup
The current version of the solver relies on [Uniswap's permit2 contract](https://docs.uniswap.org/contracts/permit2/overview) for EIP-712 (i.e., gasless) token approvals for any ERC20 tokens.
This requires a one-time setup which consists of giving an unlimited token approval to the permit2 contract for each configured tokens.
Given that the contracts have been audited (see [here](https://github.com/Uniswap/permit2/tree/main/audits)), and have undergone public scrutiny for several years, the risk of an unlimited approval to permit2 is very low.

The initial setup can be done with the following command:
```bash
> cargo run -p onlyswaps-solver -- --config ./path/to/my/config.toml --private-key $PRIV setup
Loading app config from ./path/to/my/config.toml
The following allowances are required:
Chain Token Address Permit2
------------------------------------------------------------------------------------------
56 0x55d398326f99059fF775485246999027B3197955 Default
314 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045 Custom (0x1Ea2dBcB20263a969A017022E8B1C1dc13BD2470)
43114 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76 Default

Proceed? [y/n]: y
Sending txs...
> [Chain 56] sending approve for 0x55d398326f99059fF775485246999027B3197955...
> [Chain 314] sending approve for 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045...
> [Chain 43114] sending approve for 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76...
> [Chain 56] approval for 0x55d398326f99059fF775485246999027B3197955 sent successfully
> [Chain 43114] approval for 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76 sent successfully
> [Chain 314] approval for 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045 sent successfully

Transaction results:
Chain Token Address Result
------------------------------------------------------------------------------------------
56 0x55d398326f99059fF775485246999027B3197955 mined in 0xc1fc22d51f3130574da2c2501ed10aca986ab5e3a388b9f9d57717d630374d1c
314 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045 mined in 0xf2f206ed3439b80a43c08bfd042da99596f689cdc155243bea187e47f5cbeb5f
43114 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76 mined in 0x4044eadc976bdd4546649e41e573eca30786593969b1ca4582d713892a1e4134
```

After executing the command, the binary first checks which chain / token pairs require an approval, and ask for confirmation.
Upon acceptance, a transaction per chain / token pair is sent, and the result is displayed.
27 changes: 22 additions & 5 deletions bin/onlyswaps-solver/src/setup.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::network::Network;
use alloy::primitives::{Address, U160, U256, address};
use alloy::providers::{DynProvider, Provider};
use alloy::providers::{DynProvider, Provider, ProviderBuilder};
use anyhow::Context;
use futures::TryFutureExt;
use generated::onlyswaps::ierc20::IERC20::IERC20Instance;
use onlyswaps_client::client::OnlySwapsClient;
use std::collections::HashMap;
use std::io::{Write, stdin};
Expand All @@ -25,11 +26,21 @@ pub async fn setup_allowances(
.get(&chain_id)
.context("tried setting allowance for unknown chain??")?;

// all tokens on a network share the same provider
let Some(provider) = net.tokens.first().map(|t| t.provider()) else {
continue;
};
let provider = ProviderBuilder::new()
.disable_recommended_fillers()
.with_cached_nonce_management() // ensure the provider uses a cached nonce for concurrency
.connect_provider(provider);

for (amount, token) in details
.current_allowances
.into_iter()
.zip(net.tokens.iter())
{
let token_address = *token.address();
if amount > U256::from(U160::MAX) {
// we consider anything up to 2**160 a max allowance
continue;
Expand All @@ -43,9 +54,14 @@ pub async fn setup_allowances(

println!(
"{chain_id:<10} {:<44} {permit2_display}",
token.address().to_string(),
token_address.to_string(),
);
calls.push((chain_id, token, details.permit2_address));
calls.push((
chain_id,
IERC20Instance::new(token_address, provider.clone()),
details.permit2_address,
net.own_addr,
));
}
}

Expand All @@ -65,12 +81,13 @@ pub async fn setup_allowances(

println!("Sending txs...");
let results = futures::future::join_all(calls.into_iter().map(
async move |(chain_id, token, permit2_address)| {
async move |(chain_id, token, permit2_address, own_addr)| {
println!(
"> [Chain {chain_id}] sending approve for {}...",
token.address()
);
let approve = token.approve(permit2_address, U256::MAX);

let approve = token.approve(permit2_address, U256::MAX).from(own_addr);
let res = approve
.send()
.and_then(async move |tx_watch| Ok(tx_watch.watch().await?))
Expand Down
Loading