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:
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
max_fee_per_gas
Maximum fee user is willing to pay per unit of gas for transaction inclusion
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])
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.
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 identified by the Facet event signature:
0x00000000000000000000000000000000000000000000000000000000000face7
The event's data payload contains the same RLP-encoded transaction that would be used in the calldata of an EOA-originated Facet transaction.
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
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
Smart contract that emitted the event
Use Case
Direct user interactions
Programmatic/bridged transactions
Best Practices
Chain ID Verification: Always ensure you're using the correct chain ID for your target network (mainnet vs testnet)
Gas Estimation: Properly estimate gas limits to ensure transaction success
Error Handling: Verify that L1 transactions have a successful receipt status before considering the Facet transaction submitted
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 partyAlways validate transaction parameters before submission
Monitor L1 transaction success to ensure proper Facet transaction delivery
Last updated