Tokens

This set of interfaces, contracts, and utilities are all related to ERC7984, an evolving confidential token standard. The standard utilizes the Zama fhEVM co-processor for manipulating FHE values. All amounts are stored on-chain as ciphertext handles (or pointers) to values stored on the co-processor.

  • ERC7984: Implementation of IERC7984.

  • ERC7984ERC20Wrapper: Extension of ERC7984 which wraps an ERC20 into a confidential token. The wrapper allows for free conversion in both directions at a fixed rate.

  • ERC7984Freezable: An extension of ERC7984, which allows accounts granted the "freezer" role to freeze and unfreeze tokens.

  • ERC7984ObserverAccess: An extension of ERC7984, which allows each account to add an observer who is given access to their transfer and balance amounts.

  • ERC7984Restricted: An extension of ERC7984 that implements user account transfer restrictions.

  • ERC7984Omnibus: An extension of ERC7984 that emits additional events for omnibus transfers, which contain encrypted addresses for the sub-account sender and recipient.

  • ERC7984Rwa: Extension of ERC7984 that supports confidential Real World Assets (RWAs) by providing compliance checks, transfer controls and enforcement actions.

  • ERC7984Utils: A library that provides the on-transfer callback check used by ERC7984.

Core

ERC7984

import "@openzeppelin/confidential-contracts/token/ERC7984/ERC7984.sol";

Reference implementation for IERC7984.

This contract implements a fungible token where balances and transfers are encrypted using the Zama fhEVM, providing confidentiality to users. Token amounts are stored as encrypted, unsigned integers (euint64) that can only be decrypted by authorized parties.

Key features:

  • All balances are encrypted

  • Transfers happen without revealing amounts

  • Support for operators (delegated transfer capabilities with time bounds)

  • Transfer and call pattern

  • Safe overflow/underflow handling for FHE operations

Functions
  • constructor(name_, symbol_, tokenURI_)

  • name()

  • symbol()

  • decimals()

  • tokenURI()

  • confidentialTotalSupply()

  • confidentialBalanceOf(account)

  • isOperator(holder, spender)

  • setOperator(operator, until)

  • confidentialTransfer(to, encryptedAmount, inputProof)

  • confidentialTransfer(to, amount)

  • confidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • confidentialTransferFrom(from, to, amount)

  • confidentialTransferAndCall(to, encryptedAmount, inputProof, data)

  • confidentialTransferAndCall(to, amount, data)

  • confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)

  • confidentialTransferFromAndCall(from, to, amount, data)

  • discloseEncryptedAmount(encryptedAmount)

  • finalizeDiscloseEncryptedAmount(requestId, cleartexts, decryptionProof)

  • _setOperator(holder, operator, until)

  • _mint(to, amount)

  • _burn(from, amount)

  • _transfer(from, to, amount)

  • _transferAndCall(from, to, amount, data)

  • _update(from, to, amount)

Events
IERC7984
  • OperatorSet(holder, operator, until)

  • ConfidentialTransfer(from, to, amount)

  • AmountDisclosed(encryptedAmount, amount)

Errors
  • ERC7984InvalidReceiver(receiver)

  • ERC7984InvalidSender(sender)

  • ERC7984UnauthorizedSpender(holder, spender)

  • ERC7984ZeroBalance(holder)

  • ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)

  • ERC7984UnauthorizedCaller(caller)

  • ERC7984InvalidGatewayRequest(requestId)

constructor(string name_, string symbol_, string tokenURI_) internal

name() → string public

Returns the name of the token.

symbol() → string public

Returns the symbol of the token.

decimals() → uint8 public

Returns the number of decimals of the token. Recommended to be 6.

tokenURI() → string public

Returns the token URI.

confidentialTotalSupply() → euint64 public

Returns the confidential total supply of the token.

confidentialBalanceOf(address account) → euint64 public

Returns the confidential balance of the account account.

isOperator(address holder, address spender) → bool public

Returns true if spender is currently an operator for holder.

setOperator(address operator, uint48 until) public

Sets operator as an operator for holder until the timestamp until.

An operator may transfer any amount of tokens on behalf of a holder while approved.

confidentialTransfer(address to, externalEuint64 encryptedAmount, bytes inputProof) → euint64 public

Transfers the encrypted amount encryptedAmount to to with the given input proof inputProof.

Returns the encrypted amount that was actually transferred.

confidentialTransfer(address to, euint64 amount) → euint64 public

Similar to confidentialTransfer but without an input proof. The caller must already be allowed by ACL for the given amount.

