Skip to main content

Overview

FHERC20’s core functionality revolves around maintaining complete confidentiality for token balances and transfers while still enabling all the operations users expect from a token. This page explores the fundamental features that make FHERC20 work.

Encrypted Balances

Storage Structure

FHERC20 maintains two parallel balance systems:

Confidential Balances

Type: euint64Real token balances encrypted using FHE. Only accessible with proper permissions, operations performed entirely on encrypted data.

Indicator Balances

Type: uint16Non-confidential activity indicators (0-9999) that provide visual feedback in wallets without revealing actual amounts.

Balance Encryption

When tokens are minted or transferred, the amounts are always encrypted:
The euint64 type can store values up to 2^64 - 1, which is 18,446,744,073,709,551,615. For tokens with 6 decimals (recommended), this is equivalent to about 18.4 trillion tokens with full precision.

Total Supply

Like balances, total supply is maintained in both confidential and indicated forms:

Querying Total Supply


Confidential Transfers

FHERC20 provides multiple transfer functions to handle different scenarios.

Basic Transfer

The fundamental transfer operation moves encrypted tokens from the caller to a recipient:
Use the InEuint64 overload when accepting user input from off-chain. Use the euint64 overload for contract-to-contract transfers where the value is already encrypted. Note: the euint64 overload requires the caller to be authorized via the FHE ACL for the given amount.

Transfer Implementation

The internal _transfer function handles the actual movement:

The Update Function

The _update function is the core of all balance changes. It uses FHESafeMath for overflow/underflow protection on encrypted values:
Zero-Replacement Behavior: If a user attempts to transfer more than their balance, FHERC20 does not revert. Instead, it transfers zero tokens. This preserves privacy by not revealing whether the user had sufficient balance.

Balance Queries

Confidential Balance

Returns the encrypted balance for an account:
Important: The returned euint64 is still encrypted! You cannot read its value directly. To use it:

Indicator Balance

Returns the non-confidential indicator value:
This returns a value between 0 and 9999, representing the activity indicator, not the real balance.

Balance Of Is Indicator

Returns true, signalling that balanceOf returns an indicator, not a real balance:
This is part of the ERC-7984 standard and helps wallets and block explorers understand the nature of the returned value.

Access Control for Balances

As shown in the _update function above, access control is managed inline as part of each balance update:
This ensures:
  • ✅ Users can access their own balances
  • ✅ The contract can perform operations on balances
  • ✅ Transfer participants (sender, receiver, and caller) can see the transferred amount
  • ✅ Total supply is only accessible by the contract
Learn more about FHE access control in the Access Control guide.

Minting and Burning

Minting New Tokens

There’s also a confidential mint variant that accepts already-encrypted values:

Burning Tokens

There’s also a confidential burn variant:
Like transfers, burning uses the zero-replacement pattern. If you attempt to burn more than an account’s balance, zero tokens are burned instead of reverting.

Amount Disclosure

FHERC20 includes optional disclosure functions for transparency when needed. Accounts with access to an encrypted amount can voluntarily reveal it on-chain.

Requesting Disclosure

Initiates a disclosure request for an encrypted amount. The caller must have FHE access to the amount.

Completing Disclosure

Completes the disclosure by providing the cleartext value and a decryption proof. Emits:

The Indicator System in Detail

Indicator Values

Indicators range from 0 to 9999, representing values from 0.0000 to 0.9999:

Indicator Lifecycle

1

Initial State

New accounts start with an indicator of 0.
2

First Interaction

Upon first transfer (sent or received), the indicator initializes to 7984 (0.7984), referencing the ERC-7984 standard.
3

Receive Transaction

Each time tokens are received, the indicator increases by 1 (0.0001).
4

Send Transaction

Each time tokens are sent, the indicator decreases by 1 (0.0001).
5

Wrapping

When the indicator reaches 9999, it wraps back to 0.

Indicator Functions

Indicator Tick

The indicatorTick is the amount reported in Transfer events and is calculated during contract construction:
You can query it with:
For a token with 6 decimals (recommended):
  • _indicatorTick = 10^2 = 100
  • This represents 0.0001 tokens

Resetting Indicators

Users can reset their indicator to zero for privacy:

Errors

FHERC20 defines the following custom errors:

Events

FHERC20 emits standard ERC20 events with indicator values, plus confidential-specific events:
The Transfer event doesn’t reveal the actual transfer amount—only that a transfer occurred. The value field always contains indicatorTick to maintain ERC20 compatibility while preserving privacy.

ERC20 Incompatible Functions

For privacy reasons, several standard ERC20 functions intentionally revert:
Instead, use:
  • confidentialTransfer() instead of transfer()
  • setOperator() instead of approve()
  • confidentialTransferFrom() instead of transferFrom()

Complete Example

Here’s a full example showing core FHERC20 features:
Usage: