# 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. For a one-page diagram, see the [Architecture Overview](/introduction/architecture-overview.md).

## Overview

When you send a Facet transaction to Ethereum's `0xface7` address, Facet nodes automatically detect it and include it in the Facet block for the corresponding 12-second slot. Facet produces blocks every 12 seconds regardless of whether Ethereum produced an L1 block in that slot. If L1 produced a block, the slot’s Facet block includes all `0xface7` inbox transactions from that L1 block in exact order. If L1 skipped the slot (no L1 block), Facet still produces a filler block with no inbox transactions. This is a deterministic process—no sequencer or admin can interfere.

<figure><img src="/files/7XViqguzZeY6JlE2vDgZ" alt=""><figcaption><p>Facet architecture follows Ethereum's consensus/execution split</p></figcaption></figure>

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 calldata
* `eth_getBlockReceipts`: Retrieves logs and transaction status

### 2. Facet Transaction Detection

Valid Facet transactions are identified by:

* **Calldata transactions**: `to` address equals `address(0xface7)` with receipt status = 1
* **Event log transactions**: Exactly one topic equal to `bytes32(uint256(0xface7))` with payload in data field

**One Transaction Per Ethereum Transaction Rule:**

* Each Ethereum transaction contributes at most ONE Facet transaction to the L2 block
* If multiple valid Facet payloads exist (e.g., calldata + event, or multiple events), only the first is processed
* Processing order: Calldata is checked first, then events in log index order
* Additional candidates are silently ignored (not an error condition)

### 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 0x7D Transactions

Facet executes Facet payloads as deposit transactions of type `0x7D` (like Optimism’s `0x7E` deposit tx, with Facet-specific fields/semantics). The effective L2 transaction has the following data model:

```
// Pseudocode: DepositTx
SourceHash:            bytes32   // The tx hash of the L1 transaction that originated the Facet payload
From:                  address   // For calldata-originated payloads, this is the L1 EOA that signed the envelope; for log-originated payloads, this is the emitting contract address after aliasing (see below)
To:                    address?  // Destination address; `nil` for contract creation
Mint:                  uint256?  // FCT minted on L2 and locked on L1; nil if none
Value:                 uint256   // FCT transferred from L2 balance (applied after Mint)
Gas:                   uint64    // execution gas limit
IsSystemTransaction:   bool      // Legacy field, always `false`
Data:                  bytes     // calldata
```

Transaction hash computation:

* The typed-transaction hash uses type `0x7D` and standard serialization of the above fields.
* **Important**: The `Mint` field is excluded from the hash by treating it as zero/nil for hashing purposes. In other words, changes to `Mint` do not affect the transaction hash.

### 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 block times are fixed at 12-second intervals
* When an L1 block exists for a slot, its inbox transactions appear in that slot’s Facet block
* When a slot has no L1 block, Facet produces a filler block for that slot (no inbox transactions)

### 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:

1. Each transaction attempts to buy gas sequentially
2. If insufficient gas remains in block, transaction fails
3. Next transaction attempts to buy gas
4. 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 = l1_tx_hash
```

### L1 Info Transaction Format

```
{
  type: 0x7D,
  to: L1_INFO_PRECOMPILE,
  data: abi.encode(
    block_number,
    block_timestamp,
    base_fee,
    block_hash,
    sequence_number
    ...fct_fields
  )
}
```

## Validation Process

### Deterministic Derivation

Chain state can be validated by:

1. Fetching L1 data from any Ethereum RPC
2. Running facet-node derivation logic
3. 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](https://github.com/0xFacet/facet-node): Consensus client implementation
* [facet-geth](https://github.com/0xFacet/facet-geth): Execution client (op-geth fork)
* [Optimism Specs](https://specs.optimism.io/): Deposit transaction specification


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.facet.org/reference/chain-state-derivation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
