Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 46 additions & 25 deletions anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2076,40 +2076,61 @@ impl EthApi {

let mut last_highest_gas_limit = highest_gas_limit;

// Binary search for the ideal gas limit
while (highest_gas_limit - lowest_gas_limit) > U256::one() {
request.gas = Some(mid_gas_limit);
let (exit, _, _gas, _) = self.backend.call_with_state(
match self.backend.call_with_state(
&state,
request.clone(),
fees.clone(),
block_env.clone(),
)?;
match exit {
return_ok!() => {
highest_gas_limit = mid_gas_limit;
// if last two successful estimations only vary by 10%, we consider this to
// sufficiently accurate
const ACCURACY: u64 = 10;
if (last_highest_gas_limit - highest_gas_limit) * ACCURACY /
last_highest_gas_limit <
U256::one()
{
return Ok(highest_gas_limit)
) {
Ok((exit, _, _gas, _)) => {
match exit {
return_ok!() => {
highest_gas_limit = mid_gas_limit;
// if last two successful estimations only vary by 10%, we consider this
// to sufficiently accurate
const ACCURACY: u64 = 10;
if (last_highest_gas_limit - highest_gas_limit) * ACCURACY /
last_highest_gas_limit <
U256::one()
{
return Ok(highest_gas_limit)
}
last_highest_gas_limit = highest_gas_limit;
}
InstructionResult::Revert |
InstructionResult::OutOfGas |
InstructionResult::OutOfFund => {
lowest_gas_limit = mid_gas_limit;
}
reason => {
warn!(target: "node", "estimation failed due to {:?}", reason);
return Err(BlockchainError::EvmError(reason))
}
}
last_highest_gas_limit = highest_gas_limit;
}
InstructionResult::Revert |
InstructionResult::OutOfGas |
InstructionResult::OutOfFund => {
lowest_gas_limit = mid_gas_limit;
// new midpoint
mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
}
reason => {
warn!(target: "node", "estimation failed due to {:?}", reason);
return Err(BlockchainError::EvmError(reason))
Err(reason) => {
match reason {
// We need to treat REVM reverting due to gas too high just like
// revert/OOG/OOF (see above)
BlockchainError::InvalidTransaction(
InvalidTransactionError::GasTooHigh,
) => {
lowest_gas_limit = mid_gas_limit;
}
_ => {
warn!(target: "node", "estimation failed due to {:?}", reason);
return Err(reason)
}
};
// new midpoint
mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
}
}
// new midpoint
mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2;
};
}

trace!(target : "node", "Estimated Gas for call {:?}", highest_gas_limit);
Expand Down
4 changes: 3 additions & 1 deletion anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,9 @@ impl Backend {
evm.database(state);
let result_and_state = match evm.inspect_ref(&mut inspector) {
Ok(result_and_state) => result_and_state,
Err(_) => return Err(BlockchainError::EvmError(InstructionResult::FatalExternalError)),
Err(_) => {
return Err(BlockchainError::InvalidTransaction(InvalidTransactionError::GasTooHigh))
}
};
let state = result_and_state.state;
let state: hashbrown::HashMap<H160, Account> =
Expand Down
2 changes: 1 addition & 1 deletion forge/src/gas_report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl GasReport {
(!self.ignore.contains(&contract_name) && self.report_for.is_empty()) ||
(self.report_for.contains(&contract_name));
if report_contract {
let mut contract_report =
let contract_report =
self.contracts.entry(name.to_string()).or_insert_with(Default::default);

match &trace.data {
Expand Down