ERC-8227 — Encrypted Tokens and State

Summary: ERC-8227 defines a standard interface for fungible tokens with encrypted balances and the extension of that interface to arbitrary contract state fields. Balances are stored as BFV ciphertexts; arithmetic (addition, multiplication) is performed homomorphically on-chain via precompiles.

Covenant Surface

ConstructDescription
encrypted tokenDeclare a fungible token with encrypted balances
encrypted<T>Mark any field as FHE-encrypted
fhe_add(a, b)Homomorphic addition
fhe_mul(a, b)Homomorphic multiplication
fhe_encrypt(v, pk)Encrypt a plaintext value
fhe_decrypt(c, sk)Decrypt a ciphertext (threshold protocol)
reveal field to addrAuthorized threshold decryption

Precompile Signatures

ERC-8227 defines seven precompiles. Their addresses are fixed across EVM-compatible chains that support Styx:

AddressNameSignatureGas (L1)
0x0ffhe_encrypt(bytes32 pk, uint256 value) → bytes128 ciphertext50,000
0x10fhe_add(bytes128 a, bytes128 b) → bytes1288,000
0x11fhe_mul(bytes128 a, bytes128 b) → bytes128120,000
0x12fhe_cmp(bytes128 a, bytes128 b) → bytes12890,000
0x13fhe_decrypt_auth(bytes128 c, address[] validators) → bytes128200,000
0x14fhe_reencrypt(bytes128 c, bytes32 src_pk, bytes32 dst_pk) → bytes12860,000
0x15fhe_verify_ct(bytes128 c, bytes32 pk) → bool5,000

On Aster Chain, FHE operations use the pGas model (privacy gas, priced separately from compute gas). pGas costs are 10–50× lower than L1 due to native hardware acceleration:

OperationL1 GasAster pGas
fhe_encrypt50,0005,000
fhe_add8,000400
fhe_mul120,0008,000
fhe_cmp90,0006,000
fhe_decrypt_auth200,00015,000

Ciphertext Representation

ERC-8227 standardizes ciphertexts as BFV (Brakerski-Fan-Vercauteren) scheme ciphertexts over a 128-bit packed plaintext space:

bytes128 ciphertext = [
  bytes64 c0,     // RLWE component A
  bytes64 c1,     // RLWE component B
]

Parameters:

  • Polynomial degree: n = 4096
  • Ciphertext modulus: q = 2^109
  • Plaintext modulus: t = 2^64
  • Security level: 128-bit classical

The 128-byte ciphertext representation is fixed for ERC-8227 v1. Future versions may support larger parameter sets via an extension byte.

Threshold Decryption Protocol

Decryption requires threshold participation from the network. The reveal statement in Covenant triggers this automatically:

action claim_salary(employee: address) only employer {
    reveal salary[employee] to employee
}

Compiles to:

  1. Emit DecryptionRequest(ciphertext, employee, block.number + 50) event
  2. Validators independently partial-decrypt using their key shares
  3. When threshold reached (3/5 by default on Aster), combine shares into plaintext
  4. Deliver plaintext to employee via callback

The threshold is configurable at the network level. On Ethereum L1, decryption requires a separate transaction from the recipient after a challenge period.

Security Guarantees

  • IND-CPA security: An adversary who sees only ciphertexts cannot determine underlying values
  • Circuit privacy: The operations performed on encrypted data are not leaked by the output ciphertext
  • Semantic security: Two encryptions of the same plaintext produce computationally indistinguishable ciphertexts

Not provided by ERC-8227:

  • IND-CCA security (ciphertexts are malleable by design — this is a property of FHE)
  • Protection against the network’s threshold validators colluding (requires honest majority assumption)
  • Confidentiality of access patterns (who is calling which function is still visible)

Known Limitations

  1. Multiplication depth: BFV supports bounded multiplication depth (~10 before bootstrapping). Contracts that require deep polynomial circuits should use @prove_offchain (ERC-8229) instead.
  2. No FHE comparison branching: if (encrypted_balance > 1000) cannot be used — comparisons return encrypted booleans, not plaintext. Use fhe_cmp and handle via encrypted conditional.
  3. Integer overflow: FHE arithmetic is modular. Contracts must ensure values stay within [0, 2^64).
  4. Ciphertext size: Each encrypted uint256 uses 128 bytes of storage instead of 32 bytes. Factor this into storage cost.

Minimal ERC-8227 Interface (ABI)

{
  "name": "IConfidentialToken",
  "functions": [
    { "name": "encryptedBalanceOf", "inputs": [{"name":"account","type":"address"}], "outputs": [{"name":"","type":"bytes128"}] },
    { "name": "confidentialTransfer", "inputs": [{"name":"to","type":"address"},{"name":"encAmount","type":"bytes128"}], "outputs": [{"name":"","type":"bool"}] },
    { "name": "confidentialApprove", "inputs": [{"name":"spender","type":"address"},{"name":"encAmount","type":"bytes128"}], "outputs": [] },
    { "name": "requestDecrypt", "inputs": [{"name":"account","type":"address"}], "outputs": [] }
  ],
  "events": [
    { "name": "ConfidentialTransfer", "inputs": [{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true}] },
    { "name": "DecryptionRequest", "inputs": [{"name":"account","type":"address","indexed":true},{"name":"ciphertext","type":"bytes128"},{"name":"deadline","type":"uint256"}] }
  ]
}

Note: ConfidentialTransfer intentionally omits the amount — emitting an encrypted amount would leak the transfer amount to validators during event indexing.

See Also