Test tokens for the 2.0 line, on Sepolia.
Mint value-less TTT and confidential CTTT to exercise the 2.0 products. No encryptor, no Zama peer.
Where to start
Install from the next dist-tag, create the faucet client, mint TTT and CTTT, and read both balances. Headless and React.
Two open mints, balance reads, decimals, rate, supply and metadata. Use it from Node, workers or tests.
Every client method as a wagmi + TanStack Query hook, with query options on the reads and gas headroom on the mints.
Deployment
Read from DEPLOYED_ADDRESSES.testnetFaucet in the installed build. Sepolia (11155111) is the only registered chain. The guard also accepts 31337 (local Anvil) when you pass an explicit address; there is no mainnet faucet.
| Contract | Sepolia | Role |
|---|---|---|
| ConfidentialTokenopsTestToken (CTTT) | 0x258F…361a | 6-decimal ERC-7984 wrapper behind a UUPS proxy. The client's single address knob. |
| TokenopsTestToken (TTT) | 0x37a0…D92b | 18-decimal ERC-20 that backs CTTT. Always read from the wrapper's underlying() getter. |
What changed since 1.6
The faucet's own surface has no breaking change: the differences below are additions and stricter error reporting. For the rest of the 2.0 upgrade, see Upgrading from 1.x.
Gas headroom on both mints
mintUnderlying and mintConfidential estimate their gas and send it padded by 25% (DEFAULT_GAS_HEADROOM_PERCENT). Set gasHeadroomPercent on the client or hook options, or pass a per-call gas (GasOverride) on the mint args to send a fixed limit.
Gas headroomquery on every read hook
Every read hook takes query (ReadHookQueryOptions): TanStack options minus queryKey and queryFn. query.enabled can turn a ready query off, never an unready one on.
Read-hook query optionstelemetry on hook options
BaseHookOptions gains telemetry and gasHeadroomPercent, both forwarded into the headless client. The client emits testnet-faucet.client.init and brackets each mint with a span.
TelemetryHooks never throw from render
A constructor error (an unsupported chain, a malformed address, a bad gasHeadroomPercent) becomes resolutionError inside the hook: read queries stay disabled and the mint hooks reject with that typed error.
A clearer unsupported-chain error
On mainnet or any other chain the client throws UnsupportedChainError with context.method "TestnetFaucetClient" and a context.hint that says the faucet runs on Sepolia only and how to point the clients there.
Wallet and estimate guards
Every write refuses a wallet on a different chain from the public client with WalletChainMismatchError, and a gas estimate that reverts now throws the typed error instead of handing the call to the wallet.
More re-exports
/testnet-faucet re-exports DEFAULT_GAS_HEADROOM_PERCENT, GasOverride and GasHeadroomOption. /testnet-faucet/react re-exports GasOverride, GasHeadroomOption, ReadHookQueryOptions and TokenOpsValidationError. Both add AclNotPropagatedError.
Unchanged
Addresses, both ABIs, every method name and result shape. The mint args only gain the optional gas. Mints still wait for their receipt: the faucet has no waitForReceipt: false path.
The shape of the testnet faucet
Testnet only
assertTestnetFaucetChain rejects mainnet and every chain outside TESTNET_FAUCET_SUPPORTED_CHAIN_IDS at construction. The tokens carry no value and nothing here mints anything redeemable.
Two tokens: plain TTT, confidential CTTT
TTT is a plain 18-decimal ERC-20 with an open mint. CTTT is a 6-decimal ERC-7984 wrapper whose open mint first mints the TTT that backs it. Scale amounts for the right token: 18 decimals for TTT, 6 for CTTT.
Open mint, no roles, no pause
Anyone can mint to any address. The one ceiling is maxTotalSupply on CTTT (type(uint64).max), which surfaces as FaucetSupplyExhaustedError.
Plaintext in, encrypted handle out
Mint amounts are public plaintext bigints. A confidential balance reads back as a euint64 handle; decrypting it is a separate step through your own Zama SDK instance.