Make it compilable (still bunch to fix!)

This commit is contained in:
sprites0
2025-06-17 18:06:53 -04:00
parent 5e531b7260
commit 821bf7a775
38 changed files with 3652 additions and 31 deletions

39
src/evm/api/builder.rs Normal file
View File

@ -0,0 +1,39 @@
use super::HlEvmInner;
use crate::evm::{spec::HlSpecId, transaction::HlTxTr};
use revm::{
context::{Cfg, JournalOutput},
context_interface::{Block, JournalTr},
handler::instructions::EthInstructions,
interpreter::interpreter::EthInterpreter,
Context, Database,
};
/// Trait that allows for hl HlEvm to be built.
pub trait HlBuilder: Sized {
/// Type of the context.
type Context;
/// Build the hl with an inspector.
fn build_hl_with_inspector<INSP>(
self,
inspector: INSP,
) -> HlEvmInner<Self::Context, INSP, EthInstructions<EthInterpreter, Self::Context>>;
}
impl<BLOCK, TX, CFG, DB, JOURNAL> HlBuilder for Context<BLOCK, TX, CFG, DB, JOURNAL>
where
BLOCK: Block,
TX: HlTxTr,
CFG: Cfg<Spec = HlSpecId>,
DB: Database,
JOURNAL: JournalTr<Database = DB, FinalOutput = JournalOutput>,
{
type Context = Self;
fn build_hl_with_inspector<INSP>(
self,
inspector: INSP,
) -> HlEvmInner<Self::Context, INSP, EthInstructions<EthInterpreter, Self::Context>> {
HlEvmInner::new(self, inspector)
}
}

23
src/evm/api/ctx.rs Normal file
View File

@ -0,0 +1,23 @@
use crate::evm::{spec::HlSpecId, transaction::HlTxEnv};
use revm::{
context::{BlockEnv, CfgEnv, TxEnv},
database_interface::EmptyDB,
Context, Journal, MainContext,
};
/// Type alias for the default context type of the HlEvm.
pub type HlContext<DB> = Context<BlockEnv, HlTxEnv<TxEnv>, CfgEnv<HlSpecId>, DB, Journal<DB>>;
/// Trait that allows for a default context to be created.
pub trait DefaultHl {
/// Create a default context.
fn hl() -> HlContext<EmptyDB>;
}
impl DefaultHl for HlContext<EmptyDB> {
fn hl() -> Self {
Context::mainnet()
.with_tx(HlTxEnv::default())
.with_cfg(CfgEnv::new_with_spec(HlSpecId::default()))
}
}

107
src/evm/api/exec.rs Normal file
View File

