Abstract
This EIP introduces Hash-Committed Account (HCA), a new Ethereum account type where the address is derived from a Merkle root of spending conditions rather than from a public key. The address derivation formula address = tagged_hash("HCAAddr", auth_root)[12:] eliminates public keys from the commitment chain entirely. When spending, the transaction witness contains a leaf script, a Merkle proof, and signature data. Verification proceeds without ecrecover — the sender address is an explicit transaction field. HCA is signature-scheme agnostic: ECDSA leaves work today, post-quantum leaves work when standardized via EIP-7932.
Motivation
The address derivation gap
Ethereum's post-quantum roadmap includes strong proposals for signature validation (EIP-8141), algorithm standardization (EIP-7932), and state storage (EIP-7864). Each changes how transactions are signed, which algorithms are available, or how state is stored. None changes how the address is derived.
After all three proposals are fully deployed, the address derivation formula for a new externally owned account remains:
address = keccak256(secp256k1_public_key)[12:]The public key is permanently coupled to account identity. The first transaction from any EOA exposes this key on-chain via ecrecover. Once exposed, the key becomes a static target for a Cryptographically Relevant Quantum Computer (CRQC) running Shor's algorithm.
This is a commitment problem, not a signature problem. The signature layer can be upgraded via account abstraction. The commitment layer — what the address itself is derived from — has no upgrade path.
The quantum threat
On March 30, 2026, Google Quantum AI published research demonstrating that ECDLP-256 can be broken with fewer than 500,000 physical qubits in a few minutes — a 20-fold reduction from previous estimates. Google set a 2029 internal migration deadline. The paper specifically recommends "refraining from exposing or reusing vulnerable wallet addresses."
Government mandates establish hard deadlines:
- CNSA 2.0 (NSA, September 2022): software and networking equipment MUST migrate to post-quantum cryptography by 2030, with full upgrade by 2033.
- NIST IR 8547 (November 2024): ECDSA with P-256 deprecated after 2030, disallowed after 2035 for all federal systems. Target: widespread PQC adoption by 2035.
The Ethereum Foundation's Post-Quantum portal states: "migrating a decentralized, global protocol takes years of coordination, engineering, and formal verification. The work must begin well before the threat arrives."
HCA's migration across wallets, DeFi protocols, exchanges, L2 sequencers, and hardware wallets will itself require multiple years. Initiating this work in 2026 is consistent with a 2029-2033 migration window.
Why protocol-level, not application-level
A smart contract wallet deployed via CREATE2 can achieve functionally similar behavior — committing an address to an authentication policy via the CREATE2 salt without embedding a public key. This raises the question of whether HCA should exist as a native account type or as an application-layer pattern.
A native account type is justified for three reasons:
- Gas efficiency. A simple HCA spend (single-leaf tree) costs approximately 450 gas for Merkle verification. A CREATE2 smart contract wallet requires deployment gas (~32,000), proxy storage, and delegatecall overhead per transaction.
- Simplicity. HCA account creation requires no factory contract, no proxy pattern, no deployment transaction. A user constructs a Merkle tree, derives an address, and receives funds.
- Protocol clarity. A first-class account primitive signals that quantum-safe address derivation is a protocol-level concern, not an afterthought delegated to application developers.
The precedent exists: BIP-360 introduces Pay-to-Merkle-Root (P2MR) as a native Bitcoin output type alongside Taproot, despite Taproot's script-path spends achieving functionally similar results. HCA is to EIP-8141 what P2MR is to Taproot.
Relationship to existing proposals
HCA is not an account abstraction proposal. Account abstraction (EIP-8141, ERC-4337, EIP-7702) changes how transactions are validated — it decouples signature verification from ECDSA. HCA changes what the address itself commits to — it decouples address derivation from public keys. These operate at different layers:
- EIP-7864: quantum-safe state storage (how data is stored)
- EIP-7932: quantum-safe algorithm registry (which algorithms exist)
- EIP-8141: quantum-safe transaction validation (how you sign)
- HCA: quantum-safe address derivation (what your address commits to)
Together, these four proposals cover every layer of the Ethereum account lifecycle from address creation to transaction execution to state persistence.
Specification
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.
Constants
| Constant | Value | Description |
|---|---|---|
HCA_TX_TYPE | 0x05 | EIP-2718 transaction type identifier |
MAX_TREE_DEPTH | 32 | Maximum Merkle tree depth (supports 2^32 leaves) |
MAX_LEAF_GAS | 100000 | Maximum gas for leaf script execution |
MAX_LEAF_SCRIPT_SIZE | 24576 | Maximum leaf script size in bytes (24 KB) |
MAX_WITNESS_SIZE | 65536 | Maximum witness size in bytes (64 KB) |
MERKLE_BASE_GAS | 200 | Base gas for Merkle proof verification |
MERKLE_GAS_PER_LEVEL | 80 | Gas per Merkle tree level |
Account state changes
An HCA account introduces one new 32-byte field, authRoot, to the account state:
| Field | Size | Description |
|---|---|---|
nonce | 8 bytes | Transaction counter |
balance | 32 bytes | ETH balance in wei |
authRoot | 32 bytes | Merkle root of the authentication policy tree |
codeHash | 32 bytes | keccak256("") (HCA accounts are not contracts) |
The authRoot field MUST be set when the account is first created and MUST NOT be modified except via the rotation mechanism defined in this specification.
An account is identified as an HCA account if authRoot is nonzero and codeHash equals the empty code hash.
Tagged hash construction
HCA uses domain-separated hashing following the BIP-340 tagged hash convention adapted for Keccak-256:
tagged_hash(tag, data) = keccak256(SHA256(tag) || SHA256(tag) || data)The double SHA256(tag) prefix provides provable domain separation between different operations. Five domain tags are defined:
| Tag | Constant | Usage |
|---|---|---|
"HCAAddr" | ADDR | Address derivation |
"HCALeaf" | LEAF | Leaf hash computation |
"HCABranch" | BRANCH | Branch node hash computation |
"HCAWitness" | WITNESS | Transaction signing hash |
"HCARotate" | ROTATE | authRoot rotation authorization |
Different tags MUST produce different outputs for identical inputs. This property ensures that a leaf hash can never equal a branch hash, an address hash can never collide with a witness hash, and cross-protocol collision attacks are prevented.
Leaf structure
A leaf represents a single spending condition. Each leaf is a byte sequence with a 1-byte version prefix:
leaf = version_byte || script_bytecode| Version | Meaning |
|---|---|
0x00 | Reserved (MUST be rejected as invalid) |
0x01 | HCA v1 — EVM bytecode spending condition |
0x02 | EIP-7932 algorithm registry dispatch |
0x03–0x0F | Reserved for future standardized PQ schemes |
0x10–0xFF | Reserved for experimental and application-specific use |
The leaf hash is computed as:
leaf_hash = tagged_hash("HCALeaf", version_byte || script_bytecode)Leaf scripts MUST NOT exceed MAX_LEAF_SCRIPT_SIZE bytes. Leaf scripts MUST NOT be empty. Leaf version 0x00 MUST be rejected during account creation and transaction verification.
Merkle tree construction
The authentication policy tree is a standard binary Merkle tree:
- Compute
leaf_hashfor each leaf. - If the number of leaves is not a power of two, pad by duplicating the last leaf hash until it is.
- Build the tree bottom-up. Each branch node is computed as:
branch_hash = tagged_hash("HCABranch", left_child || right_child)- The root of the tree is the
auth_root:
auth_root = merkle_root([leaf_hash_0, leaf_hash_1, ..., leaf_hash_n])The tree depth MUST NOT exceed MAX_TREE_DEPTH. Leaf ordering is significant — reordering leaves produces a different auth_root. All leaves within a single tree MUST have distinct leaf hashes — duplicate leaves MUST be rejected during tree construction.
Domain separation between leaf and branch hashing (different tagged hash tags) makes leaf-branch confusion attacks impossible by construction.
Address derivation
The HCA address is derived from the auth_root with no public key in the derivation chain:
address = tagged_hash("HCAAddr", auth_root)[12:]The last 20 bytes of the tagged hash output are taken, matching Ethereum's existing 20-byte address format for full EVM compatibility. The tagged_hash("HCAAddr", ...) prefix provides domain separation from EOA addresses (keccak256(pubkey)[12:]), CREATE addresses (keccak256(rlp([sender, nonce]))[12:]), and CREATE2 addresses (keccak256(0xff || factory || salt || init_code_hash)[12:]).
Since tagged_hash already applies keccak256 internally, the address derivation involves a single keccak256 computation with domain-separated input. No additional outer hash is applied.
Transaction type
HCA transactions use EIP-2718 typed transaction envelope with type HCA_TX_TYPE:
HCA_TX_TYPE || RLP([
chain_id,
nonce,
sender, // 20 bytes — explicit HCA address
to, // 20 bytes — recipient
value, // uint256 — wei to transfer
data, // bytes — calldata
max_priority_fee_per_gas, // uint256
max_fee_per_gas, // uint256
access_list, // []
leaf_version, // uint8
leaf_script, // bytes — spending condition bytecode
leaf_index, // uint32 — index in Merkle tree
merkle_proof, // bytes32[] — sibling hashes
witness_data // bytes — signature or proof data
])The sender field is explicit. There is no ECDSA signature recovery. The sender's identity is verified through the witness (Merkle proof + leaf script execution), not through ecrecover.
Witness structure
The witness consists of four components included in the transaction:
| Field | Type | Description |
|---|---|---|
leaf_version | uint8 | Version byte of the spending condition |
leaf_script | bytes | Spending condition bytecode |
merkle_proof | bytes32[] | Sibling hashes from leaf to root |
witness_data | bytes | Signature or other data the leaf script requires |
The total witness size MUST NOT exceed MAX_WITNESS_SIZE.
Verification procedure
Verification of an HCA transaction proceeds in three sequential steps. If any step fails, the transaction MUST be rejected.
Step 1 — Merkle proof verification:
- Compute
leaf_hash = tagged_hash("HCALeaf", leaf_version || leaf_script). - Starting from
leaf_hash, walk themerkle_proofsiblings upward, computing branch hashes at each level:current = tagged_hash("HCABranch", left || right)where the ordering is determined by the leaf index bit at each level. - The final computed root MUST equal the
authRootstored in the sender's account state. - Merkle proof verification MUST use constant-time comparison for the final root equality check to prevent timing side-channel leaks.
Step 2 — Leaf script execution:
- Execute the leaf script in a restricted EVM context (see Leaf Execution Context below).
- The leaf script receives
witness_dataand the transaction signing hash as inputs. - The leaf script MUST return
1(valid). Any other return value, a revert, or an out-of-gas condition MUST be treated as invalid.
Step 3 — Transaction execution:
If both verification steps pass, the transaction executes normally. The HCA address is set as msg.sender. From the perspective of called contracts, the transaction is indistinguishable from one sent by an EOA.
Leaf execution context
Leaf scripts execute in a restricted EVM context to prevent denial-of-service attacks and ensure verification is pure:
Gas limit: Leaf execution MUST NOT exceed MAX_LEAF_GAS (100,000 gas). Gas is metered per-opcode according to the EVM Berlin gas schedule.
Banned opcodes: The following opcodes MUST NOT appear in leaf scripts. Nodes MUST reject transactions containing leaf scripts with banned opcodes.
| Opcode | Reason |
|---|---|
CREATE, CREATE2 | No contract deployment during verification |
SSTORE | No state mutation |
SELFDESTRUCT | No account destruction |
CALL | No external calls (value transfer is a runtime property; banned statically for safety) |
DELEGATECALL | No arbitrary code execution |
LOG0–LOG4 | No event emission |
Permitted opcodes: All other opcodes are permitted, including SLOAD, BALANCE, EXTCODESIZE, EXTCODECOPY, STATICCALL, CALLCODE, and arithmetic/logic opcodes. This allows leaf scripts to read chain state for time-lock and oracle-based conditions.
Gas schedule
| Operation | Gas cost |
|---|---|
| Merkle proof verification (base) | MERKLE_BASE_GAS (200) |
| Merkle proof verification (per level) | MERKLE_GAS_PER_LEVEL (80) |
| Leaf script execution | Metered per-opcode by EVM Berlin schedule, capped at MAX_LEAF_GAS (100,000) |
| Witness calldata (nonzero byte) | 16 gas (standard EIP-2028) |
| Witness calldata (zero byte) | 4 gas (standard EIP-2028) |
Example costs for common configurations:
| Configuration | Merkle gas | Leaf gas (ECDSA) | Total verification |
|---|---|---|---|
| Single leaf (depth 0) | 200 | ~3,000 | ~3,200 |
| 4 leaves (depth 2) | 360 | ~3,000 | ~3,360 |
| 8 leaves (depth 3) | 440 | ~3,000 | ~3,440 |
| 256 leaves (depth 8) | 840 | ~3,000 | ~3,840 |
For comparison, current EOA transaction verification via ecrecover costs 3,000 gas. HCA verification cost is comparable for typical tree depths.
Performance impact
Transaction size: An HCA transaction includes the leaf script and Merkle proof as additional calldata. For a depth-3 tree with a 64-byte ECDSA leaf script and 65-byte signature, the witness adds approximately 225 bytes (64 + 96 + 65) compared to a standard 65-byte ECDSA signature. This overhead is linear in tree depth: 32 additional bytes per Merkle level.
Verification cost: Merkle proof verification requires two keccak256 operations per tree level (approximately 80 gas each). For typical trees (depth 2-8), total Merkle verification costs 360-840 gas — less than the 3,000 gas cost of a single ecrecover operation.
State overhead: One 32-byte authRoot field per HCA account. This is identical to the codeHash field already present in every account. The per-account state overhead is negligible.
Witness data: Unlike state, witness data is per-transaction and not persisted. Witness bytes are priced at standard calldata rates (16 gas/nonzero byte per EIP-2028).
authRoot rotation
An HCA account's authRoot can be updated via a dedicated rotation leaf — a leaf script whose sole purpose is authorizing replacement of the authRoot with a new value.
The rotation procedure:
- The transaction includes a witness spending a rotation-type leaf.
- The leaf script validates the rotation authorization (e.g., verifies a signature over the new
authRoot). - If the leaf script returns valid, the account's
authRootis replaced with the new value provided in the transaction's calldata. - The account nonce is incremented.
The new authRoot MUST be a valid 32-byte value. The new authRoot MUST NOT be zero. The rotation transaction MUST NOT transfer value or execute external calls — it is an authRoot-only state change.
The rotation signing hash uses a dedicated domain tag to prevent cross-context replay:
rotation_hash = tagged_hash("HCARotate",
chain_id || nonce || from || new_auth_root
)Where chain_id and nonce are 8-byte big-endian, from is 20 bytes, and new_auth_root is 32 bytes.
Rotation enables key management operations: adding post-quantum leaves, removing compromised leaves, and upgrading the authentication policy — all without changing the account address.
Transaction signing hash
The signing hash commits to all replay-protection fields, the transaction calldata, and binds the signature to a specific spending condition:
signing_hash = tagged_hash("HCAWitness",
chain_id || nonce || from || to || value ||
data_len || data ||
gas_limit || max_fee_per_gas || max_priority_fee_per_gas ||
leaf_hash
)Field encodings:
| Field | Encoding | Size |
|---|---|---|
chain_id | Big-endian | 8 bytes |
nonce | Big-endian | 8 bytes |
from | Raw bytes | 20 bytes |
to | Raw bytes | 20 bytes |
value | Big-endian | 16 bytes |
data_len | Big-endian length of data | 8 bytes |
data | Raw bytes | Variable |
gas_limit | Big-endian | 8 bytes |
max_fee_per_gas | Big-endian | 16 bytes |
max_priority_fee_per_gas | Big-endian | 16 bytes |
leaf_hash | Raw bytes | 32 bytes |
Including chain_id prevents cross-chain replay. Including from (sender address) prevents cross-account replay. Including nonce prevents same-chain replay. Including leaf_hash binds the signature to the specific spending condition used. Including data_len || data ensures transactions with different calldata produce different signing hashes.
Rationale
Why tagged hash with BIP-340 convention
The tagged_hash(tag, data) = keccak256(SHA256(tag) || SHA256(tag) || data) construction provides guaranteed domain separation between all HCA operations. The BIP-340 convention was chosen because it is well-analyzed, simple to implement, and already in production use across Bitcoin's Taproot ecosystem. The double SHA256 prefix is computed once per tag and can be cached, adding negligible overhead.
An alternative — using a single-byte prefix for domain separation — was considered and rejected because single-byte prefixes risk collisions with RLP-encoded data and do not provide the same formal separation guarantees.
Why single-hash address derivation
The address derivation formula tagged_hash("HCAAddr", auth_root)[12:] applies a single keccak256 computation with domain-separated input. An earlier draft used keccak256(tagged_hash("HCAAddr", auth_root))[12:] with an additional outer hash. Since tagged_hash already applies keccak256 internally, the outer hash was redundant — it added computational cost without improving security properties. The single-hash formula is simpler, faster, and sufficient: the domain separation guarantee comes from the tagged hash construction, not from hash nesting depth.
Why 20-byte addresses
HCA addresses use 20 bytes (tagged_hash(...)[12:]) for full backward compatibility with Ethereum's existing address format. All deployed contracts, ABIs, tooling, block explorers, and wallet software assume 20-byte addresses. The address type in Solidity is 20 bytes.
The security boundary is the 32-byte authRoot, not the 20-byte address. The address is a public identifier; authRoot is the cryptographic commitment. Truncating the identifier does not weaken the commitment.
If Ethereum adopts 32-byte addresses in the future, HCA address derivation can be extended to the full 32-byte tagged hash output in a companion EIP.
Why EVM bytecode leaves
Leaf scripts are EVM bytecode rather than a custom domain-specific language. This decision leverages the existing EVM infrastructure: all Ethereum clients already have EVM interpreters, developers already understand EVM bytecode, and the security model (gas metering, opcode restrictions) is well-understood.
A custom DSL would require new interpreter implementations in every client, new tooling, new security analysis, and new developer education — all for marginal benefit over the existing EVM.
Why depth-32 maximum
A maximum tree depth of 32 supports up to 2^32 (~4 billion) leaves, which exceeds any realistic authentication policy. The gas cost at depth 32 is approximately 2,760 gas for Merkle verification — still cheaper than ecrecover. Deeper trees provide no practical benefit and increase the theoretical maximum witness size.
Why CALL is banned statically
The EVM CALL opcode transfers value as a runtime parameter, making it impossible to distinguish value-bearing calls from zero-value calls through static bytecode analysis alone. Rather than introduce a complex runtime check within the restricted leaf execution context, all CALL invocations are banned statically. Leaf scripts that need to read external state can use STATICCALL, which is permitted and guarantees no state mutation or value transfer.
Why not EIP-8141 + CREATE2
A smart contract wallet deployed via CREATE2 with auth_root as the salt achieves functionally similar address-level commitment. However, this approach requires a factory contract deployment, proxy pattern management, and delegatecall overhead per transaction. A simple HCA account is cheaper to create (no deployment gas), cheaper to use (no proxy overhead), and simpler to understand (no factory/proxy abstraction).
HCA exists alongside EIP-8141 for the same reason BIP-360's P2MR exists alongside Taproot: a purpose-built primitive is simpler, cheaper, and clearer than an emergent pattern built on general-purpose infrastructure.
Why not ZK-STARK proof of key knowledge
ZK-STARK approaches prove knowledge of a private key preimage without revealing the public key on-chain. This protects existing EOA addresses retroactively. However, the address itself is still derived from keccak256(public_key)[12:] — the commitment remains to a public key, only hidden. STARK proofs cost approximately 9.5 million gas per transaction, compared to approximately 3,400 gas for an HCA transaction with a depth-2 tree.
ZK-STARKs are a migration tool for existing accounts. HCA is a construction for new accounts. They are complementary.
Why not hybrid PQC+EC address derivation
Hybrid approaches derive addresses from keccak256(PQ_pubkey || EC_pubkey)[12:]. This commits the address to both a classical and post-quantum public key. However, the address remains derived from public keys — both are eventually exposed. If the PQ scheme is later broken (e.g., lattice cryptanalysis advances), the address commitment is compromised. HCA's security rests on hash functions alone, which is the strongest available assumption against quantum speedup.
Why complement, not compete with EIP-8141
EIP-8141 enables existing accounts to upgrade their signature scheme. HCA enables new accounts to be born without a public key in the commitment chain. EIP-8141 is a migration mechanism. HCA is a native construction. Both are needed: EIP-8141 for the billions of dollars in existing accounts, HCA for every new account created after quantum safety becomes a protocol-level concern.
Backwards Compatibility
Existing accounts
HCA is fully opt-in. All existing EOAs, contract accounts, and EIP-7702 delegated accounts continue to function without modification. No existing transaction types are changed. No existing opcodes are modified.
msg.sender behavior
From the perspective of called contracts, an HCA account's msg.sender is a standard 20-byte address. Contracts receiving calls from HCA accounts cannot distinguish them from EOA calls. All existing contract interfaces, access control patterns, and msg.sender-based authorization continue to work.
Hard fork requirement
HCA requires a hard fork to introduce:
- A new account state field (
authRoot). - A new EIP-2718 transaction type (
HCA_TX_TYPE). - New transaction verification logic (Merkle proof + leaf execution).
This is consistent with other core EIPs that introduce new account types or transaction types.
State tree interaction
The authRoot field is stored in the account's state entry. If EIP-7864 is deployed, authRoot occupies a position in the unified binary tree alongside existing account fields. HCA's internal Merkle tree (for authentication policy) uses keccak256 and is independent of the state tree's hash function selection (BLAKE3 or Poseidon2). The two trees serve different purposes and do not interact.
Test Cases
Tagged hash domain separation
Input:
- Tag:
"HCAAddr" - Data:
0x0000000000000000000000000000000000000000000000000000000000000000(32 zero bytes)
Expected: The output MUST differ from tagged_hash("HCALeaf", same_data), tagged_hash("HCABranch", same_data), tagged_hash("HCAWitness", same_data), and tagged_hash("HCARotate", same_data).
Address derivation
Input:
- Leaves:
[{version: 0x01, script: "OP_CHECKSIG_primary"}, {version: 0x01, script: "OP_CHECKSIG_recovery"}] - Tree: binary Merkle tree, depth 1
Procedure:
- Compute
leaf_hash_0 = tagged_hash("HCALeaf", 0x01 || "OP_CHECKSIG_primary") - Compute
leaf_hash_1 = tagged_hash("HCALeaf", 0x01 || "OP_CHECKSIG_recovery") - Compute
auth_root = tagged_hash("HCABranch", leaf_hash_0 || leaf_hash_1) - Compute
address = tagged_hash("HCAAddr", auth_root)[12:]
Expected: A deterministic 20-byte address. Running the procedure twice with identical inputs MUST produce identical output.
Merkle proof verification
Input:
- Tree with 4 leaves at depth 2
- Proof for leaf at index 0
Expected: MerkleTree::verify(leaf_hash_0, proof_0, auth_root) returns true. MerkleTree::verify(leaf_hash_1, proof_0, auth_root) returns false (wrong leaf, correct proof).
Signing hash replay protection
Input:
- Identical transaction fields on chain_id 1 (mainnet) and chain_id 11155111 (Sepolia)
- Identical leaf_hash
Expected: The two signing hashes MUST differ. This verifies cross-chain replay protection.
Signing hash calldata sensitivity
Input:
- Two transactions with identical fields except
data: one with empty calldata, one with0xdeadbeef - Identical leaf_hash
Expected: The two signing hashes MUST differ. This verifies that calldata is committed to in the signing hash.
Reference Implementation
A Rust reference implementation is available at github.com/eth-hca/hca-rs (v0.2.0). It includes:
- Core modules: hash, merkle, address, witness, rlp, evm, builder
hcaCLI with six commands:create-account,derive-address,generate-proof,verify-proof,encode-tx,signing-hash- Cross-implementation test vectors with hardcoded expected values
- Property-based tests (proptest) and 4 libfuzzer fuzz targets
- Constant-time proof verification (
subtlecrate) - Criterion benchmarks for all operations
Security Considerations
Formal security reduction
HCA's address security reduces to the preimage resistance of keccak256. Given address = tagged_hash("HCAAddr", auth_root)[12:], and since tagged_hash applies keccak256 with domain-separated input, recovering auth_root from address requires a preimage attack on keccak256 truncated to 160 bits: approximately 2^160 classical security and 2^80 under Grover's algorithm.
HCA's authentication security reduces to the collision resistance of the Merkle tree (2^128 birthday bound on keccak256) combined with the security of the chosen leaf signature scheme. The commitment structure (address derivation and Merkle tree) rests entirely on hash function assumptions — no elliptic curve mathematics, no lattice assumptions, no pairing-based cryptography.
Address collision analysis
HCA addresses occupy the same 20-byte address space as existing Ethereum addresses. Cross-type collision (HCA address = existing EOA or contract address) requires finding an auth_root such that tagged_hash("HCAAddr", auth_root)[12:] equals a target address. The tagged_hash domain separator ensures the hash input structure differs from EOA derivation (keccak256(pubkey)), CREATE derivation (keccak256(rlp([sender, nonce]))), and CREATE2 derivation (keccak256(0xff || factory || salt || init_code_hash)). This makes cross-type collision a preimage attack (~2^160), not a birthday attack.
Replay protection
Three replay vectors are mitigated:
| Vector | Mitigation |
|---|---|
| Cross-chain | chain_id included in signing hash |
| Same-chain | nonce incremented per transaction |
| Cross-account | from (sender address) included in signing hash |
Additionally, data (calldata) is included in the signing hash via data_len || data, ensuring transactions with different calldata produce different signatures.
This is identical to the replay protection model used by EIP-155 and EIP-8141 frame transactions.
Leaf-branch domain separation
The use of different tagged hash tags ("HCALeaf" vs "HCABranch") makes it impossible for a leaf hash to equal a branch hash for any input. This prevents second preimage attacks where an attacker attempts to substitute a leaf node for a branch node (or vice versa) in a Merkle proof.
Denial of service via leaf script execution
Unrestricted leaf script execution could enable denial-of-service attacks where an attacker submits transactions with computationally expensive leaf scripts that waste validator resources.
Mitigations:
- Gas cap: Leaf execution is capped at
MAX_LEAF_GAS(100,000 gas). Gas is metered per-opcode according to the EVM Berlin schedule. Validators can bound the cost of verification. - Banned opcodes: State-mutating and value-transferring opcodes are prohibited. Leaf scripts are pure verification functions.
- Pre-execution filter: Nodes verify the Merkle proof BEFORE executing the leaf script. Invalid proofs are rejected at the cost of proof verification only (~200-840 gas), not leaf execution.
- Precedent: ERC-4337 defined identical restrictions for UserOperation validation. EIP-8141's VERIFY frame runs in a read-only context with similar constraints.
Timing side-channel resistance
Merkle proof verification MUST use constant-time comparison for the final root equality check. A non-constant-time comparison could leak information about the authRoot value through timing measurements, potentially enabling targeted attacks against specific accounts.
Post-quantum signature scheme independence
HCA's commitment structure (address derivation + Merkle tree) is independent of any signature scheme. The security of the commitment layer depends solely on hash function properties (keccak256 preimage and collision resistance), which are resistant to quantum speedup — Grover's algorithm provides only a quadratic improvement, not the exponential break that Shor's provides against elliptic curve cryptography.
If a post-quantum signature scheme used inside a leaf script is later broken (e.g., advances in lattice cryptanalysis compromise Dilithium), the user rotates their authRoot to a new tree containing leaves with a different scheme. The commitment structure itself remains sound. This is a fundamental advantage over approaches that bake a specific PQ scheme into the address derivation.
User misconfiguration risks
HCA introduces configuration risks not present in current EOA accounts:
- A user who creates a tree with a malformed leaf script locks their funds permanently.
- A user who loses their Merkle tree backup cannot construct witnesses and loses access to their funds.
- A user who creates a tree with no rotation leaf cannot update their authentication policy.
- A user who creates a single-leaf tree with no recovery path has no fallback if that key is compromised.
Wallet safety requirements
To mitigate configuration risks, wallets implementing HCA account creation:
- MUST validate that all leaf scripts are well-formed EVM bytecode before deriving the address.
- MUST validate that all leaf scripts contain no banned opcodes and fit within
MAX_LEAF_GAS. - MUST simulate execution of each leaf script with test witness data to confirm at least one leaf is spendable.
- MUST require the user to confirm a backup of the complete Merkle tree (all leaves, structure, and associated keys).
- MUST warn if the tree contains no rotation leaf.
- MUST warn if the tree contains only a single leaf with no recovery path.
- SHOULD include a time-locked recovery leaf by default in standard wallet implementations.
Copyright
Copyright and related rights waived via CC0.
