Facet Transaction Spec

Overview

Facet transactions are the primary mechanism for interacting with the Facet protocol. They follow a format similar to EIP-1559 Ethereum transactions and Optimism's Deposit transactions, with specific adaptations for the Facet ecosystem.

Transaction Format

Facet transactions use the EIP-2718 transaction type 0x46 (70 in base 10) and contain the following fields:

Field
Description

chain_id

Distinguishes the payload as being relevant only to Facet • Mainnet: 1027303 (0xface7 in hex) • Sepolia testnet: 16436858 (0xface7a in hex)

to

L2 recipient's address (EOA or L2 contract). Blank for contract creations

value

Amount of FCT being transferred in the transaction

gas_limit

The gas limit of the L2 transaction

data

EVM input data (ABI encoded contract call or contract creation code)

mine_boost

Optional appended data that increases payload size to increase FCT mining (see below)

Important: Facet transactions have no signature field. The "from" address is inferred from the properties of the Ethereum transaction in which they are delivered.

Serialization Format

Facet transactions must be serialized in this specific format for Facet nodes to process them:

0x46 ++ rlp_encode([chain_id, to, value, gas_limit, data, mine_boost])

Fee Model

Facet uses a base-fee-only pricing model on L2. There is no per-transaction priority fee and no max_fee_per_gas field in Facet transactions. All transactions pay the current L2 base fee computed by the protocol.

Execution on L2 (Deposit Type 0x7D)

Facet payloads are executed on L2 as deposit transactions of type 0x7D (125 decimal). The execution-layer transaction includes fields like sourceHash, from, optional mint, value (FCT), gas, isSystemTransaction, and data. For hashing, the typed-transaction hash treats mint as zero/nil so the mint amount does not affect the transaction hash. See Reference → Chain State Derivation for full field definitions and hashing rules.

Transaction Submission Methods

There are two methods to submit Facet transactions to the network:

Method 1: From EOA via Calldata

EOAs (Externally Owned Accounts) can create Facet transactions by sending a successful Ethereum transaction (receipt status = 1) to the Facet inbox address:

0x00000000000000000000000000000000000face7

This L1 transaction acts as an "envelope" that carries the RLP-encoded Facet transaction as a payload within its calldata. The signer of the Ethereum envelope transaction determines the "from" address on the Facet transaction.

Note on ETH value: The L1 envelope transaction to the inbox address must set value = 0. Never send ETH to 0xface7. Any L2 transfer amount should be expressed via the Facet payload’s value field, which is denominated in FCT and applied on L2 during execution.

Implementation Example (TypeScript/Viem)

const transactionData = [
  toHex(l2ChainId),
  to ?? "0x",
  value ? toHex(value) : "0x",
  gasLimit ? toHex(gasLimit) : "0x",
  data ?? "0x",
  mineBoost ?? "0x"
];

const encodedTransaction = concatHex([toHex(70), toRlp(transactionData)]);

const l1Transaction = {
  account: l1WalletClient.account,
  to: "0x00000000000000000000000000000000000face7",
  value: 0n,
  data: encodedTransaction,
  chain: l1WalletClient.chain,
};

await l1WalletClient.sendTransaction(l1Transaction);

Method 2: From L1 Smart Contract via Event Logs

L1 Smart Contracts can create Facet transactions by emitting events with the following specification:

Event Format Requirements

Topic Requirements:

  • Exactly one topic: The event MUST have exactly one topic

  • Topic value: 0x00000000000000000000000000000000000000000000000000000000000face7. This is bytes32(uint256(0xface7)) - the number 0xface7 cast to uint256, then to bytes32.

Data Requirements:

  • Payload location: The entire Facet transaction payload MUST be in the event's data field

  • Payload format: Same RLP-encoded transaction format as calldata method (0x46 + RLP)

  • No indexed parameters: The event MUST NOT have any indexed parameters beyond the single topic

One Transaction Per Ethereum Transaction Rule:

  • Single Facet transaction: Each Ethereum transaction can contain at most ONE valid Facet transaction

  • Multiple candidates: If an Ethereum transaction contains multiple events with the Facet signature, only the first valid Facet transaction is processed

  • Processing order: Calldata is checked before events. Within events, they are processed in log index order

  • Failure semantics: Subsequent Facet transaction candidates in the same Ethereum transaction are silently ignored, not treated as errors

Implementation Example (Solidity)

import { LibRLP } from "lib/solady/src/utils/LibRLP.sol";

contract FacetSender {
    using LibRLP for LibRLP.List;

    bytes32 constant facetEventSignature = 0x00000000000000000000000000000000000000000000000000000000000face7;
    uint8 constant facetTxType = 0x46;

    function sendFacetTransaction(
        uint256 chainId,
        bytes memory to,
        uint256 value,
        uint256 gasLimit,
        bytes memory data,
        bytes memory mineBoost
    ) internal {
        LibRLP.List memory list;

        list.p(chainId);
        list.p(to);
        list.p(value);
        list.p(gasLimit);
        list.p(data);
        list.p(mineBoost);

        bytes memory payload = abi.encodePacked(facetTxType, list.encode());
        
        assembly {
            log1(add(payload, 32), mload(payload), facetEventSignature)
        }
    }
}

Key Differences Between Methods

Aspect
EOA (Calldata)
Smart Contract (Event Log)

Sender Type

Externally Owned Account

L1 Smart Contract

Delivery Method

Transaction calldata to inbox address

Event emission with Facet signature

From Address

EOA that signed the L1 transaction

The aliased address of the smart contract that emitted the event

Use Case

Direct user interactions

Programmatic/bridged transactions

Best Practices

  1. Chain ID Verification: Always ensure you're using the correct chain ID for your target network (mainnet vs testnet)

  2. Gas Estimation: Properly estimate gas limits to ensure transaction success

  3. Error Handling: Verify that L1 transactions have a successful receipt status before considering the Facet transaction submitted

  4. Mine Boost: Use the optional mine_boost field strategically to increase FCT mining rewards when needed

Security Considerations

  • The Facet inbox address (0x00000000000000000000000000000000000face7) has no known private key, ensuring it cannot be controlled by any party

  • Always validate transaction parameters before submission

  • Monitor L1 transaction success to ensure proper Facet transaction delivery

Last updated