Skip to content

Commit

Permalink
Unify networks and add Base support (#3091)
Browse files Browse the repository at this point in the history
# Description
Create a crate called `network` which unifies all the networks in the
whole codebase. The `network` crate is in fact an enum, which should be
always consumed in a non-exhaustive way, therefore, when adding a new
network, it will error in all the place it requires action.

This reduced duplicated code, and makes it easier to add a new network.
With this change, only `network` should contain reference to the real
`chain ID`.

Added `Base` support.

# Changes
- Create a new crate `network`
- Delete all duplicated code
- Make the new type `Network` as an `enun`, and replace it in the code
base in a non-exhaustive way, so it screams error when adding a new
network
- Add support for `Base`

## How to test
1. Unit tests
2. Regression tests
  • Loading branch information
m-lord-renkse authored Oct 31, 2024
1 parent 1182a6d commit d417d0b
Show file tree
Hide file tree
Showing 43 changed files with 426 additions and 318 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/autopilot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ bytes-hex = { path = "../bytes-hex" }
anyhow = { workspace = true }
async-trait = { workspace = true }
bigdecimal = { workspace = true }
chain = { path = "../chain" }
chrono = { workspace = true }
clap = { workspace = true }
contracts = { path = "../contracts" }
Expand Down
17 changes: 4 additions & 13 deletions crates/autopilot/src/domain/settlement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod auction;
mod observer;
mod trade;
mod transaction;
use chain::Chain;
pub use {auction::Auction, observer::Observer, trade::Trade, transaction::Transaction};

/// A settled transaction together with the `Auction`, for which it was executed
Expand Down Expand Up @@ -106,7 +107,7 @@ impl Settlement {
pub async fn new(
settled: Transaction,
persistence: &infra::Persistence,
chain: &infra::blockchain::Id,
chain: &Chain,
) -> Result<Self, Error> {
let auction = persistence.get_auction(settled.auction_id).await?;

Expand Down Expand Up @@ -138,23 +139,13 @@ impl Settlement {
}
}

const MAINNET_BLOCK_TIME: u64 = 13_000; // ms
const GNOSIS_BLOCK_TIME: u64 = 5_000; // ms
const SEPOLIA_BLOCK_TIME: u64 = 13_000; // ms
const ARBITRUM_ONE_BLOCK_TIME: u64 = 100; // ms

/// How old (in terms of blocks) a settlement should be, to be considered as a
/// settlement from another environment.
///
/// Currently set to ~6h
fn max_settlement_age(chain: &infra::blockchain::Id) -> u64 {
fn max_settlement_age(chain: &Chain) -> u64 {
const TARGET_AGE: u64 = 6 * 60 * 60 * 1000; // 6h in ms
match chain {
infra::blockchain::Id::Mainnet => TARGET_AGE / MAINNET_BLOCK_TIME,
infra::blockchain::Id::Gnosis => TARGET_AGE / GNOSIS_BLOCK_TIME,
infra::blockchain::Id::Sepolia => TARGET_AGE / SEPOLIA_BLOCK_TIME,
infra::blockchain::Id::ArbitrumOne => TARGET_AGE / ARBITRUM_ONE_BLOCK_TIME,
}
chain.blocks_in(TARGET_AGE).round() as u64
}

#[derive(Debug, thiserror::Error)]
Expand Down
10 changes: 4 additions & 6 deletions crates/autopilot/src/infra/blockchain/authenticator.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use {
crate::{
domain::{self, eth},
infra::blockchain::{
self,
contracts::{deployment_address, Contracts},
},
infra::blockchain::contracts::{deployment_address, Contracts},
},
chain::Chain,
ethcontract::{dyns::DynWeb3, GasPrice},
};

Expand All @@ -25,13 +23,13 @@ impl Manager {
/// Creates an authenticator which can remove solvers from the allow-list
pub async fn new(
web3: DynWeb3,
chain: blockchain::Id,
chain: &Chain,
contracts: Contracts,
authenticator_pk: eth::H256,
) -> Self {
let authenticator_role = contracts::Roles::at(
&web3,
deployment_address(contracts::Roles::raw_contract(), &chain).expect("roles address"),
deployment_address(contracts::Roles::raw_contract(), chain).expect("roles address"),
);

Self {
Expand Down
19 changes: 6 additions & 13 deletions crates/autopilot/src/infra/blockchain/contracts.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use {
crate::{domain, infra::blockchain},
ethcontract::dyns::DynWeb3,
primitive_types::H160,
};
use {crate::domain, chain::Chain, ethcontract::dyns::DynWeb3, primitive_types::H160};

#[derive(Debug, Clone)]
pub struct Contracts {
Expand All @@ -24,7 +20,7 @@ pub struct Addresses {
}

impl Contracts {
pub async fn new(web3: &DynWeb3, chain: &blockchain::Id, addresses: Addresses) -> Self {
pub async fn new(web3: &DynWeb3, chain: &Chain, addresses: Addresses) -> Self {
let address_for = |contract: &ethcontract::Contract, address: Option<H160>| {
address
.or_else(|| deployment_address(contract, chain))
Expand Down Expand Up @@ -100,14 +96,11 @@ impl Contracts {
}
}

/// Returns the address of a contract for the specified network, or `None` if
/// there is no known deployment for the contract on that network.
pub fn deployment_address(
contract: &ethcontract::Contract,
chain: &blockchain::Id,
) -> Option<H160> {
/// Returns the address of a contract for the specified chain, or `None` if
/// there is no known deployment for the contract on that chain.
pub fn deployment_address(contract: &ethcontract::Contract, chain: &Chain) -> Option<H160> {
contract
.networks
.get(chain.network_id())
.get(&chain.id().to_string())
.map(|network| network.address)
}
43 changes: 0 additions & 43 deletions crates/autopilot/src/infra/blockchain/id.rs

This file was deleted.

23 changes: 11 additions & 12 deletions crates/autopilot/src/infra/blockchain/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use {
self::contracts::Contracts,
crate::{boundary, domain::eth},
chain::Chain,
ethcontract::dyns::DynWeb3,
ethrpc::block_stream::CurrentBlockWatcher,
primitive_types::U256,
Expand All @@ -11,14 +12,11 @@ use {

pub mod authenticator;
pub mod contracts;
pub mod id;

pub use id::Id;

/// An Ethereum RPC connection.
pub struct Rpc {
web3: DynWeb3,
chain: Id,
chain: Chain,
url: Url,
}

Expand All @@ -30,7 +28,8 @@ impl Rpc {
ethrpc_args: &shared::ethrpc::Arguments,
) -> Result<Self, Error> {
let web3 = boundary::web3_client(url, ethrpc_args);
let chain = Id::new(web3.eth().chain_id().await?).map_err(|_| Error::UnsupportedChain)?;
let chain =
Chain::try_from(web3.eth().chain_id().await?).map_err(|_| Error::UnsupportedChain)?;

Ok(Self {
web3,
Expand All @@ -39,8 +38,8 @@ impl Rpc {
})
}

/// Returns the chain id for the RPC connection.
pub fn chain(&self) -> Id {
/// Returns the chain for the RPC connection.
pub fn chain(&self) -> Chain {
self.chain
}

Expand All @@ -59,7 +58,7 @@ impl Rpc {
#[derive(Clone)]
pub struct Ethereum {
web3: DynWeb3,
chain: Id,
chain: Chain,
current_block: CurrentBlockWatcher,
contracts: Contracts,
}
Expand All @@ -73,24 +72,24 @@ impl Ethereum {
/// any initialization error.
pub async fn new(
web3: DynWeb3,
chain: Id,
chain: &Chain,
url: Url,
addresses: contracts::Addresses,
poll_interval: Duration,
) -> Self {
let contracts = Contracts::new(&web3, &chain, addresses).await;
let contracts = Contracts::new(&web3, chain, addresses).await;

Self {
current_block: ethrpc::block_stream::current_block_stream(url, poll_interval)
.await
.expect("couldn't initialize current block stream"),
web3,
chain,
chain: *chain,
contracts,
}
}

pub fn chain(&self) -> &Id {
pub fn chain(&self) -> &Chain {
&self.chain
}

Expand Down
23 changes: 11 additions & 12 deletions crates/autopilot/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use {
shadow,
solvable_orders::SolvableOrdersCache,
},
chain::Chain,
clap::Parser,
contracts::{BalancerV2Vault, IUniswapV3Factory},
ethcontract::{dyns::DynWeb3, errors::DeployError, BlockNumber},
Expand Down Expand Up @@ -93,7 +94,7 @@ async fn ethrpc(url: &Url, ethrpc_args: &shared::ethrpc::Arguments) -> infra::bl

async fn ethereum(
web3: DynWeb3,
chain: infra::blockchain::Id,
chain: &Chain,
url: Url,
contracts: infra::blockchain::contracts::Addresses,
poll_interval: Duration,
Expand Down Expand Up @@ -165,7 +166,7 @@ pub async fn run(args: Arguments) {
};
let eth = ethereum(
web3.clone(),
chain,
&chain,
url,
contracts.clone(),
args.shared.current_block.block_stream_poll_interval,
Expand Down Expand Up @@ -197,12 +198,11 @@ pub async fn run(args: Arguments) {
other => Some(other.unwrap()),
};

let network_name = shared::network::network_name(chain_id);
let chain = Chain::try_from(chain_id).expect("incorrect chain ID");

let signature_validator = signature_validator::validator(
&web3,
signature_validator::Contracts {
chain_id,
settlement: eth.contracts().settlement().address(),
vault_relayer,
},
Expand All @@ -211,7 +211,6 @@ pub async fn run(args: Arguments) {
let balance_fetcher = account_balances::cached(
&web3,
account_balances::Contracts {
chain_id,
settlement: eth.contracts().settlement().address(),
vault_relayer,
vault: vault.as_ref().map(|contract| contract.address()),
Expand All @@ -230,10 +229,11 @@ pub async fn run(args: Arguments) {
.expect("failed to create gas price estimator"),
);

let baseline_sources = args.shared.baseline_sources.clone().unwrap_or_else(|| {
shared::sources::defaults_for_chain(chain_id)
.expect("failed to get default baseline sources")
});
let baseline_sources = args
.shared
.baseline_sources
.clone()
.unwrap_or_else(|| shared::sources::defaults_for_network(&chain));
tracing::info!(?baseline_sources, "using baseline sources");
let univ2_sources = baseline_sources
.iter()
Expand Down Expand Up @@ -261,7 +261,7 @@ pub async fn run(args: Arguments) {
let finder = token_owner_finder::init(
&args.token_owner_finder,
web3.clone(),
chain_id,
&chain,
&http_factory,
&pair_providers,
vault.as_ref(),
Expand Down Expand Up @@ -312,8 +312,7 @@ pub async fn run(args: Arguments) {
factory::Network {
web3: web3.clone(),
simulation_web3,
name: network_name.to_string(),
chain_id,
chain,
native_token: eth.contracts().weth().address(),
settlement: eth.contracts().settlement().address(),
authenticator: eth
Expand Down
Loading

0 comments on commit d417d0b

Please sign in to comment.