mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
refactor(rpc): gas allowance calculation (#3304)
This commit is contained in:
@ -4,8 +4,8 @@ use crate::{
|
||||
eth::{
|
||||
error::{ensure_success, EthApiError, EthResult, RevertError, RpcInvalidTransactionError},
|
||||
revm_utils::{
|
||||
build_call_evm_env, cap_tx_gas_limit_with_caller_allowance, get_precompiles, inspect,
|
||||
transact, EvmOverrides,
|
||||
build_call_evm_env, caller_gas_allowance, cap_tx_gas_limit_with_caller_allowance,
|
||||
get_precompiles, inspect, transact, EvmOverrides,
|
||||
},
|
||||
EthTransactions,
|
||||
},
|
||||
@ -122,19 +122,8 @@ where
|
||||
}
|
||||
|
||||
// check funds of the sender
|
||||
let gas_price = env.tx.gas_price;
|
||||
if gas_price > U256::ZERO {
|
||||
let mut available_funds =
|
||||
db.basic(env.tx.caller)?.map(|acc| acc.balance).unwrap_or_default();
|
||||
if env.tx.value > available_funds {
|
||||
return Err(RpcInvalidTransactionError::InsufficientFunds.into())
|
||||
}
|
||||
// subtract transferred value from available funds
|
||||
// SAFETY: value < available_funds, checked above
|
||||
available_funds -= env.tx.value;
|
||||
// amount of gas the sender can afford with the `gas_price`
|
||||
// SAFETY: gas_price not zero
|
||||
let allowance = available_funds.checked_div(gas_price).unwrap_or_default();
|
||||
if env.tx.gas_price > U256::ZERO {
|
||||
let allowance = caller_gas_allowance(&mut db, &env.tx)?;
|
||||
|
||||
if highest_gas_limit > allowance {
|
||||
// cap the highest gas limit by max gas caller can afford with given gas price
|
||||
|
||||
@ -317,31 +317,45 @@ pub(crate) fn create_txn_env(block_env: &BlockEnv, request: CallRequest) -> EthR
|
||||
}
|
||||
|
||||
/// 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<DB>(
|
||||
mut db: DB,
|
||||
env: &mut TxEnv,
|
||||
) -> EthResult<()>
|
||||
pub(crate) fn cap_tx_gas_limit_with_caller_allowance<DB>(db: DB, env: &mut TxEnv) -> EthResult<()>
|
||||
where
|
||||
DB: Database,
|
||||
EthApiError: From<<DB as Database>::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(|| RpcInvalidTransactionError::InsufficientFunds)?;
|
||||
|
||||
// cap the gas limit
|
||||
if let Ok(gas_limit) = allowance.checked_div(env.gas_price).unwrap_or_default().try_into() {
|
||||
if let Ok(gas_limit) = caller_gas_allowance(db, env)?.try_into() {
|
||||
env.gas_limit = gas_limit;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Calculates the caller gas allowance.
|
||||
///
|
||||
/// `allowance = (account.balance - tx.value) / tx.gas_price`
|
||||
///
|
||||
/// Returns an error if the caller has insufficient funds.
|
||||
/// Caution: This assumes non-zero `env.gas_price`. Otherwise, zero allowance will be returned.
|
||||
pub(crate) fn caller_gas_allowance<DB>(mut db: DB, env: &TxEnv) -> EthResult<U256>
|
||||
where
|
||||
DB: Database,
|
||||
EthApiError: From<<DB as Database>::Error>,
|
||||
{
|
||||
Ok(db
|
||||
// Get the caller account.
|
||||
.basic(env.caller)?
|
||||
// Get the caller balance.
|
||||
.map(|acc| acc.balance)
|
||||
.unwrap_or_default()
|
||||
// Subtract transferred value from the caller balance.
|
||||
.checked_sub(env.value)
|
||||
// Return error if the caller has insufficient funds.
|
||||
.ok_or_else(|| RpcInvalidTransactionError::InsufficientFunds)?
|
||||
// Calculate the amount of gas the caller can afford with the specified gas price.
|
||||
.checked_div(env.gas_price)
|
||||
// This will be 0 if gas price is 0. It is fine, because we check it before.
|
||||
.unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Helper type for representing the fees of a [CallRequest]
|
||||
pub(crate) struct CallFees {
|
||||
/// EIP-1559 priority fee
|
||||
|
||||
Reference in New Issue
Block a user