From f636d6c9a852690c88bcf5d6b8f3f6678015837a Mon Sep 17 00:00:00 2001 From: nanocryk <6422796+nanocryk@users.noreply.github.com> Date: Wed, 24 Aug 2022 08:22:02 +0200 Subject: [PATCH] allow to adapt an estimate_gas request (#738) --- client/rpc/src/eth/execute.rs | 24 +++++++++++++++++++++++- client/rpc/src/eth/mod.rs | 5 +++-- client/rpc/src/lib.rs | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/client/rpc/src/eth/execute.rs b/client/rpc/src/eth/execute.rs index 46190de67c24..f9888c23e773 100644 --- a/client/rpc/src/eth/execute.rs +++ b/client/rpc/src/eth/execute.rs @@ -45,7 +45,25 @@ use crate::{ /// Default JSONRPC error code return by geth pub const JSON_RPC_ERROR_DEFAULT: i32 = -32000; -impl Eth +/// Allow to adapt a request for `estimate_gas`. +/// Can be used to estimate gas of some contracts using a different function +/// in the case the normal gas estimation doesn't work. +/// +/// Exemple: a precompile that tries to do a subcall but succeeds regardless of the +/// success of the subcall. The gas estimation will thus optimize the gas limit down +/// to the minimum, while we want to estimate a gas limit that will allow the subcall to +/// have enough gas to succeed. +pub trait EstimateGasAdapter { + fn adapt_request(request: CallRequest) -> CallRequest; +} + +impl EstimateGasAdapter for () { + fn adapt_request(request: CallRequest) -> CallRequest { + request + } +} + +impl Eth where B: BlockT + Send + Sync + 'static, C: ProvideRuntimeApi + StorageProvider, @@ -54,6 +72,7 @@ where BE: Backend + 'static, BE::State: StateBackend, A: ChainApi + 'static, + EGA: EstimateGasAdapter, { pub fn call(&self, request: CallRequest, number: Option) -> Result { let CallRequest { @@ -301,6 +320,9 @@ where // Get best hash (TODO missing support for estimating gas historically) let best_hash = client.info().best_hash; + // Adapt request for gas estimation. + let request = EGA::adapt_request(request); + // For simple transfer to simple account, return MIN_GAS_PER_TX directly let is_simple_transfer = match &request.data { None => true, diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index da897b6261f1..d5a8e3f2fd53 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -54,11 +54,12 @@ use crate::{internal_err, overrides::OverrideHandle, public_key, signer::EthSign pub use self::{ cache::{EthBlockDataCacheTask, EthTask}, + execute::EstimateGasAdapter, filter::EthFilter, }; /// Eth API implementation. -pub struct Eth { +pub struct Eth { pool: Arc

, graph: Arc>, client: Arc, @@ -74,7 +75,7 @@ pub struct Eth { /// When using eth_call/eth_estimateGas, the maximum allowed gas limit will be /// block.gas_limit * execute_gas_limit_multiplier execute_gas_limit_multiplier: u64, - _marker: PhantomData<(B, BE)>, + _marker: PhantomData<(B, BE, EGA)>, } impl Eth { diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index c68c5f9a1809..5f9db08e6cb7 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -33,7 +33,7 @@ mod signer; mod web3; pub use self::{ - eth::{format, Eth, EthBlockDataCacheTask, EthFilter, EthTask}, + eth::{format, EstimateGasAdapter, Eth, EthBlockDataCacheTask, EthFilter, EthTask}, eth_pubsub::{EthPubSub, EthereumSubIdProvider}, net::Net, overrides::{