Skip to content

Commit 44601cb

Browse files
azixusAnomalRoil
andauthored
fix(solver/setup): update setup & docs (#251)
* fix(solver/setup): use cached nonce to handle concurrent txs * docs(solver): add setup explanation --------- Co-authored-by: AnomalRoil <AnomalRoil@users.noreply.github.com>
1 parent d894ff0 commit 44601cb

2 files changed

Lines changed: 58 additions & 5 deletions

File tree

bin/onlyswaps-solver/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,39 @@ It is also possible to configure the solver with an external omnievent endpoint
4949
[omnievent]
5050
endpoint = "https://omnievent:3284"
5151
```
52+
53+
## Initial setup
54+
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.
55+
This requires a one-time setup which consists of giving an unlimited token approval to the permit2 contract for each configured tokens.
56+
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.
57+
58+
The initial setup can be done with the following command:
59+
```bash
60+
> cargo run -p onlyswaps-solver -- --config ./path/to/my/config.toml --private-key $PRIV setup
61+
Loading app config from ./path/to/my/config.toml
62+
The following allowances are required:
63+
Chain Token Address Permit2
64+
------------------------------------------------------------------------------------------
65+
56 0x55d398326f99059fF775485246999027B3197955 Default
66+
314 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045 Custom (0x1Ea2dBcB20263a969A017022E8B1C1dc13BD2470)
67+
43114 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76 Default
68+
69+
Proceed? [y/n]: y
70+
Sending txs...
71+
> [Chain 56] sending approve for 0x55d398326f99059fF775485246999027B3197955...
72+
> [Chain 314] sending approve for 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045...
73+
> [Chain 43114] sending approve for 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76...
74+
> [Chain 56] approval for 0x55d398326f99059fF775485246999027B3197955 sent successfully
75+
> [Chain 43114] approval for 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76 sent successfully
76+
> [Chain 314] approval for 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045 sent successfully
77+
78+
Transaction results:
79+
Chain Token Address Result
80+
------------------------------------------------------------------------------------------
81+
56 0x55d398326f99059fF775485246999027B3197955 mined in 0xc1fc22d51f3130574da2c2501ed10aca986ab5e3a388b9f9d57717d630374d1c
82+
314 0x80B98d3aa09ffff255c3ba4A241111Ff1262F045 mined in 0xf2f206ed3439b80a43c08bfd042da99596f689cdc155243bea187e47f5cbeb5f
83+
43114 0x1b0F6cF6f3185872a581BD2B5a738EB52CCd4d76 mined in 0x4044eadc976bdd4546649e41e573eca30786593969b1ca4582d713892a1e4134
84+
```
85+
86+
After executing the command, the binary first checks which chain / token pairs require an approval, and ask for confirmation.
87+
Upon acceptance, a transaction per chain / token pair is sent, and the result is displayed.

bin/onlyswaps-solver/src/setup.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use crate::network::Network;
22
use alloy::primitives::{Address, U160, U256, address};
3-
use alloy::providers::{DynProvider, Provider};
3+
use alloy::providers::{DynProvider, Provider, ProviderBuilder};
44
use anyhow::Context;
55
use futures::TryFutureExt;
6+
use generated::onlyswaps::ierc20::IERC20::IERC20Instance;
67
use onlyswaps_client::client::OnlySwapsClient;
78
use std::collections::HashMap;
89
use std::io::{Write, stdin};
@@ -25,11 +26,21 @@ pub async fn setup_allowances(
2526
.get(&chain_id)
2627
.context("tried setting allowance for unknown chain??")?;
2728

29+
// all tokens on a network share the same provider
30+
let Some(provider) = net.tokens.first().map(|t| t.provider()) else {
31+
continue;
32+
};
33+
let provider = ProviderBuilder::new()
34+
.disable_recommended_fillers()
35+
.with_cached_nonce_management() // ensure the provider uses a cached nonce for concurrency
36+
.connect_provider(provider);
37+
2838
for (amount, token) in details
2939
.current_allowances
3040
.into_iter()
3141
.zip(net.tokens.iter())
3242
{
43+
let token_address = *token.address();
3344
if amount > U256::from(U160::MAX) {
3445
// we consider anything up to 2**160 a max allowance
3546
continue;
@@ -43,9 +54,14 @@ pub async fn setup_allowances(
4354

4455
println!(
4556
"{chain_id:<10} {:<44} {permit2_display}",
46-
token.address().to_string(),
57+
token_address.to_string(),
4758
);
48-
calls.push((chain_id, token, details.permit2_address));
59+
calls.push((
60+
chain_id,
61+
IERC20Instance::new(token_address, provider.clone()),
62+
details.permit2_address,
63+
net.own_addr,
64+
));
4965
}
5066
}
5167

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

6682
println!("Sending txs...");
6783
let results = futures::future::join_all(calls.into_iter().map(
68-
async move |(chain_id, token, permit2_address)| {
84+
async move |(chain_id, token, permit2_address, own_addr)| {
6985
println!(
7086
"> [Chain {chain_id}] sending approve for {}...",
7187
token.address()
7288
);
73-
let approve = token.approve(permit2_address, U256::MAX);
89+
90+
let approve = token.approve(permit2_address, U256::MAX).from(own_addr);
7491
let res = approve
7592
.send()
7693
.and_then(async move |tx_watch| Ok(tx_watch.watch().await?))

0 commit comments

Comments
 (0)