Tokens
This document is better viewed at https://docs.openzeppelin.com/confidential-contracts/api/token |
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.
-
ERC7984ERC20Wrapper
: Extension ofERC7984
which wraps anERC20
into a confidential token. The wrapper allows for free conversion in both directions at a fixed rate. -
ERC7984Freezable
: An extension ofERC7984
, which allows accounts granted the "freezer" role to freeze and unfreeze tokens. -
ERC7984ObserverAccess
: An extension ofERC7984
, which allows each account to add an observer who is given access to their transfer and balance amounts. -
ERC7984Restricted
: An extension ofERC7984
that implements user account transfer restrictions. -
ERC7984Omnibus
: An extension ofERC7984
that emits additional events for omnibus transfers, which contain encrypted addresses for the sub-account sender and recipient. -
ERC7984Rwa
: Extension ofERC7984
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 byERC7984
.
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
-
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)
-
OperatorSet(holder, operator, until)
-
ConfidentialTransfer(from, to, amount)
-
AmountDisclosed(encryptedAmount, amount)
-
ERC7984InvalidReceiver(receiver)
-
ERC7984InvalidSender(sender)
-
ERC7984UnauthorizedSpender(holder, spender)
-
ERC7984ZeroBalance(holder)
-
ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)
-
ERC7984UnauthorizedCaller(caller)
-
ERC7984InvalidGatewayRequest(requestId)
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.
_transferAndCall(address from, address to, euint64 amount, bytes data) → euint64 transferred
internal
ERC7984InvalidReceiver(address receiver)
error
The given receiver receiver
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. |
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. |
-
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()
-
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)
-
OperatorSet(holder, operator, until)
-
ConfidentialTransfer(from, to, amount)
-
AmountDisclosed(encryptedAmount, amount)
-
ERC7984InvalidReceiver(receiver)
-
ERC7984InvalidSender(sender)
-
ERC7984UnauthorizedSpender(holder, spender)
-
ERC7984ZeroBalance(holder)
-
ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)
-
ERC7984UnauthorizedCaller(caller)
-
ERC7984InvalidGatewayRequest(requestId)
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.
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.
_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.
-
confidentialFrozen(account)
-
confidentialAvailable(account)
-
_setConfidentialFrozen(account, encryptedAmount)
-
_update(from, to, encryptedAmount)
-
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)
-
TokensFrozen(account, encryptedAmount)
-
OperatorSet(holder, operator, until)
-
ConfidentialTransfer(from, to, amount)
-
AmountDisclosed(encryptedAmount, amount)
-
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
See ERC7984._update
.
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
.
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.
-
setObserver(account, newObserver)
-
observer(account)
-
_update(from, to, amount)
-
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)
-
ERC7984ObserverAccessObserverSet(account, oldObserver, newObserver)
-
OperatorSet(holder, operator, until)
-
ConfidentialTransfer(from, to, amount)
-
AmountDisclosed(encryptedAmount, amount)
-
Unauthorized()
-
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)
).
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.
-
getRestriction(account)
-
isUserAllowed(account)
-
_update(from, to, value)
-
_setRestriction(account, restriction)
-
_blockUser(account)
-
_allowUser(account)
-
_resetUser(account)
-
_checkRestriction(account)
-
_checkSenderRestriction(account)
-
_checkRecipientRestriction(account)
-
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)
-
UserRestrictionUpdated(account, restriction)
-
OperatorSet(holder, operator, until)
-
ConfidentialTransfer(from, to, amount)
-
AmountDisclosed(encryptedAmount, amount)
-
UserRestricted(account)
-
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:
-
from
must be allowed to transfer tokens (seeisUserAllowed
). -
to
must be allowed to receive tokens (seeisUserAllowed
).
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.
_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.
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. |
-
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)
-
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)
-
OmnibusConfidentialTransfer(omnibusFrom, omnibusTo, sender, recipient, amount)
-
OperatorSet(holder, operator, until)
-
ConfidentialTransfer(from, to, amount)
-
AmountDisclosed(encryptedAmount, amount)
-
ERC7984UnauthorizedUseOfEncryptedAddress(addr, user)
-
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 .
|
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.
-
onlyAdmin()
-
onlyAgent()
-
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()
-
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(data)
-
_requireNotPaused()
-
_requirePaused()
-
_pause()
-
_unpause()
-
getRestriction(account)
-
_setRestriction(account, restriction)
-
_blockUser(account)
-
_allowUser(account)
-
_resetUser(account)
-
_checkRestriction(account)
-
_checkRecipientRestriction(account)
-
_setConfidentialFrozen(account, encryptedAmount)
-
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)
-
Paused(account)
-
Unpaused(account)
-
UserRestrictionUpdated(account, restriction)
-
TokensFrozen(account, encryptedAmount)
-
RoleAdminChanged(role, previousAdminRole, newAdminRole)
-
RoleGranted(role, account, sender)
-
RoleRevoked(role, account, sender)
-
OperatorSet(holder, operator, until)
-
ConfidentialTransfer(from, to, amount)
-
AmountDisclosed(encryptedAmount, amount)
-
EnforcedPause()
-
ExpectedPause()
-
UserRestricted(account)
-
ERC7984InvalidReceiver(receiver)
-
ERC7984InvalidSender(sender)
-
ERC7984UnauthorizedSpender(holder, spender)
-
ERC7984ZeroBalance(holder)
-
ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)
-
ERC7984UnauthorizedCaller(caller)
-
ERC7984InvalidGatewayRequest(requestId)
-
AccessControlUnauthorizedAccount(account, neededRole)
-
AccessControlBadConfirmation()
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.
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.
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
.
Utilities
ERC7984Utils
import "@openzeppelin/confidential-contracts/token/ERC7984/utils/ERC7984Utils.sol";
Library that provides common ERC7984
utility 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.