use super::frame_data::FrameResult;
use context_interface::ContextTr;
use context_interface::{
journaled_state::JournalTr,
result::{ExecutionResult, HaltReasonTr},
Block, Cfg, Database, Transaction,
};
use interpreter::{Gas, InitialAndFloorGas, SuccessOrHalt};
use primitives::{hardfork::SpecId, U256};
use state::EvmState;
pub fn eip7623_check_gas_floor(gas: &mut Gas, init_and_floor_gas: InitialAndFloorGas) {
if gas.spent_sub_refunded() < init_and_floor_gas.floor_gas {
gas.set_spent(init_and_floor_gas.floor_gas);
gas.set_refund(0);
}
}
pub fn refund(spec: SpecId, gas: &mut Gas, eip7702_refund: i64) {
gas.record_refund(eip7702_refund);
gas.set_final_refund(spec.is_enabled_in(SpecId::LONDON));
}
#[inline]
pub fn reimburse_caller<CTX: ContextTr>(
context: &mut CTX,
gas: &mut Gas,
additional_refund: U256,
) -> Result<(), <CTX::Db as Database>::Error> {
let basefee = context.block().basefee() as u128;
let caller = context.tx().caller();
let effective_gas_price = context.tx().effective_gas_price(basefee);
context.journal_mut().balance_incr(
caller,
U256::from(
effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128),
) + additional_refund,
)?;
Ok(())
}
#[inline]
pub fn reward_beneficiary<CTX: ContextTr>(
context: &mut CTX,
gas: &mut Gas,
) -> Result<(), <CTX::Db as Database>::Error> {
let beneficiary = context.block().beneficiary();
let basefee = context.block().basefee() as u128;
let effective_gas_price = context.tx().effective_gas_price(basefee);
let coinbase_gas_price = if context.cfg().spec().into().is_enabled_in(SpecId::LONDON) {
effective_gas_price.saturating_sub(basefee)
} else {
effective_gas_price
};
context.journal_mut().balance_incr(
beneficiary,
U256::from(coinbase_gas_price * (gas.spent() - gas.refunded() as u64) as u128),
)?;
Ok(())
}
pub fn output<CTX: ContextTr<Journal: JournalTr<State = EvmState>>, HALTREASON: HaltReasonTr>(
context: &mut CTX,
result: FrameResult,
) -> ExecutionResult<HALTREASON> {
let gas_refunded = result.gas().refunded() as u64;
let final_gas_used = result.gas().spent() - gas_refunded;
let output = result.output();
let instruction_result = result.into_interpreter_result();
let logs = context.journal_mut().take_logs();
match SuccessOrHalt::<HALTREASON>::from(instruction_result.result) {
SuccessOrHalt::Success(reason) => ExecutionResult::Success {
reason,
gas_used: final_gas_used,
gas_refunded,
logs,
output,
},
SuccessOrHalt::Revert => ExecutionResult::Revert {
gas_used: final_gas_used,
output: output.into_data(),
},
SuccessOrHalt::Halt(reason) => ExecutionResult::Halt {
reason,
gas_used: final_gas_used,
},
flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => {
panic!(
"Encountered unexpected internal return flag: {:?} with instruction result: {:?}",
flag, instruction_result
)
}
}
}