Skip to content
Open
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
850 changes: 637 additions & 213 deletions Cargo.lock

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ members = [
"crates/context",
"crates/context/interface",
"crates/handler",
# supra extensions
"crates/supra-extension",

# variants
"crates/op-revm",
Expand All @@ -35,6 +37,7 @@ members = [
"examples/my_evm",
"examples/custom_opcodes",
"examples/custom_precompile_journal",

]
resolver = "2"
default-members = ["crates/revm"]
Expand All @@ -56,6 +59,7 @@ context-interface = { path = "crates/context/interface", package = "revm-context
handler = { path = "crates/handler", package = "revm-handler", version = "10.0.0", default-features = false }
op-revm = { path = "crates/op-revm", package = "op-revm", version = "10.0.0", default-features = false }
ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false }
supra-extension = { path = "crates/supra-extension", package = "revm-supra-extension", version = "0.1.0", default-features = false }

# alloy
alloy-eip2930 = { version = "0.2.1", default-features = false }
Expand All @@ -72,6 +76,16 @@ alloy-signer = { version = "1.0.12", default-features = false }
alloy-signer-local = { version = "1.0.12", default-features = false }
alloy-transport = { version = "1.0.12", default-features = false }

alloy-contract = { version = "1.0.19"}
alloy = { version = "1.0.19", features = ["sol-types", "contract"] }
alloy-serde = { version = "1.0.19" }

# libraries required to build supra-contract bindings
# For more detaisl see crates/supra-extension/build.rs
#forge = { git = "https://github.com/foundry-rs/foundry.git", tag="v1.4.1"}
#alloy-chains = { version = "0.2.13" }
#shlex = { version = "1.3.0" }

# precompiles
ark-bls12-381 = { version = "0.5", default-features = false }
ark-bn254 = { version = "0.5", default-features = false }
Expand Down Expand Up @@ -113,6 +127,7 @@ derive-where = { version = "1.5.0", default-features = false }
rand = "0.9"
tokio = "1.45"
either = { version = "1.15.0", default-features = false }
derive_more = { version = "2.0.1" }

# dev-dependencies
anyhow = "1.0.98"
Expand Down
2 changes: 1 addition & 1 deletion crates/context/interface/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub trait Cfg {

/// Returns whether the priority fee check is disabled.
fn is_priority_fee_check_disabled(&self) -> bool;

/// Returns whether the automation mode is enabled.
fn is_automation_mode(&self) -> bool;
}
Expand Down
5 changes: 5 additions & 0 deletions crates/context/interface/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ pub trait Transaction {
/// Note : Common field for all transactions.
fn nonce(&self) -> u64;

/// Transaction hash (32 bytes).
///
/// Note : Common field for all transactions.
fn tx_hash(&self) -> B256;

/// Transaction kind. It can be Call or Create.
///
/// Kind is applicable for: Legacy, EIP-2930, EIP-1559
Expand Down
7 changes: 7 additions & 0 deletions crates/context/interface/src/transaction/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,11 @@ where
Either::Right(r) => r.max_priority_fee_per_gas(),
}
}

fn tx_hash(&self) -> B256 {
match self {
Either::Left(l) => l.tx_hash(),
Either::Right(r) => r.tx_hash(),
}
}
}
4 changes: 2 additions & 2 deletions crates/context/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
}
}
}

fn is_automation_mode(&self) -> bool {
self.automation_mode
}
Expand All @@ -369,4 +369,4 @@ mod test {
let cfg: CfgEnv = Default::default();
assert_eq!(cfg.max_blobs_per_tx(), None);
}
}
}
18 changes: 18 additions & 0 deletions crates/context/src/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ pub struct TxEnv {
///
/// [EIP-7702]: https://eips.ethereum.org/EIPS/eip-7702
pub authorization_list: Vec<Either<SignedAuthorization, RecoveredAuthorization>>,
/// Transaction hash
pub tx_hash: B256,
}

