This EIP introduces a new EIP-2718 transaction type called the "Composable transaction". The base transaction fields follow EIP-1559 with the access list removed. Instead of fixed-position signature fields, all signatures are encoded as typed capabilities in a trailing RLP list. Each capability carries a capability type and a signature type, providing domain separation and future-proofing for alternative signature schemes. A payer signature capability enables native transaction sponsorship. The signing hash for each capability includes only the capabilities that precede it, allowing both sender-first and payer-first signing flows without circular dependencies.
This is a simpler alternative to EIP-8141 (Frame Transaction) which requires new opcodes, frame modes, and per-frame gas accounting. The Composable transaction achieves sponsorship with zero new opcodes and minimal changes to transaction processing.
Each Ethereum upgrade has introduced new transaction types for new capabilities: EIP-1559 for priority fees, EIP-4844 for blobs, and EIP-7702 for authorizations. Both EIP-4844 and EIP-7702 extend and reuse mostly the fields from EIP-1559, yet each required an entirely new transaction type. This leads to combinatorial growth: new features cannot be combined across types. This EIP proposes a single extensible transaction format where new capabilities are added as typed capabilities, allowing future enhancements without new transaction types.
Transaction sponsorship — where a third party pays gas on behalf of the sender — has been a long-sought feature. EIP-8141 proposes a powerful but complex solution using execution frames, new opcodes (APPROVE, TXPARAMLOAD), and per-frame gas budgets. This complexity raises the implementation burden on all clients and increases the attack surface.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
| Parameter | Value |
|---|---|
COMPOSABLE_TX_TYPE |
0x05 |
CAP_SENDER_SIGNATURE |
0x00 |
CAP_PAYER_SIGNATURE |
0x01 |
SIG_BLINDED |
0x00 |
SIG_SECP256K1 |
0x01 |
SIG_ED25519 |
0x02 |
A new EIP-2718 transaction is introduced where the TransactionType is COMPOSABLE_TX_TYPE and the TransactionPayload is the RLP serialization of:
rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas,
gas_limit, to, value, data, capabilities])
capabilities = [capability_0, capability_1, ...]
The fields chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, and data follow the same semantics as EIP-1559.
The capabilities field is an RLP list of typed capabilities. Each capability is itself an RLP list whose first element is the capability type identifier.
The EIP-2718 ReceiptPayload for this transaction is rlp([status, cumulative_transaction_gas_used, logs_bloom, logs]).
The signature_type field in a capability denotes which scheme is used. There is one special blinding type used only in signing hash calculations, and two active signature schemes.
Blinded (SIG_BLINDED = 0x00):
Format: [signature_type] (empty payload)
Used only in signing hash calculations when computing the hash for a capability that has not yet been signed. When a capability's signature is blinded, SIG_BLINDED replaces the actual signature type, making the blinding explicit and unambiguous. In the final transaction, all capabilities MUST use SIG_SECP256K1 or SIG_ED25519; SIG_BLINDED appears only in signing hashes.
SECP256K1 (SIG_SECP256K1 = 0x01):
Format: [signature_type, y_parity, r, s]
y_parity: The recovery ID (0 or 1) for ECDSA signature recovery.r, s: ECDSA signature components.The address is recovered via ecrecover(signing_hash, y_parity, r, s) where signing_hash is computed as defined in Signing Hash.
ED25519 (SIG_ED25519 = 0x02):
Format: [signature_type, signature]
signature: A 64-byte Ed25519 signature.The address is verified by checking the signature against the account's Ed25519 public key.
0x00)[CAP_SENDER_SIGNATURE, signature_type, ...]
CAP_SENDER_SIGNATURE (0x00): capability type identifier.signature_type: Either SIG_SECP256K1 or SIG_ED25519 (see Signature Schemes).The recovered address is the transaction origin (tx.origin) and the account whose nonce is consumed.
0x01)[CAP_PAYER_SIGNATURE, signature_type, ...]
CAP_PAYER_SIGNATURE (0x01): capability type identifier.signature_type: Either SIG_SECP256K1 or SIG_ED25519 (see Signature Schemes).When present, the recovered address is the payer account that is charged for gas instead of the sender.
The signing hash includes all capabilities (both sender and payer), but the capability being signed has SIG_BLINDED as its signature type, with no signature payload.
For a transaction with sender and payer capabilities, the signing hash is:
signing_hash(sender_or_payer) = keccak256(COMPOSABLE_TX_TYPE || rlp([
chain_id,
nonce,
max_priority_fee_per_gas,
max_fee_per_gas,
gas_limit,
to,
value,
data,
[
[CAP_SENDER_SIGNATURE, sig_type_s, sig_or_blinded_s],
[CAP_PAYER_SIGNATURE, sig_type_p, sig_or_blinded_p]
]
]))
Where each capability uses either:
SIG_BLINDED (no payload) if that capability is being signed or it is later in capability list.SIG_SECP256K1 or SIG_ED25519 with the actual signature payload if the capability has already been signedWhere:
A valid Composable transaction MUST satisfy the following:
capabilities list MUST contain exactly one sender signature capability (CAP_SENDER_SIGNATURE).capabilities list MAY contain at most one payer signature capability (CAP_PAYER_SIGNATURE).capabilities list MUST NOT contain any capability types not defined by this or future EIPs.signature_type in each capability MUST be either SIG_SECP256K1 (0x01) or SIG_ED25519 (0x02).s value MUST be less than or equal to secp256k1n/2, as specified in EIP-2.nonce.Each capability incurs intrinsic gas costs to account for both the size of the capability data and the cryptographic work required for signature verification. These costs are included in the transaction's intrinsic gas.
<-- TODO -->
EIP-8141 introduces frames, new opcodes, per-frame gas accounting, and multiple execution modes to achieve sponsorship. The Composable transaction achieves the same result by adding a single payer signature capability to the transaction model, with no new opcodes or execution modes. The payer simply co-signs the transaction and their account is charged for gas, minimizing implementation burden and attack surface.
Including the capability type as the first element of the RLP list prevents cross-role signature confusion. Without this, a sender and payer signing the same transaction at the same index would produce the same signing hash, allowing one signature to be substituted for the other.
The signing hash at index i includes all capabilities [0..i), creating a chain of commitment where each successive signer endorses all prior signers. This avoids circular dependencies while allowing flexible ordering — both sender-first and payer-first flows are valid with clear trust semantics.
This EIP introduces a new transaction type and does not modify the behavior of existing transaction types. No backward compatibility issues are expected.
The capability type as the first element of the signing hash prevents a signature intended for one role (sender) from being reused in another role (payer). Without this, an attacker could reinterpret a sender's signature as a payer commitment or vice versa.
The payer's signature commits to the full transaction parameters including the sender's nonce. Since the sender's nonce is incremented on each transaction, a payer signature cannot be replayed across different transactions.
Copyright and related rights waived via CC0.