confidentialTransferFrom(address from, address to, externalEuint64 encryptedAmount, bytes inputProof) → euint64 transferred public

Transfers the encrypted amount encryptedAmount from from to to with the given input proof inputProof. msg.sender must be either from or an operator for from.

Returns the encrypted amount that was actually transferred.

confidentialTransferFrom(address from, address to, euint64 amount) → euint64 transferred public

Similar to confidentialTransferFrom but without an input proof. The caller must be already allowed by ACL for the given amount.

confidentialTransferAndCall(address to, externalEuint64 encryptedAmount, bytes inputProof, bytes data) → euint64 transferred public

Similar to confidentialTransfer but with a callback to to after the transfer.

The callback is made to the IERC7984Receiver.onConfidentialTransferReceived function on the to address with the actual transferred amount (may differ from the given encryptedAmount) and the given data data.

confidentialTransferAndCall(address to, euint64 amount, bytes data) → euint64 transferred public

Similar to confidentialTransfer but with a callback to to after the transfer.

confidentialTransferFromAndCall(address from, address to, externalEuint64 encryptedAmount, bytes inputProof, bytes data) → euint64 transferred public

Similar to confidentialTransferFrom but with a callback to to after the transfer.

confidentialTransferFromAndCall(address from, address to, euint64 amount, bytes data) → euint64 transferred public

Similar to confidentialTransferFrom but with a callback to to after the transfer.

discloseEncryptedAmount(euint64 encryptedAmount) public

Discloses an encrypted amount encryptedAmount publicly via an IERC7984.AmountDisclosed event. The caller and this contract must be authorized to use the encrypted amount on the ACL.

This is an asynchronous operation where the actual decryption happens off-chain and finalizeDiscloseEncryptedAmount is called with the result.

finalizeDiscloseEncryptedAmount(uint256 requestId, bytes cleartexts, bytes decryptionProof) public

Finalizes a disclose encrypted amount request. For gas saving purposes, the requestId might not be related to a discloseEncryptedAmount request. As a result, the current finalizeDiscloseEncryptedAmount function might emit a disclosed amount related to another decryption request context. In this case it would only display public information since the handle would have already been allowed for public decryption through a previous FHE.requestDecryption call. The downside of this behavior is that a finalizeDiscloseEncryptedAmount watcher might observe unexpected AmountDisclosed events.

_setOperator(address holder, address operator, uint48 until) internal

_mint(address to, euint64 amount) → euint64 transferred internal

_burn(address from, euint64 amount) → euint64 transferred internal

_transfer(address from, address to, euint64 amount) → euint64 transferred internal

_transferAndCall(address from, address to, euint64 amount, bytes data) → euint64 transferred internal

_update(address from, address to, euint64 amount) → euint64 transferred internal

ERC7984InvalidReceiver(address receiver) error

The given receiver receiver is invalid for transfers.

ERC7984InvalidSender(address sender) error

The given sender sender is invalid for transfers.

ERC7984UnauthorizedSpender(address holder, address spender) error

The given holder holder is not authorized to spend on behalf of spender.

ERC7984ZeroBalance(address holder) error

The holder holder is trying to send tokens but has a balance of 0.

ERC7984UnauthorizedUseOfEncryptedAmount(euint64 amount, address user) error

The caller user does not have access to the encrypted amount amount.

Try using the equivalent transfer function with an input proof.

ERC7984UnauthorizedCaller(address caller) error

The given caller caller is not authorized for the current operation.

ERC7984InvalidGatewayRequest(uint256 requestId) error

The given gateway request ID requestId is invalid.

Extensions

ERC7984ERC20Wrapper

import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol";

A wrapper contract built on top of ERC7984 that allows wrapping an ERC20 token into an ERC7984 token. The wrapper contract implements the IERC1363Receiver interface which allows users to transfer ERC1363 tokens directly to the wrapper with a callback to wrap the tokens.

Minting assumes the full amount of the underlying token transfer has been received, hence some non-standard tokens such as fee-on-transfer or other deflationary-type tokens are not supported by this wrapper.
Functions
  • constructor(underlying_)

  • decimals()

  • rate()

  • underlying()

  • onTransferReceived(, from, amount, data)

  • wrap(to, amount)

  • unwrap(from, to, amount)

  • unwrap(from, to, encryptedAmount, inputProof)

  • finalizeUnwrap(requestID, cleartexts, decryptionProof)

  • _unwrap(from, to, amount)

  • _fallbackUnderlyingDecimals()

  • _maxDecimals()

