For the complete documentation index, see llms.txt. This page is also available as Markdown.

Shield tokens

How to convert public ERC-20 tokens into their confidential form.

Shielding converts public ERC-20 tokens into confidential tokens. The SDK handles the ERC-20 approval and the shield transaction in a single call via wrappedToken.shield(). In React, use the useShield hook.

Shielding paths

WrappedToken.shield() exposes a single API but routes through one of two on-chain paths depending on the underlying ERC-20:

Path
Triggered when
Wallet prompts
Notes

transferAndCall

Underlying ERC-20 implements ERC-1363

1

The wrapper's onTransferReceived mints the confidential balance in one transaction.

approve + wrap

Underlying ERC-20 does not implement ERC-1363

2

An ERC-20 approve followed by a wrap call on the wrapper.

The SDK detects ERC-1363 support automatically via ERC-165 supportsInterface against the underlying token. You don't need to choose a path or detect ERC-1363 yourselfwrappedToken.shield(amount) routes correctly for any wrapper. approvalStrategy only applies to the approve + wrap path; on the transferAndCall path there is no allowance step.

Which path will my token take?

Among the wrapped tokens registered on Ethereum mainnet today, the routing is:

Confidential wrapper
Underlying
Shield path

cTGBP

tGBP

transferAndCall (single tx)

cZAMA

ZAMA

transferAndCall (single tx)

cUSDC

USDC

approve + wrap (two txs)

cUSDT

USDT

approve + wrap (two txs)

cWETH

WETH

approve + wrap (two txs)

cBRON

BRON

approve + wrap (two txs)

ERC-1363 is a conditional optimisation, not a recommended new default — only a small subset of tokens implement it today. Tokens that don't (USDC, USDT, DAI, and most existing ERC-20s) continue to use approve + wrap. Any newly deployed wrapper picks up the transferAndCall path automatically if its underlying ERC-20 implements ERC-1363 — no opt-in is required from your code. See the WrappersRegistry reference for how to look up the wrapper for a given ERC-20.

Steps

1. Create a wrapped-token instance

Start from a configured SDK instance (see Configuration) and create a WrappedToken pointing at your confidential wrapper contract. The wrapper is the confidential token: createWrappedToken(addr) takes a single address — the wrapper's own address.

If you only have the underlying ERC-20 address, the built-in registry resolves the matching wrapper.

2. Shield with exact approval (default)

The SDK always validates the ERC-20 balance before submitting. If the balance is insufficient, it throws InsufficientERC20BalanceError with requested, available, and token properties -- no transaction is sent. This is a public read with no signing requirement, so it works for all wallet types including smart wallets.

By default, shield approves the exact amount before wrapping. This is the safest option — it limits exposure if the contract is compromised:

On the approve + wrap path, the SDK sends two transactions: an ERC-20 approve for 1000 tokens, followed by the shield (wrap) call. The user sees two wallet prompts. On the transferAndCall path (ERC-1363 underlyings), shielding completes in a single transaction and approvalStrategy doesn't apply — see Shielding paths for details.

3. Shield with max approval

approvalStrategy only affects the approve + wrap path; on transferAndCall it's ignored. To avoid a separate approval transaction every time on approve + wrap tokens, pass approvalStrategy: "max". This grants an unlimited allowance on the first shield, and subsequent shields skip the approval step:

4. Shield with skip approval

If the user has already approved the wrapper contract (for example, through a separate UI flow), you can skip the approval check entirely:

This sends only the shield transaction. If the allowance is insufficient, the transaction reverts on-chain.

5. Track the transaction

Both the core SDK and React hooks resolve to a TransactionResult with the transaction txHash and its mined receipt. Use them to wait for confirmation or show progress in your UI:

In React, balance caches are automatically invalidated after a successful shield. The useConfidentialBalance hook will pick up the new balance on its next poll cycle.

Next steps

Last updated