> For the complete documentation index, see [llms.txt](https://docs.facet.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facet.org/immutable-sequencing/transaction-spec.md).

# 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`   | <p>Distinguishes the payload as being relevant only to Facet<br>• Mainnet: <code>1027303</code> (<code>0xface7</code> in hex)<br>• Sepolia testnet: <code>16436858</code> (<code>0xface7a</code> in hex)</p> |
| `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)

```typescript
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)

```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](https://docs.facet.org/reference/chain-state-derivation#address-aliasing) 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
