Behind the Scenes of a Confidential ERC-20 Transfer

Blockchain technology is built on transparency, but when it comes to financial transactions, transparency isn’t always ideal. From payroll to private investments, some information should stay confidential. This is where Fully Homomorphic Encryption (FHE) comes into play—specifically in the form of unlocking confidential ERC20 tokens (cERC20s). These tokens leverage FHE to maintain privacy while preserving the flexibility of standard ERC20 tokens.

A key part of this system is how encrypted balances are updated during token transfers. This process involves two core operations: TFHE.add() and TFHE.sub(). Let’s break down what happens behind the scenes when a confidential ERC20 token is transferred.

Recap: What Are cERC-20 Tokens?

Confidential ERC-20 tokens (cERC20s) work in a similar way to standard ERC20 tokens but with one major difference: balances and transfer amounts are encrypted. Only authorized parties can decrypt this information. On the other hand, the public blockchain remains blind to the actual amounts involved.

Homomorphic Addition Within TFHE

The fhEVM, which makes cERC20 tokens possible, is built on the TFHE (Fast Fully Homomorphic Encryption Over The Torus) scheme. It is one of the several schemes that are used in the FHE space.

At the core of cERC20 operations, there is homomorphic addition from the TFHE-rs library, that is, one of the TFHE implementations:

  • TFHE.add(): Adds two encrypted values without decrypting them.
  • TFHE.sub(): Subtracts one encrypted value from another, also without decryption.

These operations are made possible by FHE. The result remains encrypted and can only be decrypted by someone with the proper keys.

Example: Transferring a cERC20 Token

Here’s how a confidential transfer works at the code level:

function _transfer(address to, euint64 encryptedAmount) internal virtual {
    // Update the recipient’s balance
    euint256 newBalanceTo = TFHE.add(balances[to], encryptedAmount);
    balances[to] = newBalanceTo;‍    
    
    // Update the sender’s balance    
    euint256 newBalanceFrom = TFHE.sub(balances[msg.sender], encryptedAmount);    
    balances[msg.sender] = newBalanceFrom;
}

While TFHE uses several ciphertext types like LWE, GLWE, GLev, and GGSW, as the inputs are mostly LWE ciphertexts, so we’ll take a look at that case.

Recap: LWE Ciphertexts

The LWE (Learning-With-Errors) problem is based on solving linear equations with small, random noise added, making it computationally difficult to recover the original inputs. In TFHE, LWE ciphertexts are used to represent encrypted values.

An LWE ciphertext is represented as a pair (a, b), where:

- a is a vector of integers chosen from a finite field,

- b is an integer that encodes the encrypted message combined with a small amount of noise.

Formally, given a secret vector s and plaintext m, the encryption process is defined as:

c = (a, b),

where b = a · s + m + e

Here, e is the error term that ensures the ciphertext is secure against attempts to recover the plaintext.

Adding Two LWE Ciphertexts

To add two encrypted LWE ciphertexts homomorphically, we perform element-wise addition of their vector components. Given two ciphertexts c₁ = (a₁, b₁) and c₂ = (a₂, b₂), the homomorphic addition is computed as:

c₃ = (a₁ + a₂, b₁ + b₂)

This operation preserves the noise level within acceptable limits, ensuring that the resulting ciphertext remains decryptable while maintaining privacy. Importantly, since both ciphertexts include their respective noise terms, the noise in the resulting ciphertext c₃ is the sum of the original noise terms, which must be kept below a certain threshold to ensure correct decryption.

To sum up, we’ve done the following:

  1. Adding to the Recipient’s Balance: Using TFHE.add(), the encrypted amount is added to the recipient’s encrypted balance. Neither the contract nor the blockchain sees the actual values.
  2. Subtracting from the Sender’s Balance: Using TFHE.sub(), the encrypted amount is subtracted from the sender’s encrypted balance, again without exposing the plaintext values.

Because both operations occur on encrypted data, the transfer is recorded onchain, but the amounts remain private.

Why Use Encrypted Arithmetic?

  • Privacy: Sensitive financial information stays encrypted at all times.
  • Security: No need to decrypt balances, reducing the risk of data exposure.
  • Composability: Works seamlessly within existing smart contracts, enabling private transfers without altering the blockchain’s core functionality.

Conclusion

TFHE.add() and TFHE.sub() are the building blocks that enable confidential ERC20 transfers. By performing arithmetic directly on encrypted values, they allow balances to be updated onchain while keeping transaction details private. This innovation paves the way for secure, privacy-preserving financial applications on the blockchain—without sacrificing the transparency and composability that make Web3 so powerful.

Subscribe to our newsletter

Top industry insights on FHE.

By clicking Sign Up you're confirming that you agree with our Terms and Conditions.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.