diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 477cd58db9..51e1f295fa 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -40,7 +40,7 @@ serde = { version = "1.0", default-features = false, features = ["derive", "rc"] hex = { version = "0.4", default-features = false } [features] -default = ["std", "c-kzg"] +default = ["std", "c-kzg", "taiko"] std = [ "serde?/std", "alloy-primitives/std", diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 4ba4ba6f64..bb198919c8 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -802,15 +802,12 @@ mod op_tests { } } - - #[cfg(all(feature = "taiko", not(feature = "optimism")))] #[test] fn taiko_test() { // TODO(Cecilia): taiko tests } - #[cfg(test)] mod tests { use super::*; diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index 54d3357726..626d754824 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -62,37 +62,7 @@ pub enum SpecId { SHANGHAI = 18, CANYON = 19, CANCUN = 20, - ECOTONE = 21, - LATEST = u8::MAX, -} - -/// Specification IDs and their activation block. -/// -/// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) -#[cfg(all(feature = "taiko", not(feature = "optimism")))] -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, enumn::N)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum SpecId { - FRONTIER = 0, - FRONTIER_THAWING = 1, - HOMESTEAD = 2, - DAO_FORK = 3, - TANGERINE = 4, - SPURIOUS_DRAGON = 5, - BYZANTIUM = 6, - CONSTANTINOPLE = 7, - PETERSBURG = 8, - ISTANBUL = 9, - MUIR_GLACIER = 10, - BERLIN = 11, - LONDON = 12, - ARROW_GLACIER = 13, - GRAY_GLACIER = 14, - MERGE = 15, - SHANGHAI = 16, - CANCUN = 17, - KATLA = 18, + ECOTONE = 21, LATEST = u8::MAX, } @@ -455,10 +425,10 @@ mod tests { // TODO(Cecilia): update this range of bits #[test] fn test_katla_post_merge_hardforks() { - assert!(SpecId::enabled(SpecId::MERGE)); - assert!(SpecId::enabled(SpecId::SHANGHAI)); - assert!(!SpecId::enabled(SpecId::CANCUN)); - assert!(!SpecId::enabled(SpecId::LATEST)); - assert!(SpecId::enabled(SpecId::KATLA)); + assert!(SpecId::enabled(SpecId::KATLA, SpecId::MERGE)); + assert!(SpecId::enabled(SpecId::KATLA, SpecId::SHANGHAI)); + assert!(!SpecId::enabled(SpecId::KATLA, SpecId::CANCUN)); + assert!(!SpecId::enabled(SpecId::KATLA, SpecId::LATEST)); + assert!(SpecId::enabled(SpecId::KATLA, SpecId::KATLA)); } } diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 41578c1335..231931d3fa 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -41,7 +41,7 @@ criterion = "0.5" indicatif = "0.17" [features] -default = ["std", "c-kzg", "secp256k1"] +default = ["std", "c-kzg", "secp256k1", "taiko"] std = ["serde?/std", "serde_json?/std", "serde_json?/preserve_order", "revm-interpreter/std", "revm-precompile/std"] serde = ["dep:serde", "dep:serde_json", "revm-interpreter/serde"] arbitrary = ["revm-interpreter/arbitrary"] diff --git a/crates/revm/src/taiko/handler_register.rs b/crates/revm/src/taiko/handler_register.rs index 972f4e0237..07e7a3b96f 100644 --- a/crates/revm/src/taiko/handler_register.rs +++ b/crates/revm/src/taiko/handler_register.rs @@ -2,7 +2,7 @@ use crate::{ handler::{ - mainnet::{self, deduct_caller_inner}, + mainnet::{self, deduct_caller, deduct_caller_inner, end, last_frame_return, output}, register::EvmHandler, }, interpreter::{return_ok, return_revert, Gas, InstructionResult}, @@ -12,3 +12,88 @@ use crate::{ }, Context, }; +use alloc::sync::Arc; +use core::ops::Mul; +use SpecId::LONDON; + +pub fn taiko_handle_register(handler: &mut EvmHandler<'_, EXT, DB>) { + spec_to_generic!(handler.spec_id, { + handler.post_execution.reimburse_caller = Arc::new(reimburse_caller::); + handler.post_execution.reward_beneficiary = Arc::new(reward_beneficiary::); + }); +} + +#[inline] +pub fn reimburse_caller( + context: &mut Context, + gas: &Gas, +) -> Result<(), EVMError> { + if context.evm.env.tx.taiko.is_anchor { + return Ok(()); + } + let caller = context.evm.env.tx.caller; + let effective_gas_price = context.evm.env.effective_gas_price(); + + // return balance of not spend gas. + let (caller_account, _) = context + .evm + .journaled_state + .load_account(caller, &mut context.evm.db) + .map_err(EVMError::Database)?; + + caller_account.info.balance = caller_account + .info + .balance + .saturating_add(effective_gas_price * U256::from(gas.remaining() + gas.refunded() as u64)); + + Ok(()) +} + +/// Reward beneficiary with gas fee. +#[inline] +pub fn reward_beneficiary( + context: &mut Context, + gas: &Gas, +) -> Result<(), EVMError> { + if context.evm.env.tx.taiko.is_anchor { + return Ok(()); + } + let beneficiary = context.evm.env.block.coinbase; + let effective_gas_price = context.evm.env.effective_gas_price(); + + // transfer fee to coinbase/beneficiary. + // EIP-1559 discard basefee for coinbase transfer. Basefee amount of gas is discarded. + let coinbase_gas_price = if SPEC::enabled(LONDON) { + effective_gas_price.saturating_sub(context.evm.env.block.basefee) + } else { + effective_gas_price + }; + + let (coinbase_account, _) = context + .evm + .journaled_state + .load_account(beneficiary, &mut context.evm.db) + .map_err(EVMError::Database)?; + + coinbase_account.mark_touch(); + coinbase_account.info.balance = coinbase_account + .info + .balance + .saturating_add(coinbase_gas_price * U256::from(gas.spend() - gas.refunded() as u64)); + + let treasury = context.evm.env.tx.taiko.treasury; + let basefee = context.evm.env.block.basefee; + + let (treasury_account, _) = context + .evm + .journaled_state + .load_account(treasury, &mut context.evm.db) + .map_err(EVMError::Database)?; + + treasury_account.mark_touch(); + treasury_account.info.balance = treasury_account + .info + .balance + .saturating_add(basefee * U256::from(gas.spend() - gas.refunded() as u64)); + Ok(()) +}