Chain State Derivation
How does a transaction sent to Ethereum become part of the Facet chain? This document explains both the high-level process and detailed technical implementation.
Overview
When you send a Facet transaction to Ethereum's 0xface7
address, Facet nodes automatically detect it and include it in the next Facet block. This happens through a deterministic process where nodes monitor Ethereum, extract valid transactions, and apply them in order - no sequencer or admin can interfere.

The system uses two components: facet-node
monitors L1 and builds blocks, while facet-geth
executes transactions and maintains state. This architecture ensures that anyone running these components will derive exactly the same chain state from the same Ethereum data.
Transaction Processing Pipeline
1. L1 Block Monitoring
facet-node
monitors L1 blocks using these RPC calls:
eth_getBlockByNumber
: Retrieves transaction calldataeth_getBlockReceipts
: Retrieves logs and transaction status
2. Facet Transaction Detection
Valid Facet transactions are identified by:
Calldata transactions:
to
address equalsaddress(0xface7)
Event log transactions: Single topic equals
bytes32(uint256(0xface7))
3. Transaction Decoding
Facet transactions must decode to this structure:
{
chain_id: uint256
to: address
value: uint256
gas_limit: uint256
data: bytes
mine_boost: uint256
}
Deposit Transaction Construction
Type 0x7E Transactions
Facet uses Optimism's Deposit Transaction type with modifications:
Standard fields (copied from Facet transaction):
to
: Destination addressvalue
: ETH value (always 0 in practice)gas_limit
: Gas limit for executiondata
: Transaction calldata
Additional fields:
source_hash
: Unique identifier computed from L1 block and transaction indexl1_tx_origin
: EOA that initiated the L1 transactionfrom
: Transaction signer (calldata) or emitting contract (logs)mint
: FCT amount to mint before execution
Address Aliasing
For log-originated transactions, the from
address is aliased:
aliased_address = original_address + 0x1111000000000000000000000000000000001111
This prevents contracts from impersonating EOAs.
Block Construction
L1 Attributes Transaction
Every Facet block begins with an L1 attributes transaction containing:
L1 block number
L1 block timestamp
L1 block hash
Sequence number
Block Timing Rules
Facet blocks have 12-second slots
Empty "filler blocks" maintain timing when L1 blocks are sparse
Block timestamps must align with 12-second intervals
Engine API Communication
Blocks are sent to facet-geth using:
engine_forkchoiceUpdatedV2
engine_newPayloadV2
engine_getPayloadV2
Gas Mechanics
Sequential Gas Buying
Unlike standard EVM chains:
Each transaction attempts to buy gas sequentially
If insufficient gas remains in block, transaction fails
Next transaction attempts to buy gas
Block gas limit is not pre-validated
FCT Minting Rules
For contract-initiated transactions:
Contract cannot increase its own FCT balance
Excess minted FCT transfers to L1 transaction origin
Prevents contracts from self-funding
Base Fee Only
No priority fee mechanism
All transactions pay current base fee
Simplifies gas pricing model
State Transition Differences
Invalid Block Handling
facet-geth modifications ensure:
Invalid blocks cannot be submitted by facet-node
Pre-check errors affect individual transactions, not entire block
Chain continues processing subsequent transactions
Gas Limit Validation
Standard EVM: sum(tx.gas_limit) <= block.gas_limit
Facet: Each transaction validated independently during execution
Data Structures
Source Hash Computation
source_hash = keccak256(
l1_block_hash ||
uint64(log_index || sequence_number)
)
L1 Info Transaction Format
{
type: 0x7E,
to: L1_INFO_PRECOMPILE,
data: abi.encode(
block_number,
block_timestamp,
base_fee,
block_hash,
sequence_number
)
}
Validation Process
Deterministic Derivation
Chain state can be validated by:
Fetching L1 data from any Ethereum RPC
Running facet-node derivation logic
Comparing resulting state roots
Required L1 Data
Block headers (number, timestamp, hash)
Transaction receipts (status, logs)
Transaction calldata
Consensus Rules
All nodes following these rules will:
Derive identical state from same L1 data
Produce identical block sequences
Calculate identical state roots
Implementation References
facet-node: Consensus client implementation
facet-geth: Execution client (op-geth fork)
Optimism Specs: Deposit transaction specification
Last updated