ERC7984
  • name()

  • symbol()

  • tokenURI()

  • confidentialTotalSupply()

  • confidentialBalanceOf(account)

  • isOperator(holder, spender)

  • setOperator(operator, until)

  • confidentialTransfer(to, encryptedAmount, inputProof)

  • confidentialTransfer(to, amount)

  • confidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • confidentialTransferFrom(from, to, amount)

  • confidentialTransferAndCall(to, encryptedAmount, inputProof, data)

  • confidentialTransferAndCall(to, amount, data)

  • confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)

  • confidentialTransferFromAndCall(from, to, amount, data)

  • discloseEncryptedAmount(encryptedAmount)

  • finalizeDiscloseEncryptedAmount(requestId, cleartexts, decryptionProof)

  • _setOperator(holder, operator, until)

  • _mint(to, amount)

  • _burn(from, amount)

  • _transfer(from, to, amount)

  • _transferAndCall(from, to, amount, data)

  • _update(from, to, amount)

Events
IERC7984
  • OperatorSet(holder, operator, until)

  • ConfidentialTransfer(from, to, amount)

  • AmountDisclosed(encryptedAmount, amount)

Errors
ERC7984
  • ERC7984InvalidReceiver(receiver)

  • ERC7984InvalidSender(sender)

  • ERC7984UnauthorizedSpender(holder, spender)

  • ERC7984ZeroBalance(holder)

  • ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)

  • ERC7984UnauthorizedCaller(caller)

  • ERC7984InvalidGatewayRequest(requestId)

constructor(contract IERC20 underlying_) internal

decimals() → uint8 public

Returns the number of decimals of the token. Recommended to be 6.

rate() → uint256 public

Returns the rate at which the underlying token is converted to the wrapped token. For example, if the rate is 1000, then 1000 units of the underlying token equal 1 unit of the wrapped token.

underlying() → contract IERC20 public

Returns the address of the underlying ERC-20 token that is being wrapped.

onTransferReceived(address, address from, uint256 amount, bytes data) → bytes4 public

ERC1363 callback function which wraps tokens to the address specified in data or the address from (if no address is specified in data). This function refunds any excess tokens sent beyond the nearest multiple of rate. See wrap from more details on wrapping tokens.

wrap(address to, uint256 amount) public

Wraps amount amount of the underlying token into a confidential token and sends it to to. Tokens are exchanged at a fixed rate specified by rate such that amount / rate() confidential tokens are sent. Amount transferred in is rounded down to the nearest multiple of rate.

unwrap(address from, address to, euint64 amount) public

Unwraps tokens from from and sends the underlying tokens to to. The caller must be from or be an approved operator for from. amount * rate() underlying tokens are sent to to.

This is an asynchronous function and waits for decryption to be completed off-chain before disbursing tokens. NOTE: The caller must already be approved by ACL for the given amount.

unwrap(address from, address to, externalEuint64 encryptedAmount, bytes inputProof) public

Variant of unwrap that passes an inputProof which approves the caller for the encryptedAmount in the ACL.

finalizeUnwrap(uint256 requestID, bytes cleartexts, bytes decryptionProof) public

Fills an unwrap request for a given request id related to a decrypted unwrap amount.

_unwrap(address from, address to, euint64 amount) internal

_fallbackUnderlyingDecimals() → uint8 internal

Returns the default number of decimals of the underlying ERC-20 token that is being wrapped. Used as a default fallback when {_tryGetAssetDecimals} fails to fetch decimals of the underlying ERC-20 token.

_maxDecimals() → uint8 internal

Returns the maximum number that will be used for decimals by the wrapper.

ERC7984Freezable

import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Freezable.sol";

Extension of ERC7984 that implements a confidential freezing mechanism that can be managed by an authorized account with {setConfidentialFrozen} functions.

The freezing mechanism provides the guarantee to the contract owner (e.g. a DAO or a well-configured multisig) that a specific confidential amount of tokens held by an account won’t be transferable until those tokens are unfrozen.

Functions
  • confidentialFrozen(account)

  • confidentialAvailable(account)

  • _setConfidentialFrozen(account, encryptedAmount)

  • _update(from, to, encryptedAmount)

ERC7984
  • name()

  • symbol()

  • decimals()

  • tokenURI()

  • confidentialTotalSupply()

  • confidentialBalanceOf(account)

  • isOperator(holder, spender)

  • setOperator(operator, until)

  • confidentialTransfer(to, encryptedAmount, inputProof)

  • confidentialTransfer(to, amount)

  • confidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • confidentialTransferFrom(from, to, amount)

  • confidentialTransferAndCall(to, encryptedAmount, inputProof, data)

  • confidentialTransferAndCall(to, amount, data)

  • confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)

  • confidentialTransferFromAndCall(from, to, amount, data)

  • discloseEncryptedAmount(encryptedAmount)

  • finalizeDiscloseEncryptedAmount(requestId, cleartexts, decryptionProof)

  • _setOperator(holder, operator, until)

  • _mint(to, amount)

  • _burn(from, amount)

  • _transfer(from, to, amount)

  • _transferAndCall(from, to, amount, data)

Events
  • TokensFrozen(account, encryptedAmount)

IERC7984
  • OperatorSet(holder, operator, until)

  • ConfidentialTransfer(from, to, amount)

  • AmountDisclosed(encryptedAmount, amount)

Errors
ERC7984
  • ERC7984InvalidReceiver(receiver)

  • ERC7984InvalidSender(sender)

  • ERC7984UnauthorizedSpender(holder, spender)

  • ERC7984ZeroBalance(holder)

  • ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)

  • ERC7984UnauthorizedCaller(caller)

  • ERC7984InvalidGatewayRequest(requestId)

confidentialFrozen(address account) → euint64 public

Returns the confidential frozen balance of an account.

confidentialAvailable(address account) → euint64 public

Returns the confidential available (unfrozen) balance of an account. Up to confidentialBalanceOf.

_setConfidentialFrozen(address account, euint64 encryptedAmount) internal

Internal function to freeze a confidential amount of tokens for an account.

_update(address from, address to, euint64 encryptedAmount) → euint64 internal

The from account must have sufficient unfrozen balance, otherwise 0 tokens are transferred. The default freezing behavior can be changed (for a pass-through for instance) by overriding confidentialAvailable.

TokensFrozen(address indexed account, euint64 encryptedAmount) event

Emitted when a confidential amount of token is frozen for an account

ERC7984ObserverAccess

import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984ObserverAccess.sol";

Extension of ERC7984 that allows each account to add a observer who is given permanent ACL access to its transfer and balance amounts. A observer can be added or removed at any point in time.

Functions
  • setObserver(account, newObserver)

  • observer(account)

  • _update(from, to, amount)

ERC7984
  • name()

  • symbol()

  • decimals()

  • tokenURI()

  • confidentialTotalSupply()

  • confidentialBalanceOf(account)

  • isOperator(holder, spender)

  • setOperator(operator, until)

  • confidentialTransfer(to, encryptedAmount, inputProof)

  • confidentialTransfer(to, amount)

  • confidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • confidentialTransferFrom(from, to, amount)

  • confidentialTransferAndCall(to, encryptedAmount, inputProof, data)

  • confidentialTransferAndCall(to, amount, data)

  • confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)

  • confidentialTransferFromAndCall(from, to, amount, data)

  • discloseEncryptedAmount(encryptedAmount)

  • finalizeDiscloseEncryptedAmount(requestId, cleartexts, decryptionProof)

  • _setOperator(holder, operator, until)

  • _mint(to, amount)

  • _burn(from, amount)

  • _transfer(from, to, amount)

  • _transferAndCall(from, to, amount, data)

Events
  • ERC7984ObserverAccessObserverSet(account, oldObserver, newObserver)

IERC7984
  • OperatorSet(holder, operator, until)

  • ConfidentialTransfer(from, to, amount)

  • AmountDisclosed(encryptedAmount, amount)

Errors
  • Unauthorized()

ERC7984
  • ERC7984InvalidReceiver(receiver)

  • ERC7984InvalidSender(sender)

  • ERC7984UnauthorizedSpender(holder, spender)

  • ERC7984ZeroBalance(holder)

  • ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)

  • ERC7984UnauthorizedCaller(caller)

  • ERC7984InvalidGatewayRequest(requestId)

setObserver(address account, address newObserver) public

Sets the observer for the given account account to newObserver. Can be called by the account or the existing observer to abdicate the observer role (may only set to address(0)).

observer(address account) → address public

Returns the observer for the given account account.

_update(address from, address to, euint64 amount) → euint64 transferred internal

ERC7984ObserverAccessObserverSet(address account, address oldObserver, address newObserver) event

Emitted when the observer is changed for the given account account.

Unauthorized() error

Thrown when an account tries to set a newObserver for a given account without proper authority.

ERC7984Restricted

import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Restricted.sol";

Extension of ERC7984 that implements user account transfer restrictions through the isUserAllowed function. Inspired by https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Restricted.sol.

