Skip to main content
ERC20Confidential is an OpenZeppelin ERC20 with a second, encrypted balance for every holder. Use it when your token must keep working with every ERC-20 integration and holders opt in to privacy by moving tokens into the encrypted balance.

How it differs from FHERC20

Each holder has two balances in the same contract:
  • A public balance. balanceOf, transfer, approve, transferFrom, allowance, and totalSupply are the standard OpenZeppelin functions and behave exactly as on any ERC-20.
  • A confidential balance. An encrypted euint64 handle that only the holder, and accounts the token grants access to, can decrypt. You read it with confidentialBalanceOf and move it with the confidentialTransfer family.
shield moves tokens from the public balance into the confidential one, and unshield plus claimUnshielded move them back. On an FHERC20 token, the ERC-20 surface is only an indicator and its transfers revert. Here it is real, so balanceOfIsIndicator() returns false and indicatorTick() returns 0. Pick ERC20Confidential for a new token that needs both modes. To add privacy to a token that is already deployed, use a wrapper instead.

A minimal token

ERC20Confidential takes a name, a symbol, and the decimals of the public balance:
DualToken.sol
_mint is the OpenZeppelin function, so this mints public tokens. Holders call shield to make them confidential. The constructor also deploys a small indicator token that wallets can track. See how the two balances relate.

Decimals and units

The confidential balance is a 64-bit integer with at most 6 decimals. confidentialDecimals() returns 6, or the public decimals if those are lower. Every confidential unit is backed by a fixed number of public base units:
For an 18-decimal token the rate is 10^12. Shielding 1 ether credits 1_000_000 confidential units, and you pass confidential amounts in those units to transfers and unshield.

Deploy it

ERC20Confidential and ERC20ConfidentialUpgradeable call into the external ERC20ConfidentialLib, so you must deploy that library and link it before you deploy the token. See link the shared library. For the upgradeable variant, see upgradeable tokens.
Enable the Solidity optimizer. DualToken compiles to about 16 KB of bytecode with the optimizer off, and a token with a few extra functions grows quickly toward the 24 KB limit.

Pages in this section

How the two balances relate

The pool that backs confidential balances, total supply, and the indicator token.

Shield and unshield

Move tokens between the public and the confidential balance.

Confidential transfers and operators

How encrypted transfers differ from FHERC20.

Extend ERC20Confidential

Freeze accounts, add a compliance observer, mint confidentially, or bring your own ledger.