Product · Airdrop

Confidential cohort airdrops

Per-campaign clones hold an encrypted balance and an EIP-712 domain. Admin signs a Claim(address recipient,bytes32 encryptedAmount) message; recipients redeem on chain. Claim windows and the gas fee are public; the amounts stay encrypted.

Where to start

The shape of a confidential airdrop

One clone per campaign

Aria's wallet calls the factory's createConfidentialAirdrop once. The factory deploys a LibClone with packed immutable args (token, gas fee, start time, can-extend flag); the admin, fee collector, end time, and EIP-712 domain are set in initialize. The per-recipient amount is an encrypted handle.

EIP-712 gates every claim

The admin signs a Claim(address recipient,bytes32 encryptedAmount) message off-chain. On each claim() call the clone recovers the signer and checks it holds DEFAULT_ADMIN_ROLE. No on-chain merkle root, no allowlist, the signature IS the authorization.

Claim windows are plaintext

Only the start timestamp is an immutable arg; the end timestamp lives in storage. Recipients see a hard cutoff; admin can extend (via useExtendClaimWindow, when the can-extend flag was set at deploy) but cannot retroactively shrink. Past-window claims revert with a typed error.

Transient ACL on claim

When a recipient claims, the clone grants the token contract transient access (FHE.allowTransient) and calls confidentialTransfer. Persistent decrypt ACL on the allocation comes from getClaimAmount — a separate write the recipient must call BEFORE claim(), while the signature is still unused. Once claim() consumes the signature, any later getClaimAmount with the same handle reverts with SignatureAlreadyClaimed. Anyone else sees a 32-byte handle.

Reference

The lookup layer. Every exported type, error class, role, event, and ABI lives in a dedicated table — copy-paste-ready, no MDX prose between you and the import.