By default, each account has no explicit restriction. The isUserAllowed function acts as a blocklist. Developers can override isUserAllowed to check that restriction == ALLOWED to implement an allowlist.

Functions
  • getRestriction(account)

  • isUserAllowed(account)

  • _update(from, to, value)

  • _setRestriction(account, restriction)

  • _blockUser(account)

  • _allowUser(account)

  • _resetUser(account)

  • _checkRestriction(account)

  • _checkSenderRestriction(account)

  • _checkRecipientRestriction(account)

ERC7984
  • name()

  • symbol()

  • decimals()

  • tokenURI()

  • confidentialTotalSupply()

  • confidentialBalanceOf(account)

  • isOperator(holder, spender)

  • setOperator(operator, until)

  • confidentialTransfer(to, encryptedAmount, inputProof)

  • confidentialTransfer(to, amount)

  • confidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • confidentialTransferFrom(from, to, amount)

  • confidentialTransferAndCall(to, encryptedAmount, inputProof, data)

  • confidentialTransferAndCall(to, amount, data)

  • confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)

  • confidentialTransferFromAndCall(from, to, amount, data)

  • discloseEncryptedAmount(encryptedAmount)

  • finalizeDiscloseEncryptedAmount(requestId, cleartexts, decryptionProof)

  • _setOperator(holder, operator, until)

  • _mint(to, amount)

  • _burn(from, amount)

  • _transfer(from, to, amount)

  • _transferAndCall(from, to, amount, data)

Events
  • UserRestrictionUpdated(account, restriction)

IERC7984
  • OperatorSet(holder, operator, until)

  • ConfidentialTransfer(from, to, amount)

  • AmountDisclosed(encryptedAmount, amount)

Errors
  • UserRestricted(account)

ERC7984
  • ERC7984InvalidReceiver(receiver)

  • ERC7984InvalidSender(sender)

  • ERC7984UnauthorizedSpender(holder, spender)

  • ERC7984ZeroBalance(holder)

  • ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)

  • ERC7984UnauthorizedCaller(caller)

  • ERC7984InvalidGatewayRequest(requestId)

getRestriction(address account) → enum ERC7984Restricted.Restriction public

Returns the restriction of a user account.

isUserAllowed(address account) → bool public

Returns whether a user account is allowed to interact with the token.

Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist).

To convert into an allowlist, override as:

function isUserAllowed(address account) public view virtual override returns (bool) {
    return getRestriction(account) == Restriction.ALLOWED;
}

_update(address from, address to, euint64 value) → euint64 internal

See ERC7984._update. Enforces transfer restrictions (excluding minting and burning).

Requirements:

The default restriction behaviour can be changed (for a pass-through for instance) by overriding _checkSenderRestriction and/or _checkRecipientRestriction.

_setRestriction(address account, enum ERC7984Restricted.Restriction restriction) internal

Updates the restriction of a user account.

_blockUser(address account) internal

Convenience function to block a user account (set to BLOCKED).

_allowUser(address account) internal

Convenience function to allow a user account (set to ALLOWED).

_resetUser(address account) internal

Convenience function to reset a user account to default restriction.

_checkRestriction(address account) internal

Checks if a user account is restricted. Reverts with {ERC20Restricted} if so.

_checkSenderRestriction(address account) internal

Internal function which checks restriction of the from account before a transfer. Working with _update function.

_checkRecipientRestriction(address account) internal

Internal function which checks restriction of the to account before a transfer. Working with _update function.

UserRestrictionUpdated(address indexed account, enum ERC7984Restricted.Restriction restriction) event

Emitted when a user account’s restriction is updated.

UserRestricted(address account) error

The operation failed because the user account is restricted.

ERC7984Omnibus

import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Omnibus.sol";

Extension of ERC7984 that emits additional events for omnibus transfers. These events contain encrypted addresses for the sub-account sender and recipient.

There is no onchain accounting for sub-accounts—​integrators must track sub-account balances externally.
Functions
  • confidentialTransferOmnibus(omnibusTo, externalSender, externalRecipient, externalAmount, inputProof)

  • confidentialTransferOmnibus(omnibusTo, sender, recipient, amount)

  • confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, externalSender, externalRecipient, externalAmount, inputProof)

  • confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount)

  • confidentialTransferAndCallOmnibus(omnibusTo, externalSender, externalRecipient, externalAmount, inputProof, data)

  • confidentialTransferAndCallOmnibus(omnibusTo, sender, recipient, amount, data)

  • confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, externalSender, externalRecipient, externalAmount, inputProof, data)

  • confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data)

  • _confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount)

  • _confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data)

