The tempo-evm crate implements Tempo’s EVM execution layer, built on top of Reth’s EVM framework. It handles block execution, transaction processing, and Tempo-specific gas accounting.
Installation
[dependencies]
tempo-evm = "0.1.0"
Core Types
TempoEvmConfig
Main EVM configuration for Tempo.
use tempo_evm::TempoEvmConfig;
use std::sync::Arc;
use tempo_chainspec::TempoChainSpec;
// Create EVM config
let chain_spec = Arc::new(TempoChainSpec::mainnet());
let evm_config = TempoEvmConfig::new(chain_spec);
// Access chain spec
let spec = evm_config.chain_spec();
// Get mainnet config
let mainnet = TempoEvmConfig::mainnet();
Fields:
inner
EthEvmConfig<TempoChainSpec, TempoEvmFactory>
Inner Ethereum EVM config with Tempo chain spec
Block assembly logic for building new blocks
Source: crates/evm/src/lib.rs:47-82
TempoEvmFactory
Factory for creating Tempo EVM instances.
use tempo_evm::evm::TempoEvmFactory;
// TempoEvmFactory implements:
// - EvmFactory trait
// - Creates TempoEvm instances with Tempo-specific handlers
Source: crates/evm/src/evm/mod.rs
Block Execution
TempoBlockExecutionCtx
Execution context for processing Tempo blocks.
use tempo_evm::TempoBlockExecutionCtx;
use std::collections::HashMap;
pub struct TempoBlockExecutionCtx<'a> {
/// Standard Ethereum execution context
pub inner: EthBlockExecutionCtx<'a>,
/// Gas limit for general (non-payment) transactions
pub general_gas_limit: u64,
/// Gas limit for payment lane transactions
pub shared_gas_limit: u64,
/// Validator set for subblock fee distribution
pub validator_set: Option<&'a [B256]>,
/// Mapping of validator keys to fee recipients
pub subblock_fee_recipients: HashMap<PartialValidatorKey, Address>,
}
Source: crates/evm/src/context.rs:14
TempoNextBlockEnvAttributes
Attributes for building the next block.
use tempo_evm::TempoNextBlockEnvAttributes;
use reth_evm::NextBlockEnvAttributes;
pub struct TempoNextBlockEnvAttributes {
/// Standard Ethereum block attributes
pub inner: NextBlockEnvAttributes,
/// General gas limit
pub general_gas_limit: u64,
/// Shared gas limit
pub shared_gas_limit: u64,
/// Millisecond precision timestamp
pub timestamp_millis_part: u64,
/// Subblock fee recipient mapping
pub subblock_fee_recipients: HashMap<PartialValidatorKey, Address>,
}
Source: crates/evm/src/context.rs
State Access
TempoStateAccess
Trait for accessing Tempo-specific state.
use tempo_evm::TempoStateAccess;
use alloy_primitives::{Address, U256};
pub trait TempoStateAccess {
/// Get the fee token address for a transaction
fn get_fee_token(
&mut self,
tx_env: &TxEnv,
fee_payer: Address,
spec: SpecId,
) -> Result<Address, Error>;
/// Get token balance for an address
fn get_token_balance(
&mut self,
token: Address,
account: Address,
spec: SpecId,
) -> Result<U256, Error>;
}
Source: tempo-revm crate (re-exported)
Block Assembly
TempoBlockAssembler
Assembles blocks from transactions and system transactions.
use tempo_evm::TempoBlockAssembler;
use std::sync::Arc;
// Create assembler
let chain_spec = Arc::new(TempoChainSpec::mainnet());
let assembler = TempoBlockAssembler::new(chain_spec);
// Assembles:
// - User transactions
// - Subblock metadata system transaction
// - TIPFeeManager settlement system transaction
Source: crates/evm/src/assemble.rs
Receipt Building
TempoReceiptBuilder
Builds transaction receipts with Tempo-specific fields.
use tempo_evm::TempoReceiptBuilder;
// Adds:
// - feeToken field
// - feePayer field
// - Proper log indexing
Source: crates/evm/src/block.rs
Gas Parameters
Tempo uses custom gas parameters defined in the tempo-revm crate:
use tempo_evm::tempo_gas_params;
// Get gas params for a hardfork
let params = tempo_gas_params(spec_id);
// Parameters (TIP-1000):
// - CREATE: 16,000
// - CREATE2: 16,000
// - SSTORE_SET: 16,000
// - SSTORE_RESET: 800
// - REFUND_SSTORE_CLEARS: 800
References: TIP-1000
Block Environment
TempoBlockEnv
Block environment with millisecond timestamp precision.
use tempo_evm::TempoBlockEnv;
pub struct TempoBlockEnv {
/// Standard block environment
pub inner: BlockEnv,
/// Millisecond component (0-999)
pub timestamp_millis_part: u64,
}
// Full timestamp:
let timestamp_ms = block_env.inner.timestamp.to::<u64>() * 1000
+ block_env.timestamp_millis_part;
Source: tempo-revm crate (re-exported)
Halt Reasons
TempoHaltReason
Tempo-specific transaction halt reasons.
use tempo_evm::TempoHaltReason;
pub enum TempoHaltReason {
/// Invalid fee token
InvalidFeeToken,
/// Insufficient fee token balance
InsufficientFeeTokenBalance,
/// Invalid nonce key
InvalidNonceKey,
/// Transaction expired (past valid_before)
TransactionExpired,
/// Transaction not yet valid (before valid_after)
TransactionNotYetValid,
/// Invalid key authorization
InvalidKeyAuthorization,
// ... other reasons
}
Source: tempo-revm crate (re-exported)
Context Creation
The TempoEvmConfig provides methods to create execution contexts:
use tempo_evm::TempoEvmConfig;
use reth_primitives_traits::SealedBlock;
let evm_config = TempoEvmConfig::mainnet();
// Create context from existing block
let ctx = evm_config.context_for_block(&sealed_block)?;
// Create context for next block
let ctx = evm_config.context_for_next_block(
&parent_header,
next_block_attributes
)?;
Block Context:
- Decodes subblock metadata from system transaction
- Extracts validator -> fee_recipient mapping
- Calculates gas limits
Next Block Context:
- Uses provided attributes
- Sets up subblock fee recipients
- Configures gas limits
Source: crates/evm/src/lib.rs:183-245
EVM Environment
Create EVM environments for transaction execution:
use tempo_evm::TempoEvmConfig;
use tempo_primitives::TempoHeader;
let evm_config = TempoEvmConfig::mainnet();
// Create EVM env from header
let evm_env = evm_config.evm_env(&header)?;
// Create EVM env for next block
let evm_env = evm_config.next_evm_env(
&parent_header,
&next_block_attributes
)?;
The environment includes:
- Chain ID and spec ID
- Block environment (number, timestamp, gas limits, etc.)
- Configuration environment (gas params, hard fork rules)
- Tempo-specific parameters (timestamp_millis_part)
Source: crates/evm/src/lib.rs:122-181
Gas Limit Calculation
Tempo splits block gas limit into multiple lanes:
// Block gas limit: 500M
let block_gas_limit = 500_000_000;
// Shared (payment) lane: block_gas_limit / 10
let shared_gas_limit = block_gas_limit / 10; // 50M
// General lane (T1+): Fixed 30M
let general_gas_limit = 30_000_000;
// Remaining for other lanes
let remaining = block_gas_limit - shared_gas_limit - general_gas_limit;
References: TIP-1017
Source: tempo-consensus crate constant TEMPO_SHARED_GAS_DIVISOR
Error Types
TempoEvmError
use tempo_evm::TempoEvmError;
pub enum TempoEvmError {
/// No subblock metadata found in block
NoSubblockMetadataFound,
// ... other errors
}
Source: crates/evm/src/error.rs
Example: Executing a Block
use tempo_evm::{TempoEvmConfig, TempoBlockExecutionCtx};
use reth_primitives_traits::SealedBlock;
use std::sync::Arc;
#[tokio::main]
async fn main() -> eyre::Result<()> {
// Setup
let chain_spec = Arc::new(TempoChainSpec::mainnet());
let evm_config = TempoEvmConfig::new(chain_spec);
// Get sealed block
let sealed_block: SealedBlock<Block> = get_block().await?;
// Create execution context
let ctx = evm_config.context_for_block(&sealed_block)?;
// Create EVM environment
let evm_env = evm_config.evm_env(sealed_block.header())?;
// Execute block with context and env
// (actual execution requires full EVM setup)
Ok(())
}
Features
rpc - RPC type conversions and Tempo-specific RPC handlers
engine - Engine API support for block building
See Also