The following standard describes confidential fungible tokens via pointers. All amounts in this standard are represented by confidential pointers; therefore, balances and transfer amounts are confidential. Pointers refer to data stored elsewhere–onchain or offchain. The logistics of pointer resolution, operation, and location are implementation specific. The interface defines functions to transfer tokens with pointers, as well as approve operators, allowing the token to be transferred by a third party.
Motivation
Confidential tokens enable private value transfer which is vital for many usecases such as payroll, confidential DeFi, institutional settlement, and more.
A standard interface allows pointer based confidential tokens on Ethereum to be reused by other applications: from privacy-focused wallets to decentralized exchanges, while keeping transaction amounts private from public view.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Nomenclature
All amounts in this ERC are pointer based amounts represented by bytes32 pointers unless otherwise specified. The resolution and manipulation of these pointers is implementation specific.
Token
Compliant tokens MUST implement ERC-165. The supportsInterface function MUST return true if 0x4958f2a4 is passed through the interfaceID argument.
Methods
Compliant tokens MUST implement the following methods, unless otherwise specified:
name()
Returns the name of the token - e.g. "MyConfidentialToken".
OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present.
functionname()externalviewreturns(stringmemory)
symbol()
Returns the symbol of the token - e.g. "MCT".
OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present.
functionsymbol()externalviewreturns(stringmemory)
decimals()
Returns the number of decimals the token uses (e.g. 6) as a plaintext uint8.
functiondecimals()externalviewreturns(uint8)
contractURI()
Returns the metadata URI for the token. SHOULD follow the schema defined in ERC-7572.
Authorizes operator to transfer tokens on behalf of the caller until timestamp until–passed as a plaintext uint48. An operator may transfer any amount of tokens on behalf of a holder while approved. Accounts may have multiple simultaneous operators.
Transfers amount of tokens from address from to address to. The function MAY revert if the from’s account balance does not have enough tokens to spend.
Returns the actual amount that was transferred.
MUST revert if the caller is not an operator for from.
Transfers amount of tokens from address from to address to. The function MAY revert if the from’s account balance does not have enough tokens to spend.
The data parameter contains implementation-specific information such as cryptographic proofs.
Returns the actual amount that was transferred.
MUST revert if the caller is not an operator for from.
Transfers amount of tokens from address from to address to. The function MAY revert if the from’s account balance does not have enough tokens to spend.
Transfers amount of tokens from address from to address to. The function MAY revert if the from’s account balance does not have enough tokens to spend.
The data parameter contains implementation-specific information such as cryptographic proofs.
Transfer functions suffixed with andCall execute a callback to the to address AFTER all transfer logic is completed. The callback calls the onConfidentialTokenReceived function with the from address, actual amount sent, and given callData bytes (the last parameter for andCall functions). The callback flow is as follows:
If address(to).code.length == 0 the callback is a no-op and returns successfully.
If the function call returns the false boolean, attempt to transfer back the tokens to the original holder and return.
Contract Receivers
For a contract to receive a transfer with a callback, it MUST implement the onConfidentialTokenReceived function:
onConfidentialTokenReceived
If the callback is unsuccessful, the function SHOULD revert or return a pointer to the false boolean.
The token will attempt to return tokens from the receiver to the sender if false is returned. Note that this reversal may fail if the receiver spends tokens as part of the callback.
Using bytes32 allows implementations using pointer based systems and privacy mechanisms including FHE systems, zero-knowledge proofs, secure enclaves, or future technologies to be compliant.
Operator Model
Time-limited operators provide granular control while enabling DeFi protocol integration and natural permission expiration. This approach reduces the load on the external system by removing the need to track approval amounts.
Data Parameter
The bytes calldata data parameter in transfer functions allows implementations to include cryptographic proofs, access permissions, or other privacy-mechanism-specific information.
Security Considerations
Security depends on the underlying pointer based mechanism. Implementations must guard against side-channel attacks and ensure proper key management for offchain operations.
Token callbacks are associated with inherent security risks, including reentrancy and gas griefing. When utilizing callbacks, consider using reentrancy protection and setting a gas limit.