ERC7984
  • name()

  • symbol()

  • decimals()

  • tokenURI()

  • confidentialTotalSupply()

  • confidentialBalanceOf(account)

  • isOperator(holder, spender)

  • setOperator(operator, until)

  • confidentialTransfer(to, encryptedAmount, inputProof)

  • confidentialTransfer(to, amount)

  • confidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • confidentialTransferFrom(from, to, amount)

  • confidentialTransferAndCall(to, encryptedAmount, inputProof, data)

  • confidentialTransferAndCall(to, amount, data)

  • confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)

  • confidentialTransferFromAndCall(from, to, amount, data)

  • discloseEncryptedAmount(encryptedAmount)

  • finalizeDiscloseEncryptedAmount(requestId, cleartexts, decryptionProof)

  • _setOperator(holder, operator, until)

  • _mint(to, amount)

  • _burn(from, amount)

  • _transfer(from, to, amount)

  • _transferAndCall(from, to, amount, data)

  • _update(from, to, amount)

Events
  • OmnibusConfidentialTransfer(omnibusFrom, omnibusTo, sender, recipient, amount)

IERC7984
  • OperatorSet(holder, operator, until)

  • ConfidentialTransfer(from, to, amount)

  • AmountDisclosed(encryptedAmount, amount)

Errors
  • ERC7984UnauthorizedUseOfEncryptedAddress(addr, user)

ERC7984
  • ERC7984InvalidReceiver(receiver)

  • ERC7984InvalidSender(sender)

  • ERC7984UnauthorizedSpender(holder, spender)

  • ERC7984ZeroBalance(holder)

  • ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)

  • ERC7984UnauthorizedCaller(caller)

  • ERC7984InvalidGatewayRequest(requestId)

confidentialTransferOmnibus(address omnibusTo, externalEaddress externalSender, externalEaddress externalRecipient, externalEuint64 externalAmount, bytes inputProof) → euint64 public

Wraps the confidentialTransfer function and emits the OmnibusConfidentialTransfer event.

confidentialTransferOmnibus(address omnibusTo, eaddress sender, eaddress recipient, euint64 amount) → euint64 public

Wraps the confidentialTransfer function and emits the OmnibusConfidentialTransfer event.

confidentialTransferFromOmnibus(address omnibusFrom, address omnibusTo, externalEaddress externalSender, externalEaddress externalRecipient, externalEuint64 externalAmount, bytes inputProof) → euint64 public

Wraps the confidentialTransferFrom function and emits the OmnibusConfidentialTransfer event.

confidentialTransferFromOmnibus(address omnibusFrom, address omnibusTo, eaddress sender, eaddress recipient, euint64 amount) → euint64 public

Wraps the confidentialTransferFrom function and emits the OmnibusConfidentialTransfer event.

confidentialTransferAndCallOmnibus(address omnibusTo, externalEaddress externalSender, externalEaddress externalRecipient, externalEuint64 externalAmount, bytes inputProof, bytes data) → euint64 public

Wraps the confidentialTransferAndCall function and emits the OmnibusConfidentialTransfer event.

confidentialTransferAndCallOmnibus(address omnibusTo, eaddress sender, eaddress recipient, euint64 amount, bytes data) → euint64 public

Wraps the confidentialTransferAndCall function and emits the OmnibusConfidentialTransfer event.

confidentialTransferFromAndCallOmnibus(address omnibusFrom, address omnibusTo, externalEaddress externalSender, externalEaddress externalRecipient, externalEuint64 externalAmount, bytes inputProof, bytes data) → euint64 public

Wraps the confidentialTransferFromAndCall function and emits the OmnibusConfidentialTransfer event.

confidentialTransferFromAndCallOmnibus(address omnibusFrom, address omnibusTo, eaddress sender, eaddress recipient, euint64 amount, bytes data) → euint64 public

Wraps the confidentialTransferFromAndCall function and emits the OmnibusConfidentialTransfer event.

_confidentialTransferFromOmnibus(address omnibusFrom, address omnibusTo, eaddress sender, eaddress recipient, euint64 amount) → euint64 internal

Handles the ACL allowances, does the transfer without a callback, and emits OmnibusConfidentialTransfer.

_confidentialTransferFromAndCallOmnibus(address omnibusFrom, address omnibusTo, eaddress sender, eaddress recipient, euint64 amount, bytes data) → euint64 internal