impl Default for TxEnv {
Expand Down Expand Up @@ -226,6 +228,10 @@ impl Transaction for TxEnv {
fn max_priority_fee_per_gas(&self) -> Option<u128> {
self.gas_priority_fee
}

fn tx_hash(&self) -> B256 {
self.tx_hash
}
}

/// Builder for constructing [`TxEnv`] instances
Expand All @@ -245,6 +251,7 @@ pub struct TxEnvBuilder {
blob_hashes: Vec<B256>,
max_fee_per_blob_gas: u128,
authorization_list: Vec<Either<SignedAuthorization, RecoveredAuthorization>>,
tx_hash: B256,
}

impl TxEnvBuilder {
Expand All @@ -265,6 +272,7 @@ impl TxEnvBuilder {
blob_hashes: Vec::new(),
max_fee_per_blob_gas: 0,
authorization_list: Vec::new(),
tx_hash: B256::ZERO,
}
}

Expand Down Expand Up @@ -374,6 +382,12 @@ impl TxEnvBuilder {
self
}

/// Set the transaction hash
pub fn tx_hash(mut self, tx_hash: B256) -> Self {
self.tx_hash = tx_hash;
self
}

/// Set the authorization list
pub fn authorization_list(
mut self,
Expand Down Expand Up @@ -473,6 +487,7 @@ impl TxEnvBuilder {
blob_hashes: self.blob_hashes,
max_fee_per_blob_gas: self.max_fee_per_blob_gas,
authorization_list: self.authorization_list,
tx_hash: self.tx_hash,
};

// if tx_type is not set, derive it from fields and fix errors.
Expand Down Expand Up @@ -565,6 +580,7 @@ impl TxEnvBuilder {
blob_hashes: self.blob_hashes,
max_fee_per_blob_gas: self.max_fee_per_blob_gas,
authorization_list: self.authorization_list,
tx_hash: self.tx_hash,
};

// Derive tx type from fields, if some fields are wrongly set it will return an error.
Expand Down Expand Up @@ -626,6 +642,7 @@ impl TxEnv {
blob_hashes,
max_fee_per_blob_gas,
authorization_list,
tx_hash,
} = self;

TxEnvBuilder::new()
Expand All @@ -643,6 +660,7 @@ impl TxEnv {
.blob_hashes(blob_hashes)
.max_fee_per_blob_gas(max_fee_per_blob_gas)
.authorization_list(authorization_list)
.tx_hash(tx_hash)
}
}

Expand Down
20 changes: 16 additions & 4 deletions crates/handler/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::item_or_result::FrameInitOrResult;
use crate::{precompile_provider::PrecompileProvider, ItemOrResult};
use crate::{CallFrame, CreateFrame, FrameData, FrameResult};
use context::result::FromStringError;
use context::Transaction;
use context_interface::context::ContextError;
use context_interface::local::{FrameToken, OutFrame};
use context_interface::ContextTr;
Expand All @@ -21,11 +22,12 @@ use interpreter::{
FrameInput, Gas, InputsImpl, InstructionResult, Interpreter, InterpreterAction,
InterpreterResult, InterpreterTypes, SharedMemory,
};
use precompile::PrecompileId;
use primitives::{
constants::CALL_STACK_LIMIT,
hardfork::SpecId::{self, HOMESTEAD, LONDON, SPURIOUS_DRAGON},
};
use primitives::{keccak256, Address, Bytes, U256};
use primitives::{keccak256, Address, Bytes, B256, U256};
use state::Bytecode;
use std::borrow::ToOwned;
use std::boxed::Box;
Expand Down Expand Up @@ -169,7 +171,6 @@ impl EthFrame<EthInterpreter> {

// Create subroutine checkpoint
let checkpoint = ctx.journal_mut().checkpoint();

// Touch address. For "EIP-158 State Clear", this will erase empty accounts.
if let CallValue::Transfer(value) = inputs.value {
// Transfer value from caller to called account
Expand All @@ -183,7 +184,7 @@ impl EthFrame<EthInterpreter> {
}
}

let interpreter_input = InputsImpl {
let mut interpreter_input = InputsImpl {
target_address: inputs.target_address,
caller_address: inputs.caller,
bytecode_address: Some(inputs.bytecode_address),
Expand All @@ -193,6 +194,17 @@ impl EthFrame<EthInterpreter> {
let is_static = inputs.is_static;
let gas_limit = inputs.gas_limit;

// If the call's bytecode address is the TxHash precompile address,
// fetch the transaction hash from Tx and pass the hash to the
// interpreter by overwriting the interpreter_input's input with the hash.
if let Some(tx_hash_addr) = PrecompileId::TxHash.mainnet_address() {
if inputs.bytecode_address == tx_hash_addr {
let tx_hash = ctx.tx().tx_hash();
interpreter_input.input =
CallInput::Bytes(Bytes::copy_from_slice(tx_hash.as_ref()));
}
}

if let Some(result) = precompiles
.run(
ctx,
Expand Down Expand Up @@ -308,7 +320,7 @@ impl EthFrame<EthInterpreter> {
.journal_mut()
.nonce_bump_journal_entry(inputs.caller);
}

// Create address
let mut init_code_hash = None;
let created_address = match inputs.scheme {
Expand Down
2 changes: 1 addition & 1 deletion crates/handler/src/pre_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ pub fn validate_against_state_and_deduct_caller<
caller_account.info.nonce = caller_account.info.nonce.saturating_add(1);
}
}

journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call());
Ok(())
}
Expand Down
4 changes: 4 additions & 0 deletions crates/op-revm/src/transaction/abstraction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ impl<T: Transaction> Transaction for OpTransaction<T> {
fn authorization_list(&self) -> impl Iterator<Item = Self::Authorization<'_>> {
self.base.authorization_list()
}

fn tx_hash(&self) -> B256 {
self.base.tx_hash()
}
}

impl<T: Transaction> OpTxTr for OpTransaction<T> {
Expand Down
7 changes: 6 additions & 1 deletion crates/precompile/src/id.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;

use primitives::{address, Address};
use primitives::{address, supra_constants::TX_HASH_ADDRESS, Address};

use crate::{Precompile, PrecompileSpecId};

Expand Down Expand Up @@ -44,6 +44,8 @@ pub enum PrecompileId {
Bls12MapFp2ToGp2,
/// ECDSA signature verification over the secp256r1 elliptic curve (also known as P-256 or prime256v1).
P256Verify,
/// Transaction hash precompile.
TxHash,
/// Custom precompile identifier.
Custom(Cow<'static, str>),
}
Expand Down Expand Up @@ -78,6 +80,7 @@ impl PrecompileId {
Self::Bls12MapFpToGp1 => address!("0x0000000000000000000000000000000000000010"),
Self::Bls12MapFp2ToGp2 => address!("0x0000000000000000000000000000000000000011"),
Self::P256Verify => address!("0x0000000000000000000000000000000000000012"),
Self::TxHash => TX_HASH_ADDRESS,
Self::Custom(_) => return None,
};
Some(address)
Expand All @@ -104,6 +107,7 @@ impl PrecompileId {
Self::Bls12MapFpToGp1 => "BLS12_MAP_FP_TO_G1",
Self::Bls12MapFp2ToGp2 => "BLS12_MAP_FP2_TO_G2",
Self::P256Verify => "P256VERIFY",
Self::TxHash => "TX_HASH",
Self::Custom(a) => a.as_ref(),
}
}
Expand Down Expand Up @@ -173,6 +177,7 @@ impl PrecompileId {
crate::secp256r1::P256VERIFY_OSAKA
}
}
Self::TxHash => crate::tx_hash::TX_HASH,
Self::Custom(_) => return None,
};

Expand Down
3 changes: 3 additions & 0 deletions crates/precompile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub mod kzg_point_evaluation;
pub mod modexp;
pub mod secp256k1;
pub mod secp256r1;
pub mod tx_hash;
pub mod utilities;

pub use id::PrecompileId;
Expand Down Expand Up @@ -195,6 +196,7 @@ impl Precompiles {
INSTANCE.get_or_init(|| {
let mut precompiles = Self::cancun().clone();
precompiles.extend(bls12_381::precompiles());
precompiles.extend([tx_hash::TX_HASH]);
precompiles
})
}
Expand Down Expand Up @@ -399,6 +401,7 @@ pub enum PrecompileSpecId {
/// * `BLS12_PAIRING_CHECK` at address 0x0f
/// * `BLS12_MAP_FP_TO_G1` at address 0x10
/// * `BLS12_MAP_FP2_TO_G2` at address 0x11
/// * `TX_HASH` at address 0x53555001
PRAGUE,
/// Osaka spec added changes to modexp precompile:
/// * [`EIP-7823: Set upper bounds for MODEXP`](https://eips.ethereum.org/EIPS/eip-7823).
Expand Down
9 changes: 9 additions & 0 deletions crates/precompile/src/tx_hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! TX_HASH precompile is added to return the transaction hash of the
//! transaction
use primitives::supra_constants::TX_HASH_ADDRESS;

use crate::{identity::identity_run, Precompile, PrecompileId};

/// TX_HASH precompile
pub const TX_HASH: Precompile =
Precompile::new(PrecompileId::TxHash, TX_HASH_ADDRESS, identity_run);
1 change: 1 addition & 0 deletions crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub mod eip7907;
pub mod eip7918;
pub mod hardfork;
mod once_lock;
pub mod supra_constants;

pub use constants::*;
pub use once_lock::OnceLock;
Expand Down
Loading