The five airdrop flows.
Confidential cohort airdrops collapse to these five paths, each with hooks, a recipe, and a demo story chapter.
Before creating, funding, or dispersing, the token must approve this contract as an operator: call token.setOperator(<contract address>, deadline) first. Without it the transaction reverts with ERC7984UnauthorizedSpender (0x79f2cb38).
The SDK surfaces the missing approval as: “The token has not approved this contract as an operator. Call setOperator() (see /fhe operators) before this transaction.”
Do not route these calls through Multicall3. aggregate3 makes the Multicall3 contract the msg.sender, which breaks operator approvals and per-user clone authorization. Use the built-in batch functions instead: batchCreateVesting, disperse, batchDiscloseToParty.
- 1
Deploy a clone
Operator calls the factory to mint a per-cohort airdrop clone. Clone holds the encrypted cohort balance + the claim signature registry.
- factory.createConfidentialAirdrop({ params, userSalt }) where params = { token, startTimestamp, endTimestamp, canExtendClaimWindow, admin }, CREATE2 deterministic
- Receipt's ConfidentialAirdropCreated event carries the clone address
- params.admin gets DEFAULT_ADMIN_ROLE; the factory's feeCollector gets FEE_COLLECTOR_ROLE
- 2
Fund the pot
Operator transfers encrypted tokens into the clone. The pot's plaintext total stays opaque; only per-recipient ACL on claim reveals fragments.
- Operator's wallet calls setOperator on the source token (one-time per chain)
- useFundConfidentialAirdrop().mutate({ token, params, userSalt, deployer, gasFee, amount }) — the full FundAirdropArgs; SDK encrypts amount, submits transfer
- Receipt's ConfidentialAirdropFunded event flagged with the clone address
- 3
Sign claim authorizations
An address with DEFAULT_ADMIN_ROLE signs an EIP-712 typed message per recipient. The signature is portable, distribute via email, QR, link, anything. No on-chain registration step.
- Off-chain: build the Claim struct {recipient, encryptedAmount}
- useSignClaimAuthorization signs over the typed-data domain
- Ship the signature + handle to the recipient
- 4
Recipient claims
Recipient submits the signature + the encrypted-amount handle. Clone verifies signer ∈ DEFAULT_ADMIN_ROLE, marks the signature claimed, transfers.
- Recipient calls useClaim with the signature payload
- Clone ECDSA.recovers the signer, checks role, checks no double-claim
- Atomic confidential transfer to recipient (FHE.allowTransient to the token + confidentialTransfer); decrypt access comes from the separate getClaimAmount write
- 5
Admin recovery + roles
Drain the clone's full confidential token balance back to the operator (callable any time by DEFAULT_ADMIN_ROLE), withdraw collected gas fees, sweep accidentally sent tokens, and manage role membership.
- useWithdraw (DEFAULT_ADMIN_ROLE) drains the entire confidential balance to a recipient
- useWithdrawOtherToken / useWithdrawOtherConfidentialToken to sweep accidentally sent tokens
- useAirdropGrantRole / useAirdropRevokeRole for admin or fee-collector rotation
- Pausable surface via useSetPaused (DEFAULT_ADMIN_ROLE) if a fault is detected