07 — FHE Basics

The simplest FHE pattern: a counter where the value is encrypted on chain. Every observer sees ciphertext bytes; only the designated owner can decrypt the value via threshold decrypt. Increments are homomorphic — the chain adds to the ciphertext directly, no decryption ever happens during compute.

-- ShieldedCounter.cov · an FHE counter.
-- The `encrypted` qualifier means the `total` field is stored on-chain
-- as a TFHE ciphertext (ERC-8227). Every observer sees ciphertext bytes;
-- no one except the owner can see the value. `bump` adds homomorphically
-- without decryption.

encrypted counter ShieldedCounter {
    total: amount

    action bump(by: amount) {
        total += by
    }

    reveal total to owner
}

What just happened?

ConceptExplanation
encrypted counterTop-level keyword pair: a counter where the value is FHE-encrypted on chain (TFHE ciphertext, 32-byte handle per ERC-8227)
total: amountDeclares the counter value. The encrypted qualifier lifted from the construct keyword applies — total is a ciphertext, not plaintext
total += byA homomorphic add. The compiler routes this to a TFHE precompile that adds by to the ciphertext directly, producing a new ciphertext. No decryption ever happens on chain
reveal total to ownerDeclarative access policy: only the address designated as owner can request a threshold-decrypt of the value. On a real chain this requires validator consensus; in the playground’s MockChain the precompile returns a deterministic plaintext

Why this matters

Every blockchain prior to FHE-enabled chains made every value public. Privacy was achieved off-chain (mixers, ZK rollups with private state, sidechains) — never inside a single contract.

Covenant + ERC-8227 changes this. The total field above is stored encrypted, computed encrypted, and only revealed to one specific principal. An observer running an indexer over the chain learns nothing from the bytes. A validator processing the bump call learns nothing about the operand.

This is the foundational pattern. From here, you can build:

  • 08 — Encrypted Token — a confidential ERC-20 where balances are encrypted
  • B3 — Private DAO (gallery →) — voting where individual votes and running tallies are both encrypted

Real-chain considerations

The playground’s MockChain mocks the FHE precompiles so you can iterate on UX. Real on-chain deployment requires:

  • TFHE-enabled validators — Aster Chain ships these by default; on Sepolia, FHE precompiles aren’t deployed and the contract will revert when an FHE op is reached
  • Threshold decryption coordinationreveal X to owner on real chain triggers an off-chain ceremony where validators each contribute a share of the decryption result. The result is then posted on-chain or returned to the requester

For development, MockChain is the fastest iteration loop. For acceptance testing, deploy to Aster Testnet (configured in Chain Target → Aster).

Try it now

Try in Playground →

In the playground:

  1. Compile — note in the Inspector → IR tab how total += by lowers to tfhe_add(total, by) precompile dispatch
  2. Deploy to MockChain
  3. Call bump(5) — the chain shows the call succeeded but the storage slot for total shows ciphertext bytes (not 5)
  4. Call reveal total — returns 5 (the mocked threshold decrypt)
  5. Call bump(3), then reveal total — returns 8

The Privacy panel in the right sidebar lights up with the FHE-related diagnostics + side-channel notes.

Continue

Move on to 08 — Encrypted Token to see how the same pattern scales to a full ERC-8227 confidential token.