@ -0,0 +1,107 @@
use super::HlEvmInner;
use crate::evm::{handler::HlHandler, spec::HlSpecId, transaction::HlTxTr};
use revm::{
context::{ContextSetters, JournalOutput},
context_interface::{
result::{EVMError, ExecutionResult, ResultAndState},
Cfg, ContextTr, Database, JournalTr,
},
handler::{instructions::EthInstructions, EthFrame, EvmTr, Handler, PrecompileProvider},
inspector::{InspectCommitEvm, InspectEvm, Inspector, InspectorHandler, JournalExt},
interpreter::{interpreter::EthInterpreter, InterpreterResult},
DatabaseCommit, ExecuteCommitEvm, ExecuteEvm,
};
// Type alias for HL context
pub trait HlContextTr:
ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>, Tx: HlTxTr, Cfg: Cfg<Spec = HlSpecId>>
{
}
impl<T> HlContextTr for T where
T: ContextTr<
Journal: JournalTr<FinalOutput = JournalOutput>,
Tx: HlTxTr,
Cfg: Cfg<Spec = HlSpecId>,
>
{
}
/// Type alias for the error type of the HlEvm.
type HlError<CTX> = EVMError<<<CTX as ContextTr>::Db as Database>::Error>;
impl<CTX, INSP, PRECOMPILE> ExecuteEvm
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
where
CTX: HlContextTr + ContextSetters,
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
{
type Output = Result<ResultAndState, HlError<CTX>>;
type Tx = <CTX as ContextTr>::Tx;
type Block = <CTX as ContextTr>::Block;
fn set_tx(&mut self, tx: Self::Tx) {
self.0.ctx.set_tx(tx);
}
fn set_block(&mut self, block: Self::Block) {
self.0.ctx.set_block(block);
}
fn replay(&mut self) -> Self::Output {
let mut h = HlHandler::<_, _, EthFrame<_, _, _>>::new();
h.run(self)
}
}
impl<CTX, INSP, PRECOMPILE> ExecuteCommitEvm
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
where
CTX: HlContextTr<Db: DatabaseCommit> + ContextSetters,
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
{
type CommitOutput = Result<ExecutionResult, HlError<CTX>>;
fn replay_commit(&mut self) -> Self::CommitOutput {
self.replay().map(|r| {
self.ctx().db().commit(r.state);
r.result
})
}
}
impl<CTX, INSP, PRECOMPILE> InspectEvm
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
where
CTX: HlContextTr<Journal: JournalExt> + ContextSetters,
INSP: Inspector<CTX, EthInterpreter>,
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
{
type Inspector = INSP;
fn set_inspector(&mut self, inspector: Self::Inspector) {
self.0.inspector = inspector;
}
fn inspect_replay(&mut self) -> Self::Output {
let mut h = HlHandler::<_, _, EthFrame<_, _, _>>::new();
h.inspect_run(self)
}
}
impl<CTX, INSP, PRECOMPILE> InspectCommitEvm
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
where
CTX: HlContextTr<Journal: JournalExt, Db: DatabaseCommit> + ContextSetters,
INSP: Inspector<CTX, EthInterpreter>,
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
{
fn inspect_replay_commit(&mut self) -> Self::CommitOutput {
self.inspect_replay().map(|r| {
self.ctx().db().commit(r.state);
r.result
})
}
}

134
src/evm/api/mod.rs Normal file
View File

