Everything anyone can learn
Seen by all.
Every holder below is public, forever, like any ERC-721. Every mark is unique, generated on-chain from a token id that was never secret. None of them shows you the essence.
The collection
Each mark is drawn from its token id alone — never from the sealed value, which would leak it. The handle under each card is the real 32-byte ciphertext; copy one and try it from any address you like.
What only you can reach
Known by one.
One token per address. Its essence was drawn inside the coprocessor and sealed to you by an on-chain ACL — the only reason the relayer will ever open it.
Nothing sealed to you yet.
Connect a wallet to see whether one is.
The mark is public and drawn from the token id. The gauge is not — it only fills once the relayer hands you the number.
—
Settle it without telling anyone
The contract compares two sealed powers on ciphertext and publishes a single bit: who won. Neither number is revealed — not to you, not to your opponent, not to the chain.
The mechanism
Compute on what
you cannot read.
Fully homomorphic encryption lets a contract operate on values it never sees. Everything below happens on Sepolia, in public, without the number ever existing in the clear on-chain.
What the contract can do blindfolded
The contract adds them. It never sees 7, 5 or 12.
Mint to reveal, end to end
-
01
The draw
FHE.randEuint16()asks the coprocessor for randomness that is encrypted from the instant it exists. It is folded into 1–100 withremandadd— all on ciphertext. No plaintext randomness appears in calldata, in an event, or in storage. -
02
The seal
Storage gets a 32-byte handle, not a value.
FHE.allowThislets the contract keep using it;FHE.allownames you. The ACL is the whole security model — possession of a handle grants nothing. -
03
The look
Your browser makes a throwaway keypair and signs an EIP-712 request scoped to this contract. The relayer checks the on-chain ACL, then re-encrypts the value to that keypair. The plaintext exists only in your tab.
-
04
The handover
OpenZeppelin's
_updatehook fires on every transfer, extending the ACL to the incoming holder in the same transaction. Ownership was always public. The essence follows the token, not the minter.
Worth knowing
Grants are permanent
FHEVM has no revoke. A past holder keeps the ability to decrypt the handle they held, so “only the current holder” holds against anyone who never held it. Rotating the secret on transfer would mean redrawing the trait — a different product.
The draw has a small bias
randEuint8(upperBound) only takes powers of two, so the contract draws 16 bits and reduces mod 100. The bias is under 0.06% — fine for a cosmetic trait, not for anything adversarial.