Handles the ACL allowances, does the transfer with a callback, and emits OmnibusConfidentialTransfer.

OmnibusConfidentialTransfer(address indexed omnibusFrom, address indexed omnibusTo, eaddress sender, eaddress indexed recipient, euint64 amount) event

Emitted when a confidential transfer is made representing the onchain settlement of an omnibus transfer from sender to recipient of amount amount. Settlement occurs between omnibusFrom and omnibusTo and is represented in a matching IERC7984.ConfidentialTransfer event.

omnibusFrom and omnibusTo get permanent ACL allowances for sender and recipient.

ERC7984UnauthorizedUseOfEncryptedAddress(eaddress addr, address user) error

The caller user does not have access to the encrypted address addr.

Try using the equivalent transfer function with an input proof.

ERC7984Rwa

import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Rwa.sol";

Extension of ERC7984 that supports confidential Real World Assets (RWAs). This interface provides compliance checks, transfer controls and enforcement actions.

Modifiers
  • onlyAdmin()

  • onlyAgent()

Functions
  • constructor(admin)

  • supportsInterface(interfaceId)

  • isAdmin(account)

  • isAgent(account)

  • isAdminOrAgent(account)

  • addAgent(account)

  • removeAgent(account)

  • pause()

  • unpause()

  • blockUser(account)

  • unblockUser(account)

  • setConfidentialFrozen(account, encryptedAmount, inputProof)

  • setConfidentialFrozen(account, encryptedAmount)

  • confidentialMint(to, encryptedAmount, inputProof)

  • confidentialMint(to, encryptedAmount)

  • confidentialBurn(account, encryptedAmount, inputProof)

  • confidentialBurn(account, encryptedAmount)

  • forceConfidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • forceConfidentialTransferFrom(from, to, encryptedAmount)

  • confidentialAvailable(account)

  • confidentialFrozen(account)

  • paused()

  • isUserAllowed(account)

  • _update(from, to, encryptedAmount)

  • _forceUpdate(from, to, encryptedAmount)

  • _checkSenderRestriction(account)

  • AGENT_ROLE()

AccessControl
  • hasRole(role, account)

  • _checkRole(role)

  • _checkRole(role, account)

  • getRoleAdmin(role)

  • grantRole(role, account)

  • revokeRole(role, account)

  • renounceRole(role, callerConfirmation)

  • _setRoleAdmin(role, adminRole)

  • _grantRole(role, account)

  • _revokeRole(role, account)

  • DEFAULT_ADMIN_ROLE()

Multicall
  • multicall(data)

Pausable
  • _requireNotPaused()

  • _requirePaused()

  • _pause()

  • _unpause()

ERC7984Restricted
  • getRestriction(account)

  • _setRestriction(account, restriction)

  • _blockUser(account)

  • _allowUser(account)

  • _resetUser(account)

  • _checkRestriction(account)

  • _checkRecipientRestriction(account)

ERC7984Freezable
  • _setConfidentialFrozen(account, encryptedAmount)

ERC7984
  • name()

  • symbol()

  • decimals()

  • tokenURI()

  • confidentialTotalSupply()

  • confidentialBalanceOf(account)

  • isOperator(holder, spender)

  • setOperator(operator, until)

  • confidentialTransfer(to, encryptedAmount, inputProof)

  • confidentialTransfer(to, amount)

  • confidentialTransferFrom(from, to, encryptedAmount, inputProof)

  • confidentialTransferFrom(from, to, amount)

  • confidentialTransferAndCall(to, encryptedAmount, inputProof, data)

  • confidentialTransferAndCall(to, amount, data)

  • confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)

  • confidentialTransferFromAndCall(from, to, amount, data)

  • discloseEncryptedAmount(encryptedAmount)

  • finalizeDiscloseEncryptedAmount(requestId, cleartexts, decryptionProof)

  • _setOperator(holder, operator, until)

  • _mint(to, amount)

  • _burn(from, amount)

  • _transfer(from, to, amount)

  • _transferAndCall(from, to, amount, data)

Events
Pausable
  • Paused(account)

  • Unpaused(account)

ERC7984Restricted
  • UserRestrictionUpdated(account, restriction)

ERC7984Freezable
  • TokensFrozen(account, encryptedAmount)

IAccessControl
  • RoleAdminChanged(role, previousAdminRole, newAdminRole)

  • RoleGranted(role, account, sender)

  • RoleRevoked(role, account, sender)

IERC7984
  • OperatorSet(holder, operator, until)

  • ConfidentialTransfer(from, to, amount)

  • AmountDisclosed(encryptedAmount, amount)

