From 782b591c168b6299c03df513ce3e9c5696e4a01a Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 21 Mar 2023 20:45:05 +0100 Subject: [PATCH] fix(rpc): cap tx gas limit with allowance in createAccessList (#1893) --- crates/rpc/rpc/src/eth/api/call.rs | 27 ++++++++++++--------------- crates/rpc/rpc/src/eth/revm_utils.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/crates/rpc/rpc/src/eth/api/call.rs b/crates/rpc/rpc/src/eth/api/call.rs index 602d45c33c..773f1ccc66 100644 --- a/crates/rpc/rpc/src/eth/api/call.rs +++ b/crates/rpc/rpc/src/eth/api/call.rs @@ -3,7 +3,10 @@ use crate::{ eth::{ error::{EthApiError, EthResult, InvalidTransactionError, RevertError}, - revm_utils::{build_call_evm_env, get_precompiles, inspect, transact}, + revm_utils::{ + build_call_evm_env, cap_tx_gas_limit_with_caller_allowance, get_precompiles, inspect, + transact, + }, EthTransactions, }, EthApi, @@ -81,19 +84,7 @@ where if request_gas.is_none() && env.tx.gas_price > U256::ZERO { // no gas limit was provided in the request, so we need to cap the request's gas limit - let mut allowance = db.basic(env.tx.caller)?.map(|acc| acc.balance).unwrap_or_default(); - - // subtract transferred value - allowance = allowance - .checked_sub(env.tx.value) - .ok_or_else(|| InvalidTransactionError::InsufficientFunds)?; - - // cap the gas limit - if let Ok(gas_limit) = - allowance.checked_div(env.tx.gas_price).unwrap_or_default().try_into() - { - env.tx.gas_limit = gas_limit; - } + cap_tx_gas_limit_with_caller_allowance(&mut db, &mut env.tx)?; } transact(&mut db, env) @@ -292,9 +283,15 @@ where // impls and providers cfg.disable_block_gas_limit = true; - let env = build_call_evm_env(cfg, block, request.clone())?; + let mut env = build_call_evm_env(cfg, block, request.clone())?; + let mut db = SubState::new(State::new(state)); + if request.gas.is_none() && env.tx.gas_price > U256::ZERO { + // no gas limit was provided in the request, so we need to cap the request's gas limit + cap_tx_gas_limit_with_caller_allowance(&mut db, &mut env.tx)?; + } + let from = request.from.unwrap_or_default(); let to = if let Some(to) = request.to { to diff --git a/crates/rpc/rpc/src/eth/revm_utils.rs b/crates/rpc/rpc/src/eth/revm_utils.rs index fc7c35675e..02b90a055c 100644 --- a/crates/rpc/rpc/src/eth/revm_utils.rs +++ b/crates/rpc/rpc/src/eth/revm_utils.rs @@ -115,6 +115,32 @@ pub(crate) fn create_txn_env(block_env: &BlockEnv, request: CallRequest) -> EthR Ok(env) } +/// Caps the configured [TxEnv] `gas_limit` with the allowance of the caller. +/// +/// Returns an error if the caller has insufficient funds +pub(crate) fn cap_tx_gas_limit_with_caller_allowance( + mut db: DB, + env: &mut TxEnv, +) -> EthResult<()> +where + DB: Database, + EthApiError: From<::Error>, +{ + let mut allowance = db.basic(env.caller)?.map(|acc| acc.balance).unwrap_or_default(); + + // subtract transferred value + allowance = allowance + .checked_sub(env.value) + .ok_or_else(|| InvalidTransactionError::InsufficientFunds)?; + + // cap the gas limit + if let Ok(gas_limit) = allowance.checked_div(env.gas_price).unwrap_or_default().try_into() { + env.gas_limit = gas_limit; + } + + Ok(()) +} + /// Helper type for representing the fees of a [CallRequest] pub(crate) struct CallFees { /// EIP-1559 priority fee