Skip to content

Commit

Permalink
Integrate gelato as external crate (#200)
Browse files Browse the repository at this point in the history
* wip: gelato

* feature: integrate gelato lib

* chore: lint and unused must use

* fix: a test that I broke :)

* refactor: integrate refactored gelato lib

* chore: changelog

* refactor: use builder pattern for forward request

* dep: relock with latest gelato-sdk

* fix: log the json string of the request body

* fix: re-lock
  • Loading branch information
prestwich authored Jun 24, 2022
1 parent 6145a38 commit 27dea0b
Show file tree
Hide file tree
Showing 20 changed files with 411 additions and 912 deletions.
624 changes: 330 additions & 294 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@ members = [
"tools/kms-cli",
"tools/nomad-cli",
"tools/balance-exporter",
"gelato-relay",
]
4 changes: 2 additions & 2 deletions agents/relayer/src/relayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ mod test {
use nomad_test::test_utils;
use std::collections::HashMap;
use tokio::time::{sleep, Duration};
use tokio_test::assert_err;

use super::*;

Expand Down Expand Up @@ -293,7 +292,8 @@ mod test {
<Relayer as nomad_base::NomadAgent>::run(agent.build_channel("moonbeam"))
.await
.expect("Couldn't join relayer's run task");
assert_err!(run_result, "Must have returned error");

assert!(run_result.is_err(), "Must have returned error");

let run_report_error_task = agent
.run_report_error(channel_name.to_string())
Expand Down
10 changes: 6 additions & 4 deletions agents/watcher/src/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -866,10 +866,12 @@ mod test {

// Second update_history call returns zero -> first update
// and should return WatcherError::SyncingFinished
history_sync
.update_history()
.await
.expect_err("Should have received WatcherError::SyncingFinished");
let res = history_sync.update_history().await;
assert_eq!(
res.unwrap_err().to_string(),
WatcherError::SyncingFinished.to_string(),
"Should have received WatcherError::SyncingFinished"
);

assert_eq!(history_sync.committed_root, zero_root);
assert_eq!(rx.recv().await.unwrap(), first_signed_update)
Expand Down
1 change: 1 addition & 0 deletions chains/nomad-ethereum/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

### Unreleased

- use gelato-sdk as a github dep rather than a crate
- adds a changelog
16 changes: 9 additions & 7 deletions chains/nomad-ethereum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ edition = "2021"
# Main block
serde = "1.0.120"
serde_json = { version = "1.0.61", default-features = false }
ethers = {git = "https://github.com/gakonst/ethers-rs", branch = "master", features = ["abigen"]}
ethers-core = {git = "https://github.com/gakonst/ethers-rs", branch = "master"}
ethers-providers = {git = "https://github.com/gakonst/ethers-rs", branch = "master"}
ethers-signers = {git = "https://github.com/gakonst/ethers-rs", branch = "master", features = ["aws"]}
ethers-contract = { git = "https://github.com/gakonst/ethers-rs", branch = "master", features=["legacy"] }
async-trait = { version = "0.1.42", default-features = false }
tracing = "0.1.22"
color-eyre = "0.5.0"
Expand All @@ -31,10 +26,17 @@ thiserror = "1.0.30"
reqwest = { version = "0.11.10", features = ["json"]}
once_cell = "1.8.0"

ethers = { git = "https://github.com/gakonst/ethers-rs", branch = "master", features = ["abigen"] }
ethers-core = { git = "https://github.com/gakonst/ethers-rs", branch = "master" }
ethers-providers = { git = "https://github.com/gakonst/ethers-rs", branch = "master" }
ethers-signers = { git = "https://github.com/gakonst/ethers-rs", branch = "master", features = ["aws"] }
ethers-contract = { git = "https://github.com/gakonst/ethers-rs", branch = "master", features=["legacy"] }

gelato-sdk = { git = "https://github.com/nomad-xyz/gelato-sdk", branch = "main" }

nomad-xyz-configuration = { path = "../../configuration" }
nomad-types = { path = "../../nomad-types" }
nomad-core = { path = "../../nomad-core" }
gelato-relay = { path = "../../gelato-relay" }

[build-dependencies]
ethers = {git = "https://github.com/gakonst/ethers-rs", branch = "master", features = ["abigen"]}
ethers = { git = "https://github.com/gakonst/ethers-rs", branch = "master", features = ["abigen"] }
4 changes: 2 additions & 2 deletions chains/nomad-ethereum/src/bindings/home.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use home_mod::*;
#[allow(clippy::too_many_arguments)]
mod home_mod {
#[allow(clippy::too_many_arguments, non_camel_case_types)]
pub mod home_mod {
#![allow(clippy::enum_variant_names)]
#![allow(dead_code)]
#![allow(clippy::type_complexity)]
Expand Down
4 changes: 2 additions & 2 deletions chains/nomad-ethereum/src/bindings/replica.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use replica_mod::*;
#[allow(clippy::too_many_arguments)]
mod replica_mod {
#[allow(clippy::too_many_arguments, non_camel_case_types)]
pub mod replica_mod {
#![allow(clippy::enum_variant_names)]
#![allow(dead_code)]
#![allow(clippy::type_complexity)]
Expand Down
4 changes: 2 additions & 2 deletions chains/nomad-ethereum/src/bindings/xappconnectionmanager.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use xappconnectionmanager_mod::*;
#[allow(clippy::too_many_arguments)]
mod xappconnectionmanager_mod {
#[allow(clippy::too_many_arguments, non_camel_case_types)]
pub mod xappconnectionmanager_mod {
#![allow(clippy::enum_variant_names)]
#![allow(dead_code)]
#![allow(clippy::type_complexity)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
use ethers::signers::Signer;
use ethers::types::transaction::eip2718::TypedTransaction;
use ethers::types::{Address, H256};
use ethers::{prelude::Bytes, providers::Middleware};
use gelato_relay::{GelatoClient, RelayResponse, TaskState};
use nomad_core::{ChainCommunicationError, Signers, TxOutcome};
use std::{str::FromStr, sync::Arc};
use ethers::{
prelude::{Address, Bytes, H256, U64},
providers::Middleware,
types::transaction::eip2718::TypedTransaction,
};
use gelato_sdk::{
get_forwarder,
rpc::{RelayResponse, TaskState},
FeeToken, ForwardRequestBuilder, GelatoClient,
};
use std::sync::Arc;
use tokio::task::JoinHandle;
use tokio::time::{sleep, Duration};
use tracing::info;
use utils::CHAIN_ID_TO_FORWARDER;

/// EIP-712 forward request structure
mod types;
pub use types::*;

pub mod utils;

pub(crate) const GAS_TANK_PAYMENT: usize = 1;
use nomad_core::{ChainCommunicationError, Signers, TxOutcome};

pub(crate) const ACCEPTABLE_STATES: [TaskState; 4] = [
TaskState::CheckPending,
Expand All @@ -37,9 +34,9 @@ pub struct SingleChainGelatoClient<M> {
/// Gelato relay forwarder address
pub forwarder: Address,
/// Chain id
pub chain_id: usize,
pub chain_id: u64,
/// Fee token
pub fee_token: String,
pub fee_token: FeeToken,
/// Transactions are of high priority
pub is_high_priority: bool,
}
Expand All @@ -57,19 +54,17 @@ where
pub fn with_default_url(
eth_client: Arc<M>,
sponsor: Signers,
chain_id: usize,
fee_token: String,
chain_id: u64,
fee_token: impl Into<FeeToken>,
is_high_priority: bool,
) -> Self {
Self {
gelato: GelatoClient::default().into(),
eth_client,
sponsor,
forwarder: *CHAIN_ID_TO_FORWARDER
.get(&chain_id)
.expect("!forwarder proxy"),
forwarder: get_forwarder(chain_id).expect("!forwarder proxy"),
chain_id,
fee_token,
fee_token: fee_token.into(),
is_high_priority,
}
}
Expand All @@ -81,7 +76,10 @@ where
contract_address: Address,
tx: &TypedTransaction,
) -> Result<TxOutcome, ChainCommunicationError> {
let RelayResponse { task_id } = self.dispatch_tx(domain, contract_address, tx).await?;
let task_id = self
.dispatch_tx(domain, contract_address, tx)
.await?
.task_id();

info!(task_id = ?&task_id, "Submitted tx to Gelato relay.");

Expand All @@ -108,8 +106,9 @@ where
.await
.map_err(|e| ChainCommunicationError::MiddlewareError(e.into()))?,
)
.as_usize();
let data = tx.data().expect("!tx data");
.as_u64()
.into();
let data = tx.data().cloned().unwrap_or_default();

info!(
domain = domain,
Expand All @@ -126,14 +125,14 @@ where
/// otherwise.
pub fn poll_task_id(
&self,
task_id: String,
task_id: H256,
) -> JoinHandle<Result<TxOutcome, ChainCommunicationError>> {
let gelato = self.gelato();

tokio::spawn(async move {
loop {
let status = gelato
.get_task_status(&task_id)
.get_task_status(task_id)
.await
.map_err(|e| ChainCommunicationError::TxSubmissionError(e.into()))?
.expect("!task status");
Expand All @@ -152,9 +151,7 @@ where
"Gelato relay executed tx."
);

let tx_hash = &execution.transaction_hash;
let txid = H256::from_str(tx_hash)
.unwrap_or_else(|_| panic!("Malformed tx hash from Gelato"));
let txid = execution.transaction_hash;

return Ok(TxOutcome { txid });
}
Expand All @@ -169,51 +166,44 @@ where
}

/// Format and sign forward request, then dispatch to Gelato relay service.
///
/// This function pads gas by 100k to allow for gelato ops
pub async fn send_forward_request(
&self,
target: Address,
data: &Bytes,
gas_limit: usize,
data: impl Into<Bytes>,
gas_limit: U64,
) -> Result<RelayResponse, ChainCommunicationError> {
// add 100k gas padding for Gelato contract ops
let adjusted_limit = gas_limit + U64::from(100_000);

let max_fee = self
.gelato()
.get_estimated_fee(self.chain_id, &self.fee_token, gas_limit + 100_000, false)
.get_estimated_fee(self.chain_id, self.fee_token, adjusted_limit, false)
.await
.map_err(|e| ChainCommunicationError::CustomError(e.into()))?; // add 100k gas padding for Gelato contract ops

let target = format!("{:#x}", target);
let sponsor = format!("{:#x}", self.sponsor.address());
let data = data.to_string().strip_prefix("0x").unwrap().to_owned();

let unfilled_request = UnfilledForwardRequest {
chain_id: self.chain_id,
target,
data,
fee_token: self.fee_token.to_owned(),
payment_type: GAS_TANK_PAYMENT, // gas tank
max_fee,
gas: gas_limit,
sponsor,
sponsor_chain_id: self.chain_id,
nonce: 0, // default, not needed
enforce_sponsor_nonce: false, // replay safety builtin to contracts
enforce_sponsor_nonce_ordering: false,
};

info!(request = ?unfilled_request, "Signing gelato forward request.");

let sponsor_signature = self
.sponsor
.sign_typed_data(&unfilled_request)
.map_err(|e| ChainCommunicationError::CustomError(e.into()))?;

let request = ForwardRequestBuilder::default()
.chain_id(self.chain_id)
.target(target)
.data(data.into())
.fee_token(self.fee_token)
.max_fee(max_fee)
.gas(gas_limit)
.sponsored_by(&self.sponsor)
.sponsor_chain_id(self.chain_id)
.enforce_sponsor_nonce(false)
.build()
.await
.unwrap();

let filled_request = unfilled_request.into_filled(sponsor_signature.to_vec());
.expect("signer doesn't fail");

info!(request = ?filled_request, "Signed gelato forward request.");
info!(
request = serde_json::to_string(&request).unwrap().as_str(),
"Signed gelato forward request."
);

self.gelato()
.send_forward_request(&filled_request)
.send_forward_request(&request)
.await
.map_err(|e| ChainCommunicationError::TxSubmissionError(e.into()))
}
Expand Down
Loading

0 comments on commit 27dea0b

Please sign in to comment.