@ -0,0 +1,134 @@
use super::precompiles::HlPrecompiles;
use revm::{
context::{ContextSetters, Evm as EvmCtx},
context_interface::ContextTr,
handler::{
instructions::{EthInstructions, InstructionProvider},
EvmTr, PrecompileProvider,
},
inspector::{InspectorEvmTr, JournalExt},
interpreter::{interpreter::EthInterpreter, Interpreter, InterpreterAction, InterpreterTypes},
Inspector,
};
pub mod builder;
pub mod ctx;
mod exec;
pub struct HlEvmInner<CTX, INSP, I = EthInstructions<EthInterpreter, CTX>, P = HlPrecompiles>(
pub EvmCtx<CTX, INSP, I, P>,
);
impl<CTX: ContextTr, INSP>
HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, HlPrecompiles>
{
pub fn new(ctx: CTX, inspector: INSP) -> Self {
Self(EvmCtx {
ctx,
inspector,
instruction: EthInstructions::new_mainnet(),
precompiles: HlPrecompiles::default(),
})
}
/// Consumes self and returns a new Evm type with given Precompiles.
pub fn with_precompiles<OP>(
self,
precompiles: OP,
) -> HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, OP> {
HlEvmInner(self.0.with_precompiles(precompiles))
}
}
impl<CTX, INSP, I, P> InspectorEvmTr for HlEvmInner<CTX, INSP, I, P>
where
CTX: ContextTr<Journal: JournalExt> + ContextSetters,
I: InstructionProvider<
Context = CTX,
InterpreterTypes: InterpreterTypes<Output = InterpreterAction>,
>,
INSP: Inspector<CTX, I::InterpreterTypes>,
P: PrecompileProvider<CTX>,
{
type Inspector = INSP;
fn inspector(&mut self) -> &mut Self::Inspector {
&mut self.0.inspector
}
fn ctx_inspector(&mut self) -> (&mut Self::Context, &mut Self::Inspector) {
(&mut self.0.ctx, &mut self.0.inspector)
}
fn run_inspect_interpreter(
&mut self,
interpreter: &mut Interpreter<
<Self::Instructions as InstructionProvider>::InterpreterTypes,
>,
) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output
{
self.0.run_inspect_interpreter(interpreter)
}
}
impl<CTX, INSP, I, P> EvmTr for HlEvmInner<CTX, INSP, I, P>
where
CTX: ContextTr,
I: InstructionProvider<
Context = CTX,
InterpreterTypes: InterpreterTypes<Output = InterpreterAction>,
>,
P: PrecompileProvider<CTX>,
{
type Context = CTX;
type Instructions = I;
type Precompiles = P;
fn run_interpreter(
&mut self,
interpreter: &mut Interpreter<
<Self::Instructions as InstructionProvider>::InterpreterTypes,
>,
) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output
{
let context = &mut self.0.ctx;
let instructions = &mut self.0.instruction;
interpreter.run_plain(instructions.instruction_table(), context)
}
fn ctx(&mut self) -> &mut Self::Context {
&mut self.0.ctx
}
fn ctx_ref(&self) -> &Self::Context {
&self.0.ctx
}
fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions) {
(&mut self.0.ctx, &mut self.0.instruction)
}
fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles) {
(&mut self.0.ctx, &mut self.0.precompiles)
}
}
// #[cfg(test)]
// mod test {
// use super::{builder::HlBuilder, ctx::DefaultHl};
// use revm::{
// inspector::{InspectEvm, NoOpInspector},
// Context, ExecuteEvm,
// };
// #[test]
// fn default_run_bsc() {
// let ctx = Context::bsc();
// let mut evm = ctx.build_bsc_with_inspector(NoOpInspector {});
// // execute
// let _ = evm.replay();
// // inspect
// let _ = evm.inspect_replay();
// }
// }

148
src/evm/handler.rs Normal file
View File