Errors
Pausable
  • EnforcedPause()

  • ExpectedPause()

ERC7984Restricted
  • UserRestricted(account)

ERC7984
  • ERC7984InvalidReceiver(receiver)

  • ERC7984InvalidSender(sender)

  • ERC7984UnauthorizedSpender(holder, spender)

  • ERC7984ZeroBalance(holder)

  • ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)

  • ERC7984UnauthorizedCaller(caller)

  • ERC7984InvalidGatewayRequest(requestId)

IAccessControl
  • AccessControlUnauthorizedAccount(account, neededRole)

  • AccessControlBadConfirmation()

onlyAdmin() modifier

Checks if the sender is an admin.

onlyAgent() modifier

Checks if the sender is an agent.

constructor(address admin) internal

supportsInterface(bytes4 interfaceId) → bool public

Returns true if this contract implements the interface defined by interfaceId. See the corresponding ERC section to learn more about how these ids are created.

This function call must use less than 30 000 gas.

isAdmin(address account) → bool public

Returns true if has admin role, false otherwise.

isAgent(address account) → bool public

Returns true if agent, false otherwise.

isAdminOrAgent(address account) → bool public

Returns true if admin or agent, false otherwise.

addAgent(address account) public

Adds agent.

removeAgent(address account) public

Removes agent.

pause() public

Pauses contract.

unpause() public

Unpauses contract.

blockUser(address account) public

Blocks a user account.

unblockUser(address account) public

Unblocks a user account.

setConfidentialFrozen(address account, externalEuint64 encryptedAmount, bytes inputProof) public

Sets confidential frozen for an account.

setConfidentialFrozen(address account, euint64 encryptedAmount) public

Sets confidential frozen for an account with proof.

confidentialMint(address to, externalEuint64 encryptedAmount, bytes inputProof) → euint64 public

Mints confidential amount of tokens to account with proof.

confidentialMint(address to, euint64 encryptedAmount) → euint64 public

Mints confidential amount of tokens to account.

confidentialBurn(address account, externalEuint64 encryptedAmount, bytes inputProof) → euint64 public

Burns confidential amount of tokens from account with proof.

confidentialBurn(address account, euint64 encryptedAmount) → euint64 public

Burns confidential amount of tokens from account.

forceConfidentialTransferFrom(address from, address to, externalEuint64 encryptedAmount, bytes inputProof) → euint64 public

Forces transfer of confidential amount of tokens from account to account with proof by skipping compliance checks.

forceConfidentialTransferFrom(address from, address to, euint64 encryptedAmount) → euint64 transferred public

Forces transfer of confidential amount of tokens from account to account by skipping compliance checks.

confidentialAvailable(address account) → euint64 public

Returns the confidential available (unfrozen) balance of an account. Up to confidentialBalanceOf.

confidentialFrozen(address account) → euint64 public

Returns the confidential frozen balance of an account.

paused() → bool public

Returns true if the contract is paused, and false otherwise.

isUserAllowed(address account) → bool public

Returns whether a user account is allowed to interact with the token.

Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist).

To convert into an allowlist, override as:

function isUserAllowed(address account) public view virtual override returns (bool) {
    return getRestriction(account) == Restriction.ALLOWED;
}

_update(address from, address to, euint64 encryptedAmount) → euint64 internal

Internal function which updates confidential balances while performing frozen and restriction compliance checks.

_forceUpdate(address from, address to, euint64 encryptedAmount) → euint64 internal

Internal function which forces transfer of confidential amount of tokens from account to account by skipping compliance checks.

_checkSenderRestriction(address account) internal

Bypasses the from restriction check when performing a forceConfidentialTransferFrom.

AGENT_ROLE() → bytes32 public

Utilities

ERC7984Utils

import "@openzeppelin/confidential-contracts/token/ERC7984/utils/ERC7984Utils.sol";

Library that provides common ERC7984 utility functions.

Functions
  • checkOnTransferReceived(operator, from, to, amount, data)

checkOnTransferReceived(address operator, address from, address to, euint64 amount, bytes data) → ebool internal

Performs a transfer callback to the recipient of the transfer to. Should be invoked after all transfers "withCallback" on a ERC7984.

The transfer callback is not invoked on the recipient if the recipient has no code (i.e. is an EOA). If the recipient has non-zero code, it must implement IERC7984Receiver.onConfidentialTransferReceived and return an ebool indicating whether the transfer was accepted or not. If the ebool is false, the transfer will be reversed.