From 8f4c8194e6258b3a490d25fb63659c51a5eee779 Mon Sep 17 00:00:00 2001 From: kafeikui Date: Fri, 10 Nov 2023 10:18:10 +0800 Subject: [PATCH] estimate and set EIP1559 gas price when sending transactions --- crates/arpa-node/src/node_shell.rs | 25 +++++++++++++------ crates/contract-client/src/error.rs | 13 +++------- crates/contract-client/src/ethers/adapter.rs | 9 ++++--- .../contract-client/src/ethers/controller.rs | 9 ++++--- .../src/ethers/controller_oracle.rs | 7 +++--- .../src/ethers/controller_relayer.rs | 7 +++--- .../contract-client/src/ethers/coordinator.rs | 13 +++++----- crates/contract-client/src/lib.rs | 15 +++++++++-- crates/core/src/types/identity/mod.rs | 2 +- crates/core/src/types/identity/types.rs | 10 ++++---- crates/user-cli/src/user_shell.rs | 12 +++++++++ 11 files changed, 77 insertions(+), 45 deletions(-) diff --git a/crates/arpa-node/src/node_shell.rs b/crates/arpa-node/src/node_shell.rs index 9e1cad5a..439a00c8 100644 --- a/crates/arpa-node/src/node_shell.rs +++ b/crates/arpa-node/src/node_shell.rs @@ -9,7 +9,7 @@ use arpa_contract_client::ethers::controller_oracle::ControllerOracleClient; use arpa_contract_client::{ServiceClient, TransactionCaller, ViewCaller}; use arpa_core::{ address_to_string, build_wallet_from_config, pad_to_bytes32, Config, ConfigError, - GeneralMainChainIdentity, GeneralRelayedChainIdentity, WalletSigner, + GeneralMainChainIdentity, GeneralRelayedChainIdentity, WsWalletSigner, DEFAULT_WEBSOCKET_PROVIDER_RECONNECT_TIMES, }; use arpa_dal::NodeInfoFetcher; @@ -193,6 +193,7 @@ async fn send( let trx_hash = ArpaClient::call_contract_transaction( main_chain_id, "approve-arpa-to-staking", + arpa_contract.client_ref(), arpa_contract.approve(context.staking_contract_address().await?, amount), context .config @@ -278,6 +279,7 @@ async fn send( let trx_hash = StakingClient::call_contract_transaction( main_chain_id, "stake", + staking_contract.client_ref(), staking_contract.stake(amount), context .config @@ -322,6 +324,7 @@ async fn send( let trx_hash = StakingClient::call_contract_transaction( main_chain_id, "unstake", + staking_contract.client_ref(), staking_contract.unstake(amount), context .config @@ -346,6 +349,7 @@ async fn send( let trx_hash = StakingClient::call_contract_transaction( main_chain_id, "claim_frozen_principal", + staking_contract.client_ref(), staking_contract.claim_frozen_principal(), context .config @@ -410,6 +414,7 @@ async fn send( let trx_hash = ControllerClient::call_contract_transaction( main_chain_id, "node_activate", + controller_contract.client_ref(), controller_contract.node_activate(), context .config @@ -442,6 +447,7 @@ async fn send( let trx_hash = ControllerClient::call_contract_transaction( main_chain_id, "node_quit", + controller_contract.client_ref(), controller_contract.node_quit(), context .config @@ -484,6 +490,7 @@ async fn send( let trx_hash = ControllerClient::call_contract_transaction( main_chain_id, "change_dkg_public_key", + controller_contract.client_ref(), controller_contract .change_dkg_public_key(bincode::serialize(&dkg_public_key)?.into()), context @@ -523,6 +530,7 @@ async fn send( let trx_hash = ControllerClient::call_contract_transaction( *chain_id, "node_withdraw", + controller_contract.client_ref(), controller_contract.node_withdraw(recipient), context .config @@ -546,6 +554,7 @@ async fn send( let trx_hash = ControllerOracleClient::call_contract_transaction( *chain_id, "node_withdraw", + controller_oracle_contract.client_ref(), controller_oracle_contract.node_withdraw(recipient), context .config @@ -929,7 +938,7 @@ async fn call( .build_adapter_client(context.wallet.address()); let adapter_contract = - ServiceClient::>::prepare_service_client(&client) + ServiceClient::>::prepare_service_client(&client) .await?; let filter = adapter_contract @@ -972,7 +981,7 @@ async fn call( .build_adapter_client(context.chain_identity(*chain_id)?.get_id_address()); let adapter_contract = - ServiceClient::>::prepare_service_client(&client) + ServiceClient::>::prepare_service_client(&client) .await?; let filter = adapter_contract @@ -1127,7 +1136,7 @@ async fn call( .build_adapter_client(context.wallet.address()); let adapter_contract = - ServiceClient::>::prepare_service_client(&client) + ServiceClient::>::prepare_service_client(&client) .await?; let ( @@ -1167,7 +1176,7 @@ async fn call( .build_adapter_client(context.wallet.address()); let adapter_contract = - ServiceClient::>::prepare_service_client(&client) + ServiceClient::>::prepare_service_client(&client) .await?; let last_assigned_group_index = AdapterClient::call_contract_view( @@ -1191,7 +1200,7 @@ async fn call( .build_adapter_client(context.wallet.address()); let adapter_contract = - ServiceClient::>::prepare_service_client(&client) + ServiceClient::>::prepare_service_client(&client) .await?; let randomness_count = AdapterClient::call_contract_view( @@ -1290,7 +1299,7 @@ async fn call( .build_adapter_client(context.wallet.address()); let adapter_contract = - ServiceClient::>::prepare_service_client(&client) + ServiceClient::>::prepare_service_client(&client) .await?; let ( @@ -1325,7 +1334,7 @@ async fn call( .build_adapter_client(context.wallet.address()); let adapter_contract = - ServiceClient::>::prepare_service_client(&client) + ServiceClient::>::prepare_service_client(&client) .await?; let r_id = sub_matches.get_one::("request-id").unwrap(); diff --git a/crates/contract-client/src/error.rs b/crates/contract-client/src/error.rs index b06d1fd2..f3496658 100644 --- a/crates/contract-client/src/error.rs +++ b/crates/contract-client/src/error.rs @@ -1,10 +1,5 @@ -use arpa_core::{HttpWalletSigner, WalletSigner}; -use ethers::providers::Http as HttpProvider; -use ethers::{ - prelude::{signer::SignerMiddlewareError, ContractError, ProviderError}, - providers::Provider, - signers::LocalWallet, -}; +use arpa_core::{HttpWalletSigner, WsWalletSigner}; +use ethers::prelude::{ContractError, ProviderError}; use rustc_hex::FromHexError; use thiserror::Error; @@ -19,12 +14,10 @@ pub enum ContractClientError { #[error(transparent)] ChainProviderError(#[from] ProviderError), #[error(transparent)] - ContractError(#[from] ContractError), + WsContractError(#[from] ContractError), #[error(transparent)] HttpContractError(#[from] ContractError), #[error(transparent)] - SignerError(#[from] SignerMiddlewareError, LocalWallet>), - #[error(transparent)] AddressParseError(#[from] FromHexError), #[error("can't fetch new block, please check provider")] FetchingBlockError, diff --git a/crates/contract-client/src/ethers/adapter.rs b/crates/contract-client/src/ethers/adapter.rs index fb3a9bdd..7dcfd7dc 100644 --- a/crates/contract-client/src/ethers/adapter.rs +++ b/crates/contract-client/src/ethers/adapter.rs @@ -10,7 +10,7 @@ use crate::{ use arpa_core::{ pad_to_bytes32, ChainIdentity, ExponentialBackoffRetryDescriptor, GeneralMainChainIdentity, GeneralRelayedChainIdentity, PartialSignature, RandomnessRequestType, RandomnessTask, - WalletSigner, DEFAULT_MINIMUM_THRESHOLD, FULFILL_RANDOMNESS_GAS_EXCEPT_CALLBACK, + WsWalletSigner, DEFAULT_MINIMUM_THRESHOLD, FULFILL_RANDOMNESS_GAS_EXCEPT_CALLBACK, RANDOMNESS_REWARD_GAS, VERIFICATION_GAS_OVER_MINIMUM_THRESHOLD, }; use async_trait::async_trait; @@ -23,7 +23,7 @@ pub struct AdapterClient { chain_id: usize, main_id_address: Address, adapter_address: Address, - signer: Arc, + signer: Arc, contract_transaction_retry_descriptor: ExponentialBackoffRetryDescriptor, contract_view_retry_descriptor: ExponentialBackoffRetryDescriptor, } @@ -33,7 +33,7 @@ impl AdapterClient { chain_id: usize, main_id_address: Address, adapter_address: Address, - signer: Arc, + signer: Arc, contract_transaction_retry_descriptor: ExponentialBackoffRetryDescriptor, contract_view_retry_descriptor: ExponentialBackoffRetryDescriptor, ) -> Self { @@ -78,7 +78,7 @@ impl AdapterClientBuilder for GeneralRelayedChainIdentity { } } -type AdapterContract = Adapter; +type AdapterContract = Adapter; #[async_trait] impl ServiceClient for AdapterClient { @@ -151,6 +151,7 @@ impl AdapterTransactions for AdapterClient { AdapterClient::call_contract_transaction( self.chain_id, "fulfill_randomness", + adapter_contract.client_ref(), call.gas( task.callback_gas_limit + FULFILL_RANDOMNESS_GAS_EXCEPT_CALLBACK diff --git a/crates/contract-client/src/ethers/controller.rs b/crates/contract-client/src/ethers/controller.rs index 16f7cc0a..15332463 100644 --- a/crates/contract-client/src/ethers/controller.rs +++ b/crates/contract-client/src/ethers/controller.rs @@ -12,7 +12,7 @@ use crate::{TransactionCaller, ViewCaller}; use arpa_core::{ u256_to_vec, ChainIdentity, DKGTask, ExponentialBackoffRetryDescriptor, GeneralMainChainIdentity, GeneralRelayedChainIdentity, Group, MainChainIdentity, Member, Node, - WalletSigner, + WsWalletSigner, }; use async_trait::async_trait; use ethers::prelude::*; @@ -25,7 +25,7 @@ use threshold_bls::group::Curve; pub struct ControllerClient { chain_id: usize, controller_address: Address, - signer: Arc, + signer: Arc, contract_transaction_retry_descriptor: ExponentialBackoffRetryDescriptor, contract_view_retry_descriptor: ExponentialBackoffRetryDescriptor, } @@ -70,7 +70,7 @@ impl ControllerClientBuilder for GeneralRelayedChainIdentity { } } -type ControllerContract = Controller; +type ControllerContract = Controller; #[async_trait] impl ServiceClient for ControllerClient { @@ -98,6 +98,7 @@ impl ControllerTransactions for ControllerClient { ControllerClient::call_contract_transaction( self.chain_id, "node_register", + controller_contract.client_ref(), call, self.contract_transaction_retry_descriptor, true, @@ -127,6 +128,7 @@ impl ControllerTransactions for ControllerClient { ControllerClient::call_contract_transaction( self.chain_id, "commit_dkg", + controller_contract.client_ref(), call, self.contract_transaction_retry_descriptor, true, @@ -147,6 +149,7 @@ impl ControllerTransactions for ControllerClient { ControllerClient::call_contract_transaction( self.chain_id, "post_process_dkg", + controller_contract.client_ref(), call, self.contract_transaction_retry_descriptor, false, diff --git a/crates/contract-client/src/ethers/controller_oracle.rs b/crates/contract-client/src/ethers/controller_oracle.rs index 80b7f6e5..d5e9fe7f 100644 --- a/crates/contract-client/src/ethers/controller_oracle.rs +++ b/crates/contract-client/src/ethers/controller_oracle.rs @@ -8,7 +8,7 @@ use crate::{ use crate::{TransactionCaller, ViewCaller}; use arpa_core::{ u256_to_vec, ChainIdentity, ExponentialBackoffRetryDescriptor, GeneralMainChainIdentity, - GeneralRelayedChainIdentity, Group, Member, RelayedChainIdentity, WalletSigner, + GeneralRelayedChainIdentity, Group, Member, RelayedChainIdentity, WsWalletSigner, }; use async_trait::async_trait; use ethers::prelude::*; @@ -20,7 +20,7 @@ use threshold_bls::group::Curve; pub struct ControllerOracleClient { chain_id: usize, controller_oracle_address: Address, - signer: Arc, + signer: Arc, contract_transaction_retry_descriptor: ExponentialBackoffRetryDescriptor, contract_view_retry_descriptor: ExponentialBackoffRetryDescriptor, } @@ -65,7 +65,7 @@ impl ControllerOracleClientBuilder for GeneralRelayedChainIdentity } } -type ControllerOracleContract = ControllerOracle; +type ControllerOracleContract = ControllerOracle; #[async_trait] impl ServiceClient for ControllerOracleClient { @@ -94,6 +94,7 @@ impl ControllerOracleTransactions for ControllerOracleClient { ControllerOracleClient::call_contract_transaction( self.chain_id, "node_withdraw", + controller_oracle_contract.client_ref(), call, self.contract_transaction_retry_descriptor, true, diff --git a/crates/contract-client/src/ethers/controller_relayer.rs b/crates/contract-client/src/ethers/controller_relayer.rs index 9121adfd..90eb1f8c 100644 --- a/crates/contract-client/src/ethers/controller_relayer.rs +++ b/crates/contract-client/src/ethers/controller_relayer.rs @@ -6,7 +6,7 @@ use crate::{ }; use arpa_core::{ ChainIdentity, ExponentialBackoffRetryDescriptor, GeneralMainChainIdentity, - GeneralRelayedChainIdentity, MainChainIdentity, WalletSigner, + GeneralRelayedChainIdentity, MainChainIdentity, WsWalletSigner, }; use async_trait::async_trait; use ethers::prelude::*; @@ -15,7 +15,7 @@ use std::sync::Arc; pub struct ControllerRelayerClient { chain_id: usize, controller_relayer_address: Address, - signer: Arc, + signer: Arc, contract_transaction_retry_descriptor: ExponentialBackoffRetryDescriptor, } @@ -56,7 +56,7 @@ impl ControllerRelayerClientBuilder for GeneralRelayedChainIdentity { } } -type ControllerRelayerContract = ControllerRelayer; +type ControllerRelayerContract = ControllerRelayer; #[async_trait] impl ServiceClient for ControllerRelayerClient { @@ -82,6 +82,7 @@ impl ControllerRelayerTransactions for ControllerRelayerClient { ControllerRelayerClient::call_contract_transaction( self.chain_id, "relay_group", + controller_relayer_contract.client_ref(), call, self.contract_transaction_retry_descriptor, false, diff --git a/crates/contract-client/src/ethers/coordinator.rs b/crates/contract-client/src/ethers/coordinator.rs index 4a526484..a620fca1 100644 --- a/crates/contract-client/src/ethers/coordinator.rs +++ b/crates/contract-client/src/ethers/coordinator.rs @@ -9,7 +9,7 @@ use crate::{ use ::core::panic; use arpa_core::{ ChainIdentity, ExponentialBackoffRetryDescriptor, GeneralMainChainIdentity, - GeneralRelayedChainIdentity, WalletSigner, + GeneralRelayedChainIdentity, WsWalletSigner, }; use async_trait::async_trait; use dkg_core::{ @@ -24,7 +24,7 @@ use threshold_bls::group::Curve; pub struct CoordinatorClient { chain_id: usize, coordinator_address: Address, - signer: Arc, + signer: Arc, contract_transaction_retry_descriptor: ExponentialBackoffRetryDescriptor, contract_view_retry_descriptor: ExponentialBackoffRetryDescriptor, } @@ -69,7 +69,7 @@ impl CoordinatorClientBuilder for GeneralRelayedChainIden } } -type CoordinatorContract = Coordinator; +type CoordinatorContract = Coordinator; #[async_trait] impl ServiceClient for CoordinatorClient { @@ -97,6 +97,7 @@ impl CoordinatorTransactions for CoordinatorClient { CoordinatorClient::call_contract_transaction( self.chain_id, "publish", + coordinator_contract.client_ref(), call, self.contract_transaction_retry_descriptor, false, @@ -225,7 +226,7 @@ impl BoardPublisher for CoordinatorClient { #[cfg(test)] pub mod coordinator_tests { - use super::{CoordinatorClient, WalletSigner}; + use super::{CoordinatorClient, WsWalletSigner}; use crate::contract_stub::coordinator::Coordinator; use crate::coordinator::CoordinatorTransactions; use crate::error::ContractClientError; @@ -257,7 +258,7 @@ pub mod coordinator_tests { Anvil::new().chain_id(1u64).mnemonic(PHRASE).spawn() } - async fn deploy_contract(anvil: &AnvilInstance) -> Coordinator { + async fn deploy_contract(anvil: &AnvilInstance) -> Coordinator { // 2. instantiate our wallet let wallet: LocalWallet = anvil.keys()[0].clone().into(); @@ -357,7 +358,7 @@ pub mod coordinator_tests { let res = client.publish(mock_value.clone()).await; assert!(res.is_err()); - if let ContractClientError::ContractError(Revert(bytes)) = res.unwrap_err() { + if let ContractClientError::WsContractError(Revert(bytes)) = res.unwrap_err() { let error_msg = String::decode_with_selector(&bytes).unwrap(); assert_eq!("share existed", error_msg); } else { diff --git a/crates/contract-client/src/lib.rs b/crates/contract-client/src/lib.rs index a6f9d6e3..9b002372 100644 --- a/crates/contract-client/src/lib.rs +++ b/crates/contract-client/src/lib.rs @@ -4,7 +4,7 @@ use ::ethers::prelude::ContractError; use ::ethers::providers::Middleware; use ::ethers::types::U64; use ::ethers::{prelude::builders::ContractCall, types::H256}; -use arpa_core::{jitter, ExponentialBackoffRetryDescriptor}; +use arpa_core::{eip1559_gas_price_estimator, jitter, ExponentialBackoffRetryDescriptor}; use async_trait::async_trait; use error::ContractClientResult; use log::{error, info}; @@ -28,7 +28,8 @@ pub trait TransactionCaller { >( chain_id: usize, info: &str, - call: ContractCall, + client: &M, + mut call: ContractCall, contract_transaction_retry_descriptor: ExponentialBackoffRetryDescriptor, retry_on_transaction_fail: bool, ) -> ContractClientResult @@ -47,6 +48,16 @@ pub trait TransactionCaller { }) .take(contract_transaction_retry_descriptor.max_attempts); + // set gas price for EIP-1559 trxs + if let Some(tx) = call.tx.as_eip1559_mut() { + let (max_fee, max_priority_fee) = client + .estimate_eip1559_fees(Some(eip1559_gas_price_estimator)) + .await + .map_err(ContractError::from_middleware_error)?; + tx.max_fee_per_gas = Some(max_fee); + tx.max_priority_fee_per_gas = Some(max_priority_fee); + } + let transaction_hash = RetryIf::spawn( retry_strategy, || async { diff --git a/crates/core/src/types/identity/mod.rs b/crates/core/src/types/identity/mod.rs index 5a919d54..3b4ea4b7 100644 --- a/crates/core/src/types/identity/mod.rs +++ b/crates/core/src/types/identity/mod.rs @@ -16,7 +16,7 @@ pub trait ChainIdentity { fn get_adapter_address(&self) -> Address; - fn get_signer(&self) -> Arc; + fn get_signer(&self) -> Arc; fn get_contract_transaction_retry_descriptor(&self) -> ExponentialBackoffRetryDescriptor; diff --git a/crates/core/src/types/identity/types.rs b/crates/core/src/types/identity/types.rs index 52ee37f9..4ef8a65e 100644 --- a/crates/core/src/types/identity/types.rs +++ b/crates/core/src/types/identity/types.rs @@ -11,14 +11,14 @@ use ethers_providers::{Http, Middleware, Provider, ProviderError, Ws}; use ethers_signers::{LocalWallet, Signer}; use std::sync::Arc; -pub type WalletSigner = SignerMiddleware>>, LocalWallet>; +pub type WsWalletSigner = SignerMiddleware>>, LocalWallet>; pub type HttpWalletSigner = SignerMiddleware>>, LocalWallet>; #[derive(Debug, Clone)] pub struct GeneralMainChainIdentity { chain_id: usize, - signer: Arc, + signer: Arc, provider_endpoint: String, controller_address: Address, controller_relayer_address: Address, @@ -74,7 +74,7 @@ impl ChainIdentity for GeneralMainChainIdentity { self.adapter_address } - fn get_signer(&self) -> Arc { + fn get_signer(&self) -> Arc { self.signer.clone() } @@ -155,7 +155,7 @@ impl ChainProviderManager for GeneralMainChainIdentity { #[derive(Debug, Clone)] pub struct GeneralRelayedChainIdentity { chain_id: usize, - signer: Arc, + signer: Arc, provider_endpoint: String, controller_oracle_address: Address, adapter_address: Address, @@ -208,7 +208,7 @@ impl ChainIdentity for GeneralRelayedChainIdentity { self.adapter_address } - fn get_signer(&self) -> Arc { + fn get_signer(&self) -> Arc { self.signer.clone() } diff --git a/crates/user-cli/src/user_shell.rs b/crates/user-cli/src/user_shell.rs index 53059749..cf06162a 100644 --- a/crates/user-cli/src/user_shell.rs +++ b/crates/user-cli/src/user_shell.rs @@ -199,6 +199,7 @@ async fn send(args: ArgMatches, context: &mut Context) -> anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result anyhow::Result