@ -0,0 +1,148 @@
//! EVM Handler related to Hl chain
use super::{spec::HlSpecId, transaction::HlTxTr};
use revm::{
context::{
result::{ExecutionResult, HaltReason},
Cfg, ContextTr, JournalOutput, LocalContextTr,
},
context_interface::{result::ResultAndState, JournalTr},
handler::{handler::EvmTrError, EvmTr, Frame, FrameResult, Handler, MainnetHandler},
inspector::{Inspector, InspectorEvmTr, InspectorFrame, InspectorHandler},
interpreter::{interpreter::EthInterpreter, FrameInput, InitialAndFloorGas, SuccessOrHalt},
};
pub struct HlHandler<EVM, ERROR, FRAME> {
pub mainnet: MainnetHandler<EVM, ERROR, FRAME>,
}
impl<EVM, ERROR, FRAME> HlHandler<EVM, ERROR, FRAME> {
pub fn new() -> Self {
Self {
mainnet: MainnetHandler::default(),
}
}
}
impl<EVM, ERROR, FRAME> Default for HlHandler<EVM, ERROR, FRAME> {
fn default() -> Self {
Self::new()
}
}
pub trait HlContextTr:
ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>, Tx: HlTxTr, Cfg: Cfg<Spec = HlSpecId>>
{
}
impl<T> HlContextTr for T where
T: ContextTr<
Journal: JournalTr<FinalOutput = JournalOutput>,
Tx: HlTxTr,
Cfg: Cfg<Spec = HlSpecId>,
>
{
}
impl<EVM, ERROR, FRAME> Handler for HlHandler<EVM, ERROR, FRAME>
where
EVM: EvmTr<Context: HlContextTr>,
ERROR: EvmTrError<EVM>,
FRAME: Frame<Evm = EVM, Error = ERROR, FrameResult = FrameResult, FrameInit = FrameInput>,
{
type Evm = EVM;
type Error = ERROR;
type Frame = FRAME;
type HaltReason = HaltReason;
fn validate_initial_tx_gas(
&self,
evm: &Self::Evm,
) -> Result<revm::interpreter::InitialAndFloorGas, Self::Error> {
let ctx = evm.ctx_ref();
let tx = ctx.tx();
if tx.is_system_transaction() {
return Ok(InitialAndFloorGas {
initial_gas: 0,
floor_gas: 0,
});
}
self.mainnet.validate_initial_tx_gas(evm)
}
fn reward_beneficiary(
&self,
evm: &mut Self::Evm,
exec_result: &mut <Self::Frame as Frame>::FrameResult,
) -> Result<(), Self::Error> {
Ok(())
}
fn output(
&self,
evm: &mut Self::Evm,
result: <Self::Frame as Frame>::FrameResult,
) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
let ctx = evm.ctx();
ctx.error();
let tx = ctx.tx();
// used gas with refund calculated.
let gas_refunded = if tx.is_system_transaction() {
0
} else {
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();
// Reset journal and return present state.
let JournalOutput { state, logs } = evm.ctx().journal().finalize();
let result = match SuccessOrHalt::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,
},
// Only two internal return flags.
flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => {
panic!(
"Encountered unexpected internal return flag: {flag:?} with instruction result: {instruction_result:?}"
)
}
};
// Clear local context
evm.ctx().local().clear();
// Clear journal
evm.ctx().journal().clear();
Ok(ResultAndState { result, state })
}
}
impl<EVM, ERROR, FRAME> InspectorHandler for HlHandler<EVM, ERROR, FRAME>
where
EVM: InspectorEvmTr<
Context: HlContextTr,
Inspector: Inspector<<<Self as Handler>::Evm as EvmTr>::Context, EthInterpreter>,
>,
ERROR: EvmTrError<EVM>,
FRAME: Frame<Evm = EVM, Error = ERROR, FrameResult = FrameResult, FrameInit = FrameInput>
+ InspectorFrame<IT = EthInterpreter>,
{
type IT = EthInterpreter;
}

5
src/evm/mod.rs Normal file
View File

@ -0,0 +1,5 @@
pub mod api;
mod handler;
pub mod precompiles;
pub mod spec;
pub mod transaction;

87
src/evm/precompiles.rs Normal file
View File

@ -0,0 +1,87 @@
#![allow(unused)]
use super::spec::HlSpecId;
use cfg_if::cfg_if;
use once_cell::{race::OnceBox, sync::Lazy};
use revm::{
context::Cfg,
context_interface::ContextTr,
handler::{EthPrecompiles, PrecompileProvider},
interpreter::{InputsImpl, InterpreterResult},
precompile::{bls12_381, kzg_point_evaluation, modexp, secp256r1, Precompiles},
primitives::{hardfork::SpecId, Address},
};
use std::boxed::Box;
// HL precompile provider
#[derive(Debug, Clone)]
pub struct HlPrecompiles {
/// Inner precompile provider is same as Ethereums.
inner: EthPrecompiles,
}
impl HlPrecompiles {
/// Create a new precompile provider with the given hl spec.
#[inline]
pub fn new(spec: HlSpecId) -> Self {
let precompiles = cancun();
Self { inner: EthPrecompiles { precompiles, spec: spec.into_eth_spec() } }
}
#[inline]
pub fn precompiles(&self) -> &'static Precompiles {
self.inner.precompiles
}
}
/// Returns precompiles for Istanbul spec.
pub fn cancun() -> &'static Precompiles {
static INSTANCE: OnceBox<Precompiles> = OnceBox::new();
INSTANCE.get_or_init(|| {
let mut precompiles = Precompiles::cancun().clone();
// precompiles.extend([tendermint::TENDERMINT_HEADER_VALIDATION, iavl::IAVL_PROOF_VALIDATION]);
Box::new(precompiles)
})
}
impl<CTX> PrecompileProvider<CTX> for HlPrecompiles
where
CTX: ContextTr<Cfg: Cfg<Spec = HlSpecId>>,
{
type Output = InterpreterResult;
#[inline]
fn set_spec(&mut self, spec: <CTX::Cfg as Cfg>::Spec) -> bool {
*self = Self::new(spec);
true
}
#[inline]
fn run(
&mut self,
context: &mut CTX,
address: &Address,
inputs: &InputsImpl,
is_static: bool,
gas_limit: u64,
) -> Result<Option<Self::Output>, String> {
self.inner.run(context, address, inputs, is_static, gas_limit)
}
#[inline]
fn warm_addresses(&self) -> Box<impl Iterator<Item = Address>> {
self.inner.warm_addresses()
}
#[inline]
fn contains(&self, address: &Address) -> bool {
self.inner.contains(address)
}
}
impl Default for HlPrecompiles {
fn default() -> Self {
Self::new(HlSpecId::default())
}
}

