ERC-7945 Confidential transfer capable token (Confidential Transactions Supported Token)

Final · Tokens · created 2025-05-09

A common interface for tokens that hide account balances and transfer amounts as encrypted data. It lets wallets and apps handle amount-concealing tokens without being tied to a specific implementation.

Why it is needed

Ethereum's standard token (ERC-20) exposes every account's balance and transfer amount directly on the blockchain. Anyone can see how much a given address holds and how much it has sent, making it difficult for amount-sensitive individuals or institutions to use. Some blockchains, like Monero or Zcash, hide amounts at the protocol level, and techniques like Zether implement this via smart contracts without changing the protocol, but Ethereum has had almost no common standard for such confidential tokens. As a result, users and apps could not easily tell which token contracts support confidential transfers, nor could they reliably transfer tokens without revealing the actual amounts. This standard defines only a minimal common surface covering balance queries, transfers, delegated transfers, approvals, and related events, allowing different proof systems, ciphertext encodings, and regulatory compliance procedures to coexist behind a single interface.

What to implement

In depth

All amounts are encrypted data of type bytes

Under this standard, balances, transfer amounts, and allowances are all exchanged as bytes types. confidentialBalanceOf(address owner) returns an encrypted balance as bytes memory rather than a uint256 number. The standard does not specify how this bytes value should be encrypted or serialized, or which proof system to use, leaving that to the implementation. The original text cites a Zether-style implementation as an example, where balances and transfer amounts are homomorphically encrypted under an ElGamal public key. By fixing only this minimal interface, different proof systems, ciphertext encodings, and regulatory-compliance workflows can coexist behind one common interface.

confidentialTransfer and Proof Verification

confidentialTransfer(_to, _confidentialTransferValue, _proof) sends _to an amount of tokens equal to the value hidden behind the encrypted value, and MUST emit a ConfidentialTransfer event. If verification of the caller's _proof fails, it SHOULD revert. In the Zether-style example implementation, _proof verifies three things: that the transfer amount was correctly encrypted under the public keys of both the caller and _to, that the hidden value is non-negative, and that the caller's confidential balance is sufficient to cover that value.

Delegated Transfer: confidentialTransferFrom

confidentialTransferFrom(_from, _to, _confidentialTransferValue, _proof) sends tokens from _from to _to on the caller's behalf, used in withdrawal-style workflows where a contract moves tokens for a user or collects fees in a subcurrency. It SHOULD revert if the _from account has not deliberately approved the caller in some way, and SHOULD also revert if proof verification fails. In the Zether-style example, the proof verifies that the amount was encrypted under the three public keys of _from, _to, and the caller, that the amount is non-negative, and that the caller's confidential allowance is sufficient.

confidentialApprove, Which Differs Substantially from ERC-20's approve

Calling confidentialApprove splits the caller's confidential balance into an allowance part and a left part, such that the value behind the two parts combined equals the value behind the original balance. _spender can call confidentialTransferFrom repeatedly to draw down the allowance part until it reaches zero, with the value behind the allowance part decreasing by the transfer amount each call. The left part becomes the caller's new confidential balance. Calling the function again first merges the existing allowance part back into the caller's confidential balance, then overwrites the allowance part with the new _confidentialValue. The remaining allowance is queried via confidentialAllowance(_owner, _spender).

Event emission rules

The ConfidentialTransfer event MUST be emitted whenever tokens are transferred. When transferred via confidentialTransferFrom, _spender MUST be set to the caller's address; otherwise it SHOULD be set to 0x0. When minting new tokens, a ConfidentialTransfer SHOULD be emitted with _from set to 0x0; when burning, with _to set to 0x0. The ConfidentialApproval event MUST be emitted every time a call to confidentialApprove(address,bytes,bytes) succeeds.

Why confidentialTotalSupply Is Not Required

A field like ERC-20's totalSupply() conflicts with confidentiality. If every user could query and decrypt the total supply, they could compare values before and after a mint or burn to infer the actual amount minted or burned, destroying confidentiality. For this reason, the standard does not require confidentialTotalSupply() and instead lets implementations optionally support it based on whether anti-money-laundering and audit needs apply. Letting only a small group of parties know the plaintext total supply behind the ciphertext makes operation far more practical.

Audit and Anti-Money-Laundering Support

For issuers subject to government or monetary-authority oversight, such as banks or financial institutions, audit support can be added without changing confidentialTransfer's function signature, simply by encoding more information into the parameters. In the Zether-style example implementation cited in the original text, the caller redundantly encrypts the transfer amount under the public keys of the caller, the recipient, and a group of auditors, so that only the relevant parties can learn the exact amount. The same approach can be applied to confidentialTotalSupply().

ERC-20-Compatible Fat Tokens and Optional Metadata

A confidential token may also implement ERC-20 at the same time. Accounts of such a fat token can hold both a plaintext balance and a confidential balance, and may optionally provide methods to hide an ERC-20 plaintext balance into a confidential balance, or conversely to convert a confidential balance back into a plaintext balance. The original text explains that the ERC-20 interface brings much greater usability and utility to confidential tokens. Meanwhile, the IERC7945Metadata interface, which holds name, symbol, and decimals, is OPTIONAL, and other interfaces or contracts MUST NOT assume these values are present.

Things to watch out for

Original ERC · ← ERCs