55
src/evm/spec.rs Normal file
View File

@ -0,0 +1,55 @@
use revm::primitives::hardfork::SpecId;
use std::str::FromStr;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)]
pub enum HlSpecId {
#[default]
V1, // V1
}
impl HlSpecId {
pub const fn is_enabled_in(self, other: HlSpecId) -> bool {
other as u8 <= self as u8
}
/// Converts the [`HlSpecId`] into a [`SpecId`].
pub const fn into_eth_spec(self) -> SpecId {
match self {
Self::V1 => SpecId::CANCUN,
}
}
}
impl From<HlSpecId> for SpecId {
fn from(spec: HlSpecId) -> Self {
spec.into_eth_spec()
}
}
/// String identifiers for HL hardforks
pub mod name {
pub const V1: &str = "V1";
}
impl FromStr for HlSpecId {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
name::V1 => Self::V1,
_ => return Err(format!("Unknown HL spec: {s}")),
})
}
}
impl From<HlSpecId> for &'static str {
fn from(spec_id: HlSpecId) -> Self {
match spec_id {
HlSpecId::V1 => name::V1,
}
}
}

203
src/evm/transaction.rs Normal file
View File

@ -0,0 +1,203 @@
use alloy_consensus::Transaction as AlloyTransaction;
use alloy_rpc_types::AccessList;
use auto_impl::auto_impl;
use reth_evm::{FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, TransactionEnv};
use reth_primitives::TransactionSigned;
use revm::{
context::TxEnv,
context_interface::transaction::Transaction,
primitives::{Address, Bytes, TxKind, B256, U256},
};
#[auto_impl(&, &mut, Box, Arc)]
pub trait HlTxTr: Transaction {
/// Whether the transaction is a system transaction
fn is_system_transaction(&self) -> bool;
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HlTxEnv<T: Transaction> {
pub base: T,
pub is_system_transaction: bool,
}
impl<T: Transaction> HlTxEnv<T> {
pub fn new(base: T) -> Self {
Self {
base,
is_system_transaction: false,
}
}
}
impl Default for HlTxEnv<TxEnv> {
fn default() -> Self {
Self {
base: TxEnv::default(),
is_system_transaction: false,
}
}
}
impl<T: Transaction> Transaction for HlTxEnv<T> {
type AccessListItem<'a>
= T::AccessListItem<'a>
where
T: 'a;
type Authorization<'a>
= T::Authorization<'a>
where
T: 'a;
fn tx_type(&self) -> u8 {
self.base.tx_type()
}
fn caller(&self) -> Address {
self.base.caller()
}
fn gas_limit(&self) -> u64 {
self.base.gas_limit()
}
fn value(&self) -> U256 {
self.base.value()
}
fn input(&self) -> &Bytes {
self.base.input()
}
fn nonce(&self) -> u64 {
self.base.nonce()
}
fn kind(&self) -> TxKind {
self.base.kind()
}
fn chain_id(&self) -> Option<u64> {
self.base.chain_id()
}
fn gas_price(&self) -> u128 {
self.base.gas_price()
}
fn access_list(&self) -> Option<impl Iterator<Item = Self::AccessListItem<'_>>> {
self.base.access_list()
}
fn blob_versioned_hashes(&self) -> &[B256] {
self.base.blob_versioned_hashes()
}
fn max_fee_per_blob_gas(&self) -> u128 {
self.base.max_fee_per_blob_gas()
}
fn authorization_list_len(&self) -> usize {
self.base.authorization_list_len()
}
fn authorization_list(&self) -> impl Iterator<Item = Self::Authorization<'_>> {
self.base.authorization_list()
}
fn max_fee_per_gas(&self) -> u128 {
self.base.max_fee_per_gas()
}
fn max_priority_fee_per_gas(&self) -> Option<u128> {
self.base.max_priority_fee_per_gas()
}
fn effective_gas_price(&self, base_fee: u128) -> u128 {
self.base.effective_gas_price(base_fee)
}
}
impl<T: Transaction> HlTxTr for HlTxEnv<T> {
fn is_system_transaction(&self) -> bool {
self.is_system_transaction
}
}
impl<T: revm::context::Transaction> IntoTxEnv<Self> for HlTxEnv<T> {
fn into_tx_env(self) -> Self {
self
}
}
impl FromRecoveredTx<TransactionSigned> for HlTxEnv<TxEnv> {
fn from_recovered_tx(tx: &TransactionSigned, sender: Address) -> Self {
Self::new(TxEnv::from_recovered_tx(tx, sender))
}
}
impl FromTxWithEncoded<TransactionSigned> for HlTxEnv<TxEnv> {
fn from_encoded_tx(tx: &TransactionSigned, sender: Address, _encoded: Bytes) -> Self {
let base = match tx.clone().into_typed_transaction() {
reth_primitives::Transaction::Legacy(tx) => TxEnv::from_recovered_tx(&tx, sender),
reth_primitives::Transaction::Eip2930(tx) => TxEnv::from_recovered_tx(&tx, sender),
reth_primitives::Transaction::Eip1559(tx) => TxEnv::from_recovered_tx(&tx, sender),
reth_primitives::Transaction::Eip4844(tx) => TxEnv::from_recovered_tx(&tx, sender),
reth_primitives::Transaction::Eip7702(tx) => TxEnv::from_recovered_tx(&tx, sender),
};
let is_system_transaction = match tx.gas_price() {
Some(x) => x == 0u128,
None => false,
};
Self {
base,
is_system_transaction
}
}
}
impl<T: TransactionEnv> TransactionEnv for HlTxEnv<T> {
fn set_gas_limit(&mut self, gas_limit: u64) {
self.base.set_gas_limit(gas_limit);
}
fn nonce(&self) -> u64 {
TransactionEnv::nonce(&self.base)
}
fn set_nonce(&mut self, nonce: u64) {
self.base.set_nonce(nonce);
}
fn set_access_list(&mut self, access_list: AccessList) {
self.base.set_access_list(access_list);
}
}
#[cfg(test)]
mod tests {
use super::*;
use revm::primitives::Address;
#[test]
fn test_hl_transaction_fields() {
let hl_tx = HlTxEnv {
base: TxEnv {
tx_type: 0,
gas_limit: 10,
gas_price: 100,
gas_priority_fee: Some(5),
..Default::default()
},
is_system_transaction: false,
};
assert_eq!(hl_tx.tx_type(), 0);
assert_eq!(hl_tx.gas_limit(), 10);
assert_eq!(hl_tx.kind(), revm::primitives::TxKind::Call(Address::ZERO));
}
}