diff --git a/content/confidential-contracts/api/finance.mdx b/content/confidential-contracts/api/finance.mdx index 46be5ad3..082b6202 100644 --- a/content/confidential-contracts/api/finance.mdx +++ b/content/confidential-contracts/api/finance.mdx @@ -25,7 +25,7 @@ For convenience, this directory also includes: ## `BatcherConfidential` - + @@ -36,8 +36,8 @@ import "@openzeppelin/confidential-contracts/finance/BatcherConfidential.sol"; ``` `BatcherConfidential` is a batching primitive that enables routing between two [`ERC7984ERC20Wrapper`](/confidential-contracts/api/token#ERC7984ERC20Wrapper) contracts -via a non-confidential route. Users deposit [`BatcherConfidential.fromToken`](#BatcherConfidential-fromToken--) into the batcher and receive [`BatcherConfidential.toToken`](#BatcherConfidential-toToken--) in exchange. Deposits are -made by using `ERC7984` transfer and call functions such as [`ERC7984.confidentialTransferAndCall`](/confidential-contracts/api/token#ERC7984-confidentialTransferAndCall-address-euint64-bytes-). +(with distinct underlying tokens) via a non-confidential route. Users deposit [`BatcherConfidential.fromToken`](#BatcherConfidential-fromToken--) into the batcher and receive +[`BatcherConfidential.toToken`](#BatcherConfidential-toToken--) in exchange. Deposits are made by using `ERC7984` transfer and call functions such as [`ERC7984.confidentialTransferAndCall`](/confidential-contracts/api/token#ERC7984-confidentialTransferAndCall-address-euint64-bytes-). Developers must implement the virtual function [`BatcherConfidential._executeRoute`](#BatcherConfidential-_executeRoute-uint256-uint256-) to perform the batch's route. This function is called once the batch deposits are unwrapped into the underlying tokens. The function should swap the underlying [`BatcherConfidential.fromToken`](#BatcherConfidential-fromToken--) for @@ -119,6 +119,8 @@ underlying tokens into [`BatcherConfidential.toToken`](#BatcherConfidential-toTo - [InvalidExchangeRate(batchId, totalDeposits, exchangeRate)](#BatcherConfidential-InvalidExchangeRate-uint256-uint256-uint64-) - [Unauthorized()](#BatcherConfidential-Unauthorized--) - [InvalidWrapperToken(token)](#BatcherConfidential-InvalidWrapperToken-address-) +- [DuplicateUnderlyingTokens()](#BatcherConfidential-DuplicateUnderlyingTokens--) +- [IntermediateStepToTokenBalanceChanged(batchId)](#BatcherConfidential-IntermediateStepToTokenBalanceChanged-uint256-)
ReentrancyGuardTransient @@ -485,7 +487,7 @@ the balance of the underlying [`BatcherConfidential.toToken`](#BatcherConfidenti [`BatcherConfidential.dispatchBatchCallback`](#BatcherConfidential-dispatchBatchCallback-uint256-uint64-bytes-) (and in turn [`BatcherConfidential._executeRoute`](#BatcherConfidential-_executeRoute-uint256-uint256-)) can be repeatedly called until the route execution is complete. If a multi-step route is necessary, intermediate steps should return `ExecuteOutcome.Partial`. Intermediate steps *must* not -result in underlying [`BatcherConfidential.toToken`](#BatcherConfidential-toToken--) being transferred into the batcher. +result in underlying [`BatcherConfidential.toToken`](#BatcherConfidential-toToken--) being transferred to or from the batcher. @@ -771,13 +773,47 @@ The given `token` does not support `IERC7984ERC20Wrapper` via `ERC165`. + + +
+
+

DuplicateUnderlyingTokens()

+
+

error

+# +
+
+
+ +The underlying wrapper tokens are the same. + +
+
+ + + +
+
+

IntermediateStepToTokenBalanceChanged(uint256 batchId)

+
+

error

+# +
+
+
+ +Intermediate steps must not result in underlying [`BatcherConfidential.toToken`](#BatcherConfidential-toToken--) being transferred to or from the batcher. + +
+
+
## `ERC7821WithExecutor` - + @@ -915,7 +951,7 @@ function _erc7821AuthorizedExecutor( ## `VestingWalletCliffConfidential` - + @@ -1139,7 +1175,7 @@ The specified cliff duration is larger than the vesting duration. ## `VestingWalletConfidential` - + @@ -1467,7 +1503,7 @@ Emitted when releasable vested tokens are released. ## `VestingWalletConfidentialFactory` - + diff --git a/content/confidential-contracts/api/governance.mdx b/content/confidential-contracts/api/governance.mdx index 4f0fce5a..6b6cfd19 100644 --- a/content/confidential-contracts/api/governance.mdx +++ b/content/confidential-contracts/api/governance.mdx @@ -16,7 +16,7 @@ This directory includes primitives for on-chain confidential governance. ## `VotesConfidential` - + @@ -61,7 +61,7 @@ to activate checkpoints and have their voting power tracked. HandleAccessManager - [getHandleAllowance(handle, account, persistent)](#HandleAccessManager-getHandleAllowance-bytes32-address-bool-) -- [_validateHandleAllowance(handle)](#HandleAccessManager-_validateHandleAllowance-bytes32-) +- [_validateHandleAllowance()](#HandleAccessManager-_validateHandleAllowance-bytes32-)
diff --git a/content/confidential-contracts/api/interfaces.mdx b/content/confidential-contracts/api/interfaces.mdx index 1a7711d5..4e37e175 100644 --- a/content/confidential-contracts/api/interfaces.mdx +++ b/content/confidential-contracts/api/interfaces.mdx @@ -23,7 +23,7 @@ These interfaces are available as `.sol` files and are useful to interact with t ## `IERC7984` - + @@ -424,7 +424,7 @@ should be able to disclose the amount. This functionality is implementation spec ## `IERC7984ERC20Wrapper` - + @@ -638,13 +638,123 @@ Emitted when an unwrap request is finalized for a given `receiver`, `unwrapReque + + +
+ +## `IERC7984HookModule` + + + + + +
+ +```solidity +import "@openzeppelin/confidential-contracts/interfaces/IERC7984HookModule.sol"; +``` + +Interface for an ERC-7984 hook module. + +
+

Functions

+
+- [preTransfer(from, to, encryptedAmount)](#IERC7984HookModule-preTransfer-address-address-euint64-) +- [postTransfer(from, to, encryptedAmount)](#IERC7984HookModule-postTransfer-address-address-euint64-) +- [onInstall(initData)](#IERC7984HookModule-onInstall-bytes-) +
+IERC165 + +- [supportsInterface(interfaceId)](#IERC165-supportsInterface-bytes4-) + +
+
+
+ +
+

Events

+
+- [ERC7984HookModuleResult(token, from, to, encryptedAmount, result, context)](#IERC7984HookModule-ERC7984HookModuleResult-address-address-address-euint64-ebool-bytes32-) +
+
+ + + +
+
+

preTransfer(address from, address to, euint64 encryptedAmount) → ebool

+
+

external

+# +
+
+
+ +Hook that runs before a transfer. Should not mutate token state. Module is already +granted transient access to `encryptedAmount`. + +
+
+ + + +
+
+

postTransfer(address from, address to, euint64 encryptedAmount)

+
+

external

+# +
+
+
+ +Performs operation after transfer. + +
+
+ + + +
+
+

onInstall(bytes initData)

+
+

external

+# +
+
+
+ +Performs operations after installation. + +
+
+ + + +
+
+

ERC7984HookModuleResult(address indexed token, address indexed from, address indexed to, euint64 encryptedAmount, ebool result, bytes32 context)

+
+

event

+# +
+
+ +
+ +Optionally emitted by a module to indicate the result of its validation (pre-transfer) hook. + +
+
+
## `IERC7984Receiver` - + @@ -678,6 +788,10 @@ Interface for contracts that can receive ERC7984 transfers with a callback. Called upon receiving a confidential token transfer. Returns an encrypted boolean indicating success of the callback. If false is returned, the token contract will attempt to refund the transfer. + +The calling contract (token) must be granted ACL allowance to read the confidential return value. + + Do not manually refund the transfer AND return false, as this can lead to double refunds. @@ -691,7 +805,7 @@ Do not manually refund the transfer AND return false, as this can lead to double ## `IERC7984Rwa` - + @@ -707,6 +821,8 @@ Interface for confidential RWA contracts.

Functions

- [paused()](#IERC7984Rwa-paused--) +- [isAdmin(account)](#IERC7984Rwa-isAdmin-address-) +- [isAgent(account)](#IERC7984Rwa-isAgent-address-) - [canTransact(account)](#IERC7984Rwa-canTransact-address-) - [confidentialFrozen(account)](#IERC7984Rwa-confidentialFrozen-address-) - [confidentialAvailable(account)](#IERC7984Rwa-confidentialAvailable-address-) @@ -722,6 +838,7 @@ Interface for confidential RWA contracts. - [confidentialBurn(account, encryptedAmount)](#IERC7984Rwa-confidentialBurn-address-euint64-) - [forceConfidentialTransferFrom(from, to, encryptedAmount, inputProof)](#IERC7984Rwa-forceConfidentialTransferFrom-address-address-externalEuint64-bytes-) - [forceConfidentialTransferFrom(from, to, encryptedAmount)](#IERC7984Rwa-forceConfidentialTransferFrom-address-address-euint64-) +- [recoverAddress(lostAccount, newAccount)](#IERC7984Rwa-recoverAddress-address-address-)
IERC7984 @@ -755,6 +872,7 @@ Interface for confidential RWA contracts.

Events

+- [TokensRecovered(lostAccount, newAccount, amount)](#IERC7984Rwa-TokensRecovered-address-address-euint64-)
IERC7984 @@ -783,6 +901,40 @@ Returns true if the contract is paused, false otherwise.
+ + +
+
+

isAdmin(address account) → bool

+
+

external

+# +
+
+
+ +Returns true if has admin role, false otherwise. + +
+
+ + + +
+
+

isAgent(address account) → bool

+
+

external

+# +
+
+
+ +Returns true if agent, false otherwise. + +
+
+
@@ -1038,3 +1190,38 @@ Forces transfer of confidential amount of tokens from account to account by skip
+ + +
+
+

recoverAddress(address lostAccount, address newAccount) → euint64

+
+

external

+# +
+
+
+ +Recovers the address of a lost account to a new account. + +
+
+ + + +
+
+

TokensRecovered(address indexed lostAccount, address indexed newAccount, euint64 amount)

+
+

event

+# +
+
+ +
+ +Emitted when the balance `amount` of `lostAccount` is recovered to `newAccount`. + +
+
+ diff --git a/content/confidential-contracts/api/token.mdx b/content/confidential-contracts/api/token.mdx index dd268a47..0d48366b 100644 --- a/content/confidential-contracts/api/token.mdx +++ b/content/confidential-contracts/api/token.mdx @@ -13,7 +13,11 @@ This set of interfaces, contracts, and utilities are all related to `ERC7984`, a * [`ERC7984Omnibus`](#ERC7984Omnibus): An extension of [`ERC7984`](#ERC7984) that emits additional events for omnibus transfers, which contain encrypted addresses for the sub-account sender and recipient. * [`ERC7984Rwa`](#ERC7984Rwa): Extension of [`ERC7984`](#ERC7984) that supports confidential Real World Assets (RWAs) by providing compliance checks, transfer controls and enforcement actions. * [`ERC7984Votes`](#ERC7984Votes): An extension of [`ERC7984`](#ERC7984) that supports confidential vote tracking and delegation via [`VotesConfidential`](/confidential-contracts/api/governance#VotesConfidential). +* [`ERC7984Hooked`](#ERC7984Hooked): An extension of [`ERC7984`](#ERC7984) that calls pre and post transfer hooks on installed modules. * [`ERC7984Utils`](#ERC7984Utils): A library that provides the on-transfer callback check used by [`ERC7984`](#ERC7984). +* [`ERC7984HookModule`](#ERC7984HookModule): A an abstract, base implementation for hook modules compatible with [`ERC7984Hooked`](#ERC7984Hooked). +* [`ERC7984BalanceCapHookModule`](#ERC7984BalanceCapHookModule): An example hook module for [`ERC7984Hooked`](#ERC7984Hooked) that enforces a per-account encrypted balance cap. +* [`ERC7984HolderCapHookModule`](#ERC7984HolderCapHookModule): An example hook module for [`ERC7984Hooked`](#ERC7984Hooked) that enforces a maximum number of holders. Must be installed before any tokens are minted. ## Core [`ERC7984`](#ERC7984) @@ -26,9 +30,13 @@ This set of interfaces, contracts, and utilities are all related to `ERC7984`, a [`ERC7984Omnibus`](#ERC7984Omnibus) [`ERC7984Rwa`](#ERC7984Rwa) [`ERC7984Votes`](#ERC7984Votes) +[`ERC7984Hooked`](#ERC7984Hooked) ## Utilities [`ERC7984Utils`](#ERC7984Utils) +[`ERC7984HookModule`](#ERC7984HookModule) +[`ERC7984BalanceCapHookModule`](#ERC7984BalanceCapHookModule) +[`ERC7984HolderCapHookModule`](#ERC7984HolderCapHookModule) @@ -36,7 +44,7 @@ This set of interfaces, contracts, and utilities are all related to `ERC7984`, a ## `ERC7984` - + @@ -113,10 +121,8 @@ Key features: - [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) - [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) - [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) - [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) - [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-)
@@ -288,11 +294,8 @@ Returns true if `spender` is currently an operator for `holder`.
-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. - +See [`IERC7984.setOperator`](/confidential-contracts/api/interfaces#IERC7984-setOperator-address-uint48-). Operators are given ACL allowance (ability to decrypt) for the transferred amount +of transfers they initiate.
@@ -338,7 +341,7 @@ Similar to `confidentialTransfer-address-externalEuint64-bytes` but without an i
-

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

+

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

public

# @@ -358,7 +361,7 @@ Returns the encrypted amount that was actually transferred.
-

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

+

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

public

# @@ -376,7 +379,7 @@ The caller *must* be already allowed by ACL for the given `amount`.
-

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

+

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

public

# @@ -398,7 +401,7 @@ data `data`.
-

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

+

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

public

# @@ -415,7 +418,7 @@ Similar to `confidentialTransfer-address-euint64` but with a callback to `to` af
-

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

+

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

public

# @@ -433,7 +436,7 @@ after the transfer.
-

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

+

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

public

# @@ -563,6 +566,28 @@ May not be tied to a prior request via [`ERC7984.requestDiscloseEncryptedAmount`
+Transfers the given amount of tokens from `from` to `to` and calls the `onConfidentialTransferReceived` +function on the recipient. + +The token contract initiates a second transfer refunding the tokens from the recipient to the sender--the +amount is 0 if the callback succeeds, otherwise the amount is the amount that was transferred. + +The returned `transferred` amount is a fresh ciphertext computed as `sent - refund` +and `msg.sender` only receives a transient FHE allowance for it. This value is generally +intended to be processed only in the same transaction. Event observers see `sent` and `refund` individually. + + +The refund triggered when [`IERC7984Receiver.onConfidentialTransferReceived`](/confidential-contracts/api/interfaces#IERC7984Receiver-onConfidentialTransferReceived-address-address-euint64-bytes-) returns an encrypted +false is best-effort only. A receiver that transfers, burns, or otherwise reduces its balance during +the hook can still return false, in which case the refund transfers zero tokens. The sender's tokens +end up with the recipient rather than being refunded. + + + +Refunds are subject to the same validation flow as a normal transfer--they may fail for a variety of +reasons (such as failed hook validation in [`ERC7984Hooked`](#ERC7984Hooked)). In these cases, the tokens do not return to the sender. + +
@@ -578,6 +603,9 @@ May not be tied to a prior request via [`ERC7984.requestDiscloseEncryptedAmount`
+Safely moves up to `amount` from `from` to `to`, or mints/burns if `from`/`to` is the zero address. +Emits a [`IERC7984.ConfidentialTransfer`](/confidential-contracts/api/interfaces#IERC7984-ConfidentialTransfer-address-address-euint64-) event with the successfully transferred amount. +
@@ -650,23 +678,6 @@ 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. - -
-
-
@@ -705,30 +716,13 @@ The given caller `caller` is not authorized for the current operation.
- - -
-
-

ERC7984InvalidGatewayRequest(uint256 requestId)

-
-

error

-# -
-
-
- -The given gateway request ID `requestId` is invalid. - -
-
-
## `ERC7984ERC20Wrapper` - + @@ -837,10 +831,8 @@ tokens such as fee-on-transfer or other deflationary-type tokens are not support - [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) - [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) - [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) - [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) - [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-)
@@ -1100,8 +1092,8 @@ Returns the maximum total supply of wrapped tokens supported by the encrypted da
-Get the address that has a pending unwrap request for the given `unwrapAmount`. Returns `address(0)` if no pending -unwrap request for the amount `unwrapAmount` exists. +Gets the address that will receive the ERC-20 tokens associated with a pending unwrap request identified by +`unwrapRequestId`. Returns `address(0)` if there is no pending unwrap request with id `unwrapRequestId`.
@@ -1141,6 +1133,9 @@ not overflow.
+Safely moves up to `amount` from `from` to `to`, or mints/burns if `from`/`to` is the zero address. +Emits a [`IERC7984.ConfidentialTransfer`](/confidential-contracts/api/interfaces#IERC7984-ConfidentialTransfer-address-address-euint64-) event with the successfully transferred amount. +
@@ -1233,7 +1228,7 @@ Returns the maximum number that will be used for [`ERC7984.decimals`](#ERC7984-d ## `ERC7984Freezable` - + @@ -1323,10 +1318,8 @@ Inspired by https://github.com/OpenZeppelin/openzeppelin-community-contracts/blo - [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) - [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) - [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) - [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) - [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-) @@ -1441,31 +1434,64 @@ Emitted when a confidential amount of token is frozen for an account - +
-## `ERC7984ObserverAccess` +## `ERC7984Hooked` - +
```solidity -import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984ObserverAccess.sol"; +import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Hooked.sol"; ``` -Extension of [`ERC7984`](#ERC7984) that allows each account to add an observer who is given -permanent ACL access to its transfer and balance amounts. An observer can be added or removed at any point in time. +Extension of [`ERC7984`](#ERC7984) that supports hook modules. Inspired by ERC-7579 modules. + +Modules are called before and after transfers. Before the transfer, modules +conduct checks to see if they approve the given transfer and return an encrypted boolean. If any module +returns false, the transferred amount becomes 0. After the transfer, modules are notified of the final transfer +amount and may do accounting as necessary. Modules may revert on either call, which will propagate +and revert the entire transaction. + + +Hook modules are trusted contracts--they have access to any private state the token has access to. This arbitrary +ACL access allows hook modules to grant themselves (or any other address) allowance to view any handle the token has access to. +ACL allowances granted by the hook module persist even after the module is uninstalled. + + +
+

Modifiers

+
+- [onlyAuthorizedModuleChange()](#ERC7984Hooked-onlyAuthorizedModuleChange--) +
+

Functions

-- [setObserver(account, newObserver)](#ERC7984ObserverAccess-setObserver-address-address-) -- [observer(account)](#ERC7984ObserverAccess-observer-address-) -- [_update(from, to, amount)](#ERC7984ObserverAccess-_update-address-address-euint64-) +- [isModuleInstalled(module)](#ERC7984Hooked-isModuleInstalled-address-) +- [installModule(module, initData)](#ERC7984Hooked-installModule-address-bytes-) +- [uninstallModule(module)](#ERC7984Hooked-uninstallModule-address-) +- [modules(start, end)](#ERC7984Hooked-modules-uint256-uint256-) +- [maxModules()](#ERC7984Hooked-maxModules--) +- [_authorizeModuleChange()](#ERC7984Hooked-_authorizeModuleChange--) +- [_installModule(module, initData)](#ERC7984Hooked-_installModule-address-bytes-) +- [_uninstallModule(module)](#ERC7984Hooked-_uninstallModule-address-) +- [_update(from, to, encryptedAmount)](#ERC7984Hooked-_update-address-address-euint64-) +- [_runPreTransferHooks(from, to, encryptedAmount)](#ERC7984Hooked-_runPreTransferHooks-address-address-euint64-) +- [_runPostTransferHooks(from, to, encryptedAmount)](#ERC7984Hooked-_runPostTransferHooks-address-address-euint64-) +- [_validateHandleAllowance(handle)](#ERC7984Hooked-_validateHandleAllowance-bytes32-) +
+HandleAccessManager + +- [getHandleAllowance(handle, account, persistent)](#HandleAccessManager-getHandleAllowance-bytes32-address-bool-) + +
ERC7984 @@ -1501,7 +1527,8 @@ permanent ACL access to its transfer and balance amounts. An observer can be add

Events

-- [ERC7984ObserverAccessObserverSet(account, oldObserver, newObserver)](#ERC7984ObserverAccess-ERC7984ObserverAccessObserverSet-address-address-address-) +- [ERC7984HookedModuleInstalled(module)](#ERC7984Hooked-ERC7984HookedModuleInstalled-address-) +- [ERC7984HookedModuleUninstalled(module)](#ERC7984Hooked-ERC7984HookedModuleUninstalled-address-)
ERC7984 @@ -1522,469 +1549,387 @@ permanent ACL access to its transfer and balance amounts. An observer can be add

Errors

-- [Unauthorized()](#ERC7984ObserverAccess-Unauthorized--) +- [ERC7984HookedInvalidModule(module)](#ERC7984Hooked-ERC7984HookedInvalidModule-address-) +- [ERC7984HookedDuplicateModule(module)](#ERC7984Hooked-ERC7984HookedDuplicateModule-address-) +- [ERC7984HookedNonexistentModule(module)](#ERC7984Hooked-ERC7984HookedNonexistentModule-address-) +- [ERC7984HookedExceededMaxModules()](#ERC7984Hooked-ERC7984HookedExceededMaxModules--) +
+HandleAccessManager + +- [HandleAccessManagerNotAllowed(handle, account)](#HandleAccessManager-HandleAccessManagerNotAllowed-bytes32-address-) + +
ERC7984 - [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) - [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) - [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) - [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) - [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-)
- +
-

setObserver(address account, address newObserver)

+

onlyAuthorizedModuleChange()

-

public

-# +

internal

+#
-
-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

+

isModuleInstalled(address module) → bool

public

-# +#
-Returns the observer for the given account `account`. +Checks if a module is installed.
- +
-

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

+

installModule(address module, bytes initData)

-

internal

-# +

public

+#
+Installs a hook module. + +Consider gas footprint of the module before adding it since all modules will perform +both steps (pre-hook, post-hook) on all transfers. +
- +
-

ERC7984ObserverAccessObserverSet(address account, address oldObserver, address newObserver)

+

uninstallModule(address module)

-

event

-# +

public

+#
-
-Emitted when the observer is changed for the given account `account`. +Uninstalls a hook module.
- +
-

Unauthorized()

+

modules(uint256 start, uint256 end) → address[]

-

error

-# +

public

+#
-Thrown when an account tries to set a `newObserver` for a given `account` without proper authority. - -
-
- - - -
- -## `ERC7984Omnibus` - - - - - -
- -```solidity -import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Omnibus.sol"; -``` - -Extension of [`ERC7984`](#ERC7984) that emits additional events for omnibus transfers. -These events contain encrypted addresses for the sub-account sender and recipient. +Returns a slice of the list of modules installed on the token with inclusive start and exclusive end. -There is no onchain accounting for sub-accounts--integrators must track sub-account -balances externally. +Use an end value of type(uint256).max to get the entire list of modules. -
-

Functions

-
-- [confidentialTransferOmnibus(omnibusTo, externalSender, externalRecipient, externalAmount, inputProof)](#ERC7984Omnibus-confidentialTransferOmnibus-address-externalEaddress-externalEaddress-externalEuint64-bytes-) -- [confidentialTransferOmnibus(omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-confidentialTransferOmnibus-address-eaddress-eaddress-euint64-) -- [confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, externalSender, externalRecipient, externalAmount, inputProof)](#ERC7984Omnibus-confidentialTransferFromOmnibus-address-address-externalEaddress-externalEaddress-externalEuint64-bytes-) -- [confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-confidentialTransferFromOmnibus-address-address-eaddress-eaddress-euint64-) -- [confidentialTransferAndCallOmnibus(omnibusTo, externalSender, externalRecipient, externalAmount, inputProof, data)](#ERC7984Omnibus-confidentialTransferAndCallOmnibus-address-externalEaddress-externalEaddress-externalEuint64-bytes-bytes-) -- [confidentialTransferAndCallOmnibus(omnibusTo, sender, recipient, amount, data)](#ERC7984Omnibus-confidentialTransferAndCallOmnibus-address-eaddress-eaddress-euint64-bytes-) -- [confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, externalSender, externalRecipient, externalAmount, inputProof, data)](#ERC7984Omnibus-confidentialTransferFromAndCallOmnibus-address-address-externalEaddress-externalEaddress-externalEuint64-bytes-bytes-) -- [confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data)](#ERC7984Omnibus-confidentialTransferFromAndCallOmnibus-address-address-eaddress-eaddress-euint64-bytes-) -- [_confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-_confidentialTransferFromOmnibus-address-address-eaddress-eaddress-euint64-) -- [_confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data)](#ERC7984Omnibus-_confidentialTransferFromAndCallOmnibus-address-address-eaddress-eaddress-euint64-bytes-) -
-ERC7984 - -- [supportsInterface(interfaceId)](#ERC7984-supportsInterface-bytes4-) -- [name()](#ERC7984-name--) -- [symbol()](#ERC7984-symbol--) -- [decimals()](#ERC7984-decimals--) -- [contractURI()](#ERC7984-contractURI--) -- [confidentialTotalSupply()](#ERC7984-confidentialTotalSupply--) -- [confidentialBalanceOf(account)](#ERC7984-confidentialBalanceOf-address-) -- [isOperator(holder, spender)](#ERC7984-isOperator-address-address-) -- [setOperator(operator, until)](#ERC7984-setOperator-address-uint48-) -- [confidentialTransfer(to, encryptedAmount, inputProof)](#ERC7984-confidentialTransfer-address-externalEuint64-bytes-) -- [confidentialTransfer(to, amount)](#ERC7984-confidentialTransfer-address-euint64-) -- [confidentialTransferFrom(from, to, encryptedAmount, inputProof)](#ERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes-) -- [confidentialTransferFrom(from, to, amount)](#ERC7984-confidentialTransferFrom-address-address-euint64-) -- [confidentialTransferAndCall(to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferAndCall-address-externalEuint64-bytes-bytes-) -- [confidentialTransferAndCall(to, amount, data)](#ERC7984-confidentialTransferAndCall-address-euint64-bytes-) -- [confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes-) -- [confidentialTransferFromAndCall(from, to, amount, data)](#ERC7984-confidentialTransferFromAndCall-address-address-euint64-bytes-) -- [requestDiscloseEncryptedAmount(encryptedAmount)](#ERC7984-requestDiscloseEncryptedAmount-euint64-) -- [discloseEncryptedAmount(encryptedAmount, cleartextAmount, decryptionProof)](#ERC7984-discloseEncryptedAmount-euint64-uint64-bytes-) -- [_setOperator(holder, operator, until)](#ERC7984-_setOperator-address-address-uint48-) -- [_mint(to, amount)](#ERC7984-_mint-address-euint64-) -- [_burn(from, amount)](#ERC7984-_burn-address-euint64-) -- [_transfer(from, to, amount)](#ERC7984-_transfer-address-address-euint64-) -- [_transferAndCall(from, to, amount, data)](#ERC7984-_transferAndCall-address-address-euint64-bytes-) -- [_update(from, to, amount)](#ERC7984-_update-address-address-euint64-) - -
-
-

Events

-
-- [OmnibusConfidentialTransfer(omnibusFrom, omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) -
-ERC7984 - -- [AmountDiscloseRequested(encryptedAmount, requester)](#ERC7984-AmountDiscloseRequested-euint64-address-) - -
-
-IERC7984 - -- [OperatorSet(holder, operator, until)](#IERC7984-OperatorSet-address-address-uint48-) -- [ConfidentialTransfer(from, to, amount)](#IERC7984-ConfidentialTransfer-address-address-euint64-) -- [AmountDisclosed(encryptedAmount, amount)](#IERC7984-AmountDisclosed-euint64-uint64-) + -
+
+
+

maxModules() → uint256

+
+

public

+#
+
-
-

Errors

-
-- [ERC7984UnauthorizedUseOfEncryptedAddress(addr, user)](#ERC7984Omnibus-ERC7984UnauthorizedUseOfEncryptedAddress-eaddress-address-) -
-ERC7984 - -- [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) -- [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) -- [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) -- [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) -- [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-) +Returns the maximum number of modules that can be installed. -
- +
-

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

+

_authorizeModuleChange()

-

public

-# +

internal

+#
-Wraps the `confidentialTransfer-address-externalEuint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +Authorization logic for installing and uninstalling modules. Must be implemented by the concrete contract.
- +
-

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

+

_installModule(address module, bytes initData)

-

public

-# +

internal

+#
-Wraps the `confidentialTransfer-address-euint64` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +Internal function which installs a hook module.
- +
-

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

+

_uninstallModule(address module)

-

public

-# +

internal

+#
-Wraps the `confidentialTransferFrom-address-address-externalEuint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +Internal function which uninstalls a module.
- +
-

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

+

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

-

public

-# +

internal

+#
-Wraps the `confidentialTransferFrom-address-address-euint64` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +See [`ERC7984._update`](#ERC7984-_update-address-address-euint64-). + +Modified to run pre and post transfer hooks. Zero tokens are transferred if a module does not approve +the transfer.
- +
-

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

+

_runPreTransferHooks(address from, address to, euint64 encryptedAmount) → ebool compliant

-

public

-# +

internal

+#
-Wraps the `confidentialTransferAndCall-address-externalEuint64-bytes-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +Runs the pre-transfer hooks for all modules.
- +
-

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

+

_runPostTransferHooks(address from, address to, euint64 encryptedAmount)

-

public

-# +

internal

+#
-Wraps the `confidentialTransferAndCall-address-euint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +Runs the post-transfer hooks for all modules.
- +
-

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

+

_validateHandleAllowance(bytes32 handle) → bool

-

public

-# +

internal

+#
-Wraps the `confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +See [`HandleAccessManager._validateHandleAllowance`](/confidential-contracts/api/utils#HandleAccessManager-_validateHandleAllowance-bytes32-). Allow modules to access any handle the token has access to.
- +
-

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

+

ERC7984HookedModuleInstalled(address module)

-

public

-# +

event

+#
+
-Wraps the `confidentialTransferFromAndCall-address-address-euint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. +Emitted when a module is installed.
- - +
-

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

+

ERC7984HookedModuleUninstalled(address module)

-

internal

-# +

event

+#
+
-Handles the ACL allowances, does the transfer without a callback, and emits [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-). +Emitted when a module is uninstalled.
- +
-

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

+

ERC7984HookedInvalidModule(address module)

-

internal

-# +

error

+#
-Handles the ACL allowances, does the transfer with a callback, and emits [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-). +The address is not a valid module.
- +
-

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

+

ERC7984HookedDuplicateModule(address module)

-

event

-# +

error

+#
-
-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`](/confidential-contracts/api/interfaces#IERC7984-ConfidentialTransfer-address-address-euint64-) event. - - -`omnibusFrom` and `omnibusTo` get permanent ACL allowances for `sender` and `recipient`. - +The module is already installed.
- +
-

ERC7984UnauthorizedUseOfEncryptedAddress(eaddress addr, address user)

+

ERC7984HookedNonexistentModule(address module)

error

-# +#
-The caller `user` does not have access to the encrypted address `addr`. +The module is not installed. - -Try using the equivalent transfer function with an input proof. - +
+
+ + +
+
+

ERC7984HookedExceededMaxModules()

+
+

error

+#
+
- +The maximum number of modules has been exceeded. + +
+
+ +
-## `ERC7984Restricted` +## `ERC7984ObserverAccess` - +
```solidity -import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Restricted.sol"; +import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984ObserverAccess.sol"; ``` -Extension of [`ERC7984`](#ERC7984) that implements user account transfer restrictions through the -[`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-) 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 [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-) function acts as -a blocklist. Developers can override [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-) to check that `restriction == ALLOWED` -to implement an allowlist. +Extension of [`ERC7984`](#ERC7984) that allows each account to add an observer who is given +permanent ACL access to its transfer and balance amounts. An observer can be added or removed at any point in time.

Functions

-- [getRestriction(account)](#ERC7984Restricted-getRestriction-address-) -- [canTransact(account)](#ERC7984Restricted-canTransact-address-) -- [_update(from, to, value)](#ERC7984Restricted-_update-address-address-euint64-) -- [_setRestriction(account, restriction)](#ERC7984Restricted-_setRestriction-address-enum-ERC7984Restricted-Restriction-) -- [_blockUser(account)](#ERC7984Restricted-_blockUser-address-) -- [_allowUser(account)](#ERC7984Restricted-_allowUser-address-) -- [_resetUser(account)](#ERC7984Restricted-_resetUser-address-) -- [_checkRestriction(account)](#ERC7984Restricted-_checkRestriction-address-) -- [_checkSenderRestriction(account)](#ERC7984Restricted-_checkSenderRestriction-address-) -- [_checkRecipientRestriction(account)](#ERC7984Restricted-_checkRecipientRestriction-address-) +- [setObserver(account, newObserver)](#ERC7984ObserverAccess-setObserver-address-address-) +- [observer(account)](#ERC7984ObserverAccess-observer-address-) +- [_update(from, to, amount)](#ERC7984ObserverAccess-_update-address-address-euint64-)
ERC7984 @@ -2020,7 +1965,7 @@ to implement an allowlist.

Events

-- [UserRestrictionUpdated(account, restriction)](#ERC7984Restricted-UserRestrictionUpdated-address-enum-ERC7984Restricted-Restriction-) +- [ERC7984ObserverAccessObserverSet(account, oldObserver, newObserver)](#ERC7984ObserverAccess-ERC7984ObserverAccessObserverSet-address-address-address-)
ERC7984 @@ -2041,353 +1986,1650 @@ to implement an allowlist.

Errors

-- [UserRestricted(account)](#ERC7984Restricted-UserRestricted-address-) +- [Unauthorized()](#ERC7984ObserverAccess-Unauthorized--)
ERC7984 - [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) - [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) - [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) - [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) - [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-)
- +
-

getRestriction(address account) → enum ERC7984Restricted.Restriction

+

setObserver(address account, address newObserver)

public

-# +#
-Returns the restriction of a user account. +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)`).
- +
-

canTransact(address account) → bool

+

observer(address account) → address

public

-# +#
-Returns whether a user account is allowed to interact with the token. - -Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist). +Returns the observer for the given account `account`.
- +
-

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

+

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

internal

-# +#
-See [`ERC7984._update`](#ERC7984-_update-address-address-euint64-). Enforces transfer restrictions (excluding minting and burning). - -Requirements: - -* `from` must be allowed to transfer tokens (see [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-)). -* `to` must be allowed to receive tokens (see [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-)). - -The default restriction behavior can be changed (for a pass-through for instance) by overriding -[`ERC7984Restricted._checkSenderRestriction`](#ERC7984Restricted-_checkSenderRestriction-address-) and/or [`ERC7984Restricted._checkRecipientRestriction`](#ERC7984Restricted-_checkRecipientRestriction-address-). +Safely moves up to `amount` from `from` to `to`, or mints/burns if `from`/`to` is the zero address. +Emits a [`IERC7984.ConfidentialTransfer`](/confidential-contracts/api/interfaces#IERC7984-ConfidentialTransfer-address-address-euint64-) event with the successfully transferred amount.
- +
-

_setRestriction(address account, enum ERC7984Restricted.Restriction restriction)

+

ERC7984ObserverAccessObserverSet(address account, address oldObserver, address newObserver)

-

internal

-# +

event

+#
+
-Updates the restriction of a user account. +Emitted when the observer is changed for the given account `account`.
- +
-

_blockUser(address account)

+

Unauthorized()

-

internal

-# +

error

+#
-Convenience function to block a user account (set to BLOCKED). +Thrown when an account tries to set a `newObserver` for a given `account` without proper authority.
- + + +
+ +## `ERC7984Omnibus` + + + + -
-
-

_allowUser(address account)

-
-

internal

-# -
-
-Convenience function to allow a user account (set to ALLOWED). +```solidity +import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Omnibus.sol"; +``` + +Extension of [`ERC7984`](#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)](#ERC7984Omnibus-confidentialTransferOmnibus-address-externalEaddress-externalEaddress-externalEuint64-bytes-) +- [confidentialTransferOmnibus(omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-confidentialTransferOmnibus-address-eaddress-eaddress-euint64-) +- [confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, externalSender, externalRecipient, externalAmount, inputProof)](#ERC7984Omnibus-confidentialTransferFromOmnibus-address-address-externalEaddress-externalEaddress-externalEuint64-bytes-) +- [confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-confidentialTransferFromOmnibus-address-address-eaddress-eaddress-euint64-) +- [confidentialTransferAndCallOmnibus(omnibusTo, externalSender, externalRecipient, externalAmount, inputProof, data)](#ERC7984Omnibus-confidentialTransferAndCallOmnibus-address-externalEaddress-externalEaddress-externalEuint64-bytes-bytes-) +- [confidentialTransferAndCallOmnibus(omnibusTo, sender, recipient, amount, data)](#ERC7984Omnibus-confidentialTransferAndCallOmnibus-address-eaddress-eaddress-euint64-bytes-) +- [confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, externalSender, externalRecipient, externalAmount, inputProof, data)](#ERC7984Omnibus-confidentialTransferFromAndCallOmnibus-address-address-externalEaddress-externalEaddress-externalEuint64-bytes-bytes-) +- [confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data)](#ERC7984Omnibus-confidentialTransferFromAndCallOmnibus-address-address-eaddress-eaddress-euint64-bytes-) +- [_confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-_confidentialTransferFromOmnibus-address-address-eaddress-eaddress-euint64-) +- [_confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data)](#ERC7984Omnibus-_confidentialTransferFromAndCallOmnibus-address-address-eaddress-eaddress-euint64-bytes-) +
+ERC7984 + +- [supportsInterface(interfaceId)](#ERC7984-supportsInterface-bytes4-) +- [name()](#ERC7984-name--) +- [symbol()](#ERC7984-symbol--) +- [decimals()](#ERC7984-decimals--) +- [contractURI()](#ERC7984-contractURI--) +- [confidentialTotalSupply()](#ERC7984-confidentialTotalSupply--) +- [confidentialBalanceOf(account)](#ERC7984-confidentialBalanceOf-address-) +- [isOperator(holder, spender)](#ERC7984-isOperator-address-address-) +- [setOperator(operator, until)](#ERC7984-setOperator-address-uint48-) +- [confidentialTransfer(to, encryptedAmount, inputProof)](#ERC7984-confidentialTransfer-address-externalEuint64-bytes-) +- [confidentialTransfer(to, amount)](#ERC7984-confidentialTransfer-address-euint64-) +- [confidentialTransferFrom(from, to, encryptedAmount, inputProof)](#ERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes-) +- [confidentialTransferFrom(from, to, amount)](#ERC7984-confidentialTransferFrom-address-address-euint64-) +- [confidentialTransferAndCall(to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferAndCall-address-externalEuint64-bytes-bytes-) +- [confidentialTransferAndCall(to, amount, data)](#ERC7984-confidentialTransferAndCall-address-euint64-bytes-) +- [confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes-) +- [confidentialTransferFromAndCall(from, to, amount, data)](#ERC7984-confidentialTransferFromAndCall-address-address-euint64-bytes-) +- [requestDiscloseEncryptedAmount(encryptedAmount)](#ERC7984-requestDiscloseEncryptedAmount-euint64-) +- [discloseEncryptedAmount(encryptedAmount, cleartextAmount, decryptionProof)](#ERC7984-discloseEncryptedAmount-euint64-uint64-bytes-) +- [_setOperator(holder, operator, until)](#ERC7984-_setOperator-address-address-uint48-) +- [_mint(to, amount)](#ERC7984-_mint-address-euint64-) +- [_burn(from, amount)](#ERC7984-_burn-address-euint64-) +- [_transfer(from, to, amount)](#ERC7984-_transfer-address-address-euint64-) +- [_transferAndCall(from, to, amount, data)](#ERC7984-_transferAndCall-address-address-euint64-bytes-) +- [_update(from, to, amount)](#ERC7984-_update-address-address-euint64-) +
- +
+

Events

+
+- [OmnibusConfidentialTransfer(omnibusFrom, omnibusTo, sender, recipient, amount)](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) +
+ERC7984 -
-
-

_resetUser(address account)

-
-

internal

-# +- [AmountDiscloseRequested(encryptedAmount, requester)](#ERC7984-AmountDiscloseRequested-euint64-address-) + +
+
+IERC7984 + +- [OperatorSet(holder, operator, until)](#IERC7984-OperatorSet-address-address-uint48-) +- [ConfidentialTransfer(from, to, amount)](#IERC7984-ConfidentialTransfer-address-address-euint64-) +- [AmountDisclosed(encryptedAmount, amount)](#IERC7984-AmountDisclosed-euint64-uint64-) + +
-
-Convenience function to reset a user account to default restriction. +
+

Errors

+
+- [ERC7984UnauthorizedUseOfEncryptedAddress(addr, user)](#ERC7984Omnibus-ERC7984UnauthorizedUseOfEncryptedAddress-eaddress-address-) +
+ERC7984 + +- [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) +- [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) +- [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) +- [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) +- [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) +
- +
-

_checkRestriction(address account)

+

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

-

internal

-# +

public

+#
-Checks if a user account is restricted. Reverts with [`ERC7984Restricted.UserRestricted`](#ERC7984Restricted-UserRestricted-address-) if so. +Wraps the `confidentialTransfer-address-externalEuint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
- + + +
+
+

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

+
+

public

+# +
+
+
+ +Wraps the `confidentialTransfer-address-euint64` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Wraps the `confidentialTransferFrom-address-address-externalEuint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Wraps the `confidentialTransferFrom-address-address-euint64` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Wraps the `confidentialTransferAndCall-address-externalEuint64-bytes-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Wraps the `confidentialTransferAndCall-address-euint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Wraps the `confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Wraps the `confidentialTransferFromAndCall-address-address-euint64-bytes` function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) 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 [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-). + +
+
+ + + +
+
+

_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 [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-). + +
+
+ + + +
+
+

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`](/confidential-contracts/api/interfaces#IERC7984-ConfidentialTransfer-address-address-euint64-) 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. + + +
+
+ + + +
+ +## `ERC7984Restricted` + + + + + +
+ +```solidity +import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Restricted.sol"; +``` + +Extension of [`ERC7984`](#ERC7984) that implements user account transfer restrictions through the +[`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-) 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 [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-) function acts as +a blocklist. Developers can override [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-) to check that `restriction == ALLOWED` +to implement an allowlist. + +
+

Functions

+
+- [getRestriction(account)](#ERC7984Restricted-getRestriction-address-) +- [canTransact(account)](#ERC7984Restricted-canTransact-address-) +- [_update(from, to, value)](#ERC7984Restricted-_update-address-address-euint64-) +- [_setRestriction(account, restriction)](#ERC7984Restricted-_setRestriction-address-enum-ERC7984Restricted-Restriction-) +- [_blockUser(account)](#ERC7984Restricted-_blockUser-address-) +- [_allowUser(account)](#ERC7984Restricted-_allowUser-address-) +- [_resetUser(account)](#ERC7984Restricted-_resetUser-address-) +- [_checkRestriction(account)](#ERC7984Restricted-_checkRestriction-address-) +- [_checkSenderRestriction(account)](#ERC7984Restricted-_checkSenderRestriction-address-) +- [_checkRecipientRestriction(account)](#ERC7984Restricted-_checkRecipientRestriction-address-) +
+ERC7984 + +- [supportsInterface(interfaceId)](#ERC7984-supportsInterface-bytes4-) +- [name()](#ERC7984-name--) +- [symbol()](#ERC7984-symbol--) +- [decimals()](#ERC7984-decimals--) +- [contractURI()](#ERC7984-contractURI--) +- [confidentialTotalSupply()](#ERC7984-confidentialTotalSupply--) +- [confidentialBalanceOf(account)](#ERC7984-confidentialBalanceOf-address-) +- [isOperator(holder, spender)](#ERC7984-isOperator-address-address-) +- [setOperator(operator, until)](#ERC7984-setOperator-address-uint48-) +- [confidentialTransfer(to, encryptedAmount, inputProof)](#ERC7984-confidentialTransfer-address-externalEuint64-bytes-) +- [confidentialTransfer(to, amount)](#ERC7984-confidentialTransfer-address-euint64-) +- [confidentialTransferFrom(from, to, encryptedAmount, inputProof)](#ERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes-) +- [confidentialTransferFrom(from, to, amount)](#ERC7984-confidentialTransferFrom-address-address-euint64-) +- [confidentialTransferAndCall(to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferAndCall-address-externalEuint64-bytes-bytes-) +- [confidentialTransferAndCall(to, amount, data)](#ERC7984-confidentialTransferAndCall-address-euint64-bytes-) +- [confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes-) +- [confidentialTransferFromAndCall(from, to, amount, data)](#ERC7984-confidentialTransferFromAndCall-address-address-euint64-bytes-) +- [requestDiscloseEncryptedAmount(encryptedAmount)](#ERC7984-requestDiscloseEncryptedAmount-euint64-) +- [discloseEncryptedAmount(encryptedAmount, cleartextAmount, decryptionProof)](#ERC7984-discloseEncryptedAmount-euint64-uint64-bytes-) +- [_setOperator(holder, operator, until)](#ERC7984-_setOperator-address-address-uint48-) +- [_mint(to, amount)](#ERC7984-_mint-address-euint64-) +- [_burn(from, amount)](#ERC7984-_burn-address-euint64-) +- [_transfer(from, to, amount)](#ERC7984-_transfer-address-address-euint64-) +- [_transferAndCall(from, to, amount, data)](#ERC7984-_transferAndCall-address-address-euint64-bytes-) + +
+
+
+ +
+

Events

+
+- [UserRestrictionUpdated(account, restriction)](#ERC7984Restricted-UserRestrictionUpdated-address-enum-ERC7984Restricted-Restriction-) +
+ERC7984 + +- [AmountDiscloseRequested(encryptedAmount, requester)](#ERC7984-AmountDiscloseRequested-euint64-address-) + +
+
+IERC7984 + +- [OperatorSet(holder, operator, until)](#IERC7984-OperatorSet-address-address-uint48-) +- [ConfidentialTransfer(from, to, amount)](#IERC7984-ConfidentialTransfer-address-address-euint64-) +- [AmountDisclosed(encryptedAmount, amount)](#IERC7984-AmountDisclosed-euint64-uint64-) + +
+
+
+ +
+

Errors

+
+- [UserRestricted(account)](#ERC7984Restricted-UserRestricted-address-) +
+ERC7984 + +- [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) +- [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) +- [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) +- [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) +- [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) + +
+
+
+ + + +
+
+

getRestriction(address account) → enum ERC7984Restricted.Restriction

+
+

public

+# +
+
+
+ +Returns the restriction of a user account. + +
+
+ + + +
+
+

canTransact(address account) → bool

+
+

public

+# +
+
+
+ +Returns whether a user account is allowed to receive or send tokens. + +Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist). + +
+
+ + + +
+
+

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

+
+

internal

+# +
+
+
+ +See [`ERC7984._update`](#ERC7984-_update-address-address-euint64-). Enforces transfer restrictions. + +Requirements: + +* `from` must be allowed to transfer tokens (see [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-)). +* `to` must be allowed to receive tokens (see [`ERC7984Restricted.canTransact`](#ERC7984Restricted-canTransact-address-)). + +The default restriction behavior can be changed (for a pass-through for instance) by overriding +[`ERC7984Restricted._checkSenderRestriction`](#ERC7984Restricted-_checkSenderRestriction-address-) and/or [`ERC7984Restricted._checkRecipientRestriction`](#ERC7984Restricted-_checkRecipientRestriction-address-). + +
+
+ + + +
+
+

_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 [`ERC7984Restricted.UserRestricted`](#ERC7984Restricted-UserRestricted-address-) if so. + +
+
+ + + +
+
+

_checkSenderRestriction(address account)

+
+

internal

+# +
+
+
+ +Internal function which checks restriction of the `from` account before a transfer. +Working with [`ERC7984._update`](#ERC7984-_update-address-address-euint64-) function. + +
+
+ + + +
+
+

_checkRecipientRestriction(address account)

+
+

internal

+# +
+
+
+ +Internal function which checks restriction of the `to` account before a transfer. +Working with [`ERC7984._update`](#ERC7984-_update-address-address-euint64-) 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. + +
+
+ + + +
+ +## `ERC7984Rwa` + + + + + +
+ +```solidity +import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Rwa.sol"; +``` + +Extension of [`ERC7984`](#ERC7984) that supports confidential Real World Assets (RWAs). +This interface provides compliance checks, transfer controls and enforcement actions. + +
+

Modifiers

+
+- [onlyAdmin()](#ERC7984Rwa-onlyAdmin--) +- [onlyAgent()](#ERC7984Rwa-onlyAgent--) +
+
+ +
+

Functions

+
+- [constructor(admin)](#ERC7984Rwa-constructor-address-) +- [supportsInterface(interfaceId)](#ERC7984Rwa-supportsInterface-bytes4-) +- [isAdmin(account)](#ERC7984Rwa-isAdmin-address-) +- [isAgent(account)](#ERC7984Rwa-isAgent-address-) +- [addAgent(account)](#ERC7984Rwa-addAgent-address-) +- [removeAgent(account)](#ERC7984Rwa-removeAgent-address-) +- [pause()](#ERC7984Rwa-pause--) +- [unpause()](#ERC7984Rwa-unpause--) +- [blockUser(account)](#ERC7984Rwa-blockUser-address-) +- [unblockUser(account)](#ERC7984Rwa-unblockUser-address-) +- [setConfidentialFrozen(account, encryptedAmount, inputProof)](#ERC7984Rwa-setConfidentialFrozen-address-externalEuint64-bytes-) +- [setConfidentialFrozen(account, encryptedAmount)](#ERC7984Rwa-setConfidentialFrozen-address-euint64-) +- [confidentialMint(to, encryptedAmount, inputProof)](#ERC7984Rwa-confidentialMint-address-externalEuint64-bytes-) +- [confidentialMint(to, encryptedAmount)](#ERC7984Rwa-confidentialMint-address-euint64-) +- [confidentialBurn(account, encryptedAmount, inputProof)](#ERC7984Rwa-confidentialBurn-address-externalEuint64-bytes-) +- [confidentialBurn(account, encryptedAmount)](#ERC7984Rwa-confidentialBurn-address-euint64-) +- [recoverAddress(lostAccount, newAccount)](#ERC7984Rwa-recoverAddress-address-address-) +- [forceConfidentialTransferFrom(from, to, encryptedAmount, inputProof)](#ERC7984Rwa-forceConfidentialTransferFrom-address-address-externalEuint64-bytes-) +- [forceConfidentialTransferFrom(from, to, encryptedAmount)](#ERC7984Rwa-forceConfidentialTransferFrom-address-address-euint64-) +- [confidentialAvailable(account)](#ERC7984Rwa-confidentialAvailable-address-) +- [confidentialFrozen(account)](#ERC7984Rwa-confidentialFrozen-address-) +- [paused()](#ERC7984Rwa-paused--) +- [canTransact(account)](#ERC7984Rwa-canTransact-address-) +- [_update(from, to, encryptedAmount)](#ERC7984Rwa-_update-address-address-euint64-) +- [_checkSenderRestriction(account)](#ERC7984Rwa-_checkSenderRestriction-address-) +- [_checkRecipientRestriction(account)](#ERC7984Rwa-_checkRecipientRestriction-address-) +- [_requireNotPaused()](#ERC7984Rwa-_requireNotPaused--) +- [_isForceTransfer(selector)](#ERC7984Rwa-_isForceTransfer-bytes4-) +- [_msgSender()](#ERC7984Rwa-_msgSender--) +- [_msgData()](#ERC7984Rwa-_msgData--) +- [AGENT_ROLE()](#ERC7984Rwa-AGENT_ROLE-bytes32) +
+AccessControl + +- [hasRole(role, account)](#AccessControl-hasRole-bytes32-address-) +- [_checkRole(role)](#AccessControl-_checkRole-bytes32-) +- [_checkRole(role, account)](#AccessControl-_checkRole-bytes32-address-) +- [getRoleAdmin(role)](#AccessControl-getRoleAdmin-bytes32-) +- [grantRole(role, account)](#AccessControl-grantRole-bytes32-address-) +- [revokeRole(role, account)](#AccessControl-revokeRole-bytes32-address-) +- [renounceRole(role, callerConfirmation)](#AccessControl-renounceRole-bytes32-address-) +- [_setRoleAdmin(role, adminRole)](#AccessControl-_setRoleAdmin-bytes32-bytes32-) +- [_grantRole(role, account)](#AccessControl-_grantRole-bytes32-address-) +- [_revokeRole(role, account)](#AccessControl-_revokeRole-bytes32-address-) +- [DEFAULT_ADMIN_ROLE()](#AccessControl-DEFAULT_ADMIN_ROLE-bytes32) + +
+
+Multicall + +- [multicall(data)](#Multicall-multicall-bytes---) + +
+
+Pausable + +- [_requirePaused()](#Pausable-_requirePaused--) +- [_pause()](#Pausable-_pause--) +- [_unpause()](#Pausable-_unpause--) + +
+
+ERC7984Restricted + +- [getRestriction(account)](#ERC7984Restricted-getRestriction-address-) +- [_setRestriction(account, restriction)](#ERC7984Restricted-_setRestriction-address-enum-ERC7984Restricted-Restriction-) +- [_blockUser(account)](#ERC7984Restricted-_blockUser-address-) +- [_allowUser(account)](#ERC7984Restricted-_allowUser-address-) +- [_resetUser(account)](#ERC7984Restricted-_resetUser-address-) +- [_checkRestriction(account)](#ERC7984Restricted-_checkRestriction-address-) + +
+
+ERC7984Freezable + +- [_confidentialAvailable(account)](#ERC7984Freezable-_confidentialAvailable-address-) +- [_setConfidentialFrozen(account, encryptedAmount)](#ERC7984Freezable-_setConfidentialFrozen-address-euint64-) + +
+
+ERC7984 + +- [name()](#ERC7984-name--) +- [symbol()](#ERC7984-symbol--) +- [decimals()](#ERC7984-decimals--) +- [contractURI()](#ERC7984-contractURI--) +- [confidentialTotalSupply()](#ERC7984-confidentialTotalSupply--) +- [confidentialBalanceOf(account)](#ERC7984-confidentialBalanceOf-address-) +- [isOperator(holder, spender)](#ERC7984-isOperator-address-address-) +- [setOperator(operator, until)](#ERC7984-setOperator-address-uint48-) +- [confidentialTransfer(to, encryptedAmount, inputProof)](#ERC7984-confidentialTransfer-address-externalEuint64-bytes-) +- [confidentialTransfer(to, amount)](#ERC7984-confidentialTransfer-address-euint64-) +- [confidentialTransferFrom(from, to, encryptedAmount, inputProof)](#ERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes-) +- [confidentialTransferFrom(from, to, amount)](#ERC7984-confidentialTransferFrom-address-address-euint64-) +- [confidentialTransferAndCall(to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferAndCall-address-externalEuint64-bytes-bytes-) +- [confidentialTransferAndCall(to, amount, data)](#ERC7984-confidentialTransferAndCall-address-euint64-bytes-) +- [confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes-) +- [confidentialTransferFromAndCall(from, to, amount, data)](#ERC7984-confidentialTransferFromAndCall-address-address-euint64-bytes-) +- [requestDiscloseEncryptedAmount(encryptedAmount)](#ERC7984-requestDiscloseEncryptedAmount-euint64-) +- [discloseEncryptedAmount(encryptedAmount, cleartextAmount, decryptionProof)](#ERC7984-discloseEncryptedAmount-euint64-uint64-bytes-) +- [_setOperator(holder, operator, until)](#ERC7984-_setOperator-address-address-uint48-) +- [_mint(to, amount)](#ERC7984-_mint-address-euint64-) +- [_burn(from, amount)](#ERC7984-_burn-address-euint64-) +- [_transfer(from, to, amount)](#ERC7984-_transfer-address-address-euint64-) +- [_transferAndCall(from, to, amount, data)](#ERC7984-_transferAndCall-address-address-euint64-bytes-) + +
+
+
+ +
+

Events

+
+
+Pausable + +- [Paused(account)](#Pausable-Paused-address-) +- [Unpaused(account)](#Pausable-Unpaused-address-) + +
+
+ERC7984Restricted + +- [UserRestrictionUpdated(account, restriction)](#ERC7984Restricted-UserRestrictionUpdated-address-enum-ERC7984Restricted-Restriction-) + +
+
+ERC7984Freezable + +- [TokensFrozen(account, encryptedAmount)](#ERC7984Freezable-TokensFrozen-address-euint64-) + +
+
+ERC7984 + +- [AmountDiscloseRequested(encryptedAmount, requester)](#ERC7984-AmountDiscloseRequested-euint64-address-) + +
+
+IERC7984Rwa + +- [TokensRecovered(lostAccount, newAccount, amount)](#IERC7984Rwa-TokensRecovered-address-address-euint64-) + +
+
+IERC7984 + +- [OperatorSet(holder, operator, until)](#IERC7984-OperatorSet-address-address-uint48-) +- [ConfidentialTransfer(from, to, amount)](#IERC7984-ConfidentialTransfer-address-address-euint64-) +- [AmountDisclosed(encryptedAmount, amount)](#IERC7984-AmountDisclosed-euint64-uint64-) + +
+
+IAccessControl + +- [RoleAdminChanged(role, previousAdminRole, newAdminRole)](#IAccessControl-RoleAdminChanged-bytes32-bytes32-bytes32-) +- [RoleGranted(role, account, sender)](#IAccessControl-RoleGranted-bytes32-address-address-) +- [RoleRevoked(role, account, sender)](#IAccessControl-RoleRevoked-bytes32-address-address-) + +
+
+
+ +
+

Errors

+
+- [ERC7984RwaSelfRecoveryNotAllowed()](#ERC7984Rwa-ERC7984RwaSelfRecoveryNotAllowed--) +
+Pausable + +- [EnforcedPause()](#Pausable-EnforcedPause--) +- [ExpectedPause()](#Pausable-ExpectedPause--) + +
+
+ERC7984Restricted + +- [UserRestricted(account)](#ERC7984Restricted-UserRestricted-address-) + +
+
+ERC7984 + +- [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) +- [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) +- [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) +- [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) +- [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) + +
+
+IAccessControl + +- [AccessControlUnauthorizedAccount(account, neededRole)](#IAccessControl-AccessControlUnauthorizedAccount-address-bytes32-) +- [AccessControlBadConfirmation()](#IAccessControl-AccessControlBadConfirmation--) + +
+
+
+ + + +
+
+

onlyAdmin()

+
+

internal

+# +
+
+ +
+ +Checks if the sender is an admin. + +
+
+ + + +
+
+

onlyAgent()

+
+

internal

+# +
+
+ +
+ +Checks if the sender is an agent. + +
+
+ + + +
+
+

constructor(address admin)

+
+

internal

+# +
+
+
+ +
+
+ + + +
+
+

supportsInterface(bytes4 interfaceId) → bool

+
+

public

+# +
+
+
+ +
+
+ + + +
+
+

isAdmin(address account) → bool

+
+

public

+# +
+
+
+ +Returns true if has admin role, false otherwise. + +
+
+ + + +
+
+

isAgent(address account) → bool

+
+

public

+# +
+
+
+ +Returns true if 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 with proof. + +
+
+ + + +
+
+

setConfidentialFrozen(address account, euint64 encryptedAmount)

+
+

public

+# +
+
+
+ +Sets confidential frozen for an account. + +
+
+ + + +
+
+

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. + +
+
+ + + +
+
+

recoverAddress(address lostAccount, address newAccount) → euint64

+
+

public

+# +
+
+
+ +Recovers the address of a lost account to a new account. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Variant of `forceConfidentialTransferFrom-address-address-euint64` with an input proof. + +
+
+ + + +
+
+

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

+
+

public

+# +
+
+
+ +Force transfer callable by the role [`ERC7984Rwa.AGENT_ROLE`](#ERC7984Rwa-AGENT_ROLE-bytes32) which transfers tokens from `from` to `to` and +bypasses the [`ERC7984Restricted`](#ERC7984Restricted) (only on from) and [`++Pausable++`](https://docs.openzeppelin.com/contracts/api/utils#pausable) +checks. Frozen tokens are not transferred and must be unfrozen first. + +
+
+ + + +
+
+

confidentialAvailable(address account) → euint64

+
+

public

+# +
+
+
+ +Returns the confidential available (unfrozen) balance of an account. Gives ACL allowance to `account`. + +
+
+ + + +
+
+

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. + +
+
+ + + +
+
+

canTransact(address account) → bool

+
+

public

+# +
+
+
+ +Returns whether a user account is allowed to receive or send tokens. + +Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist). + +
+
+ + + +
+
+

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

+
+

internal

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

_checkSenderRestriction(address account)

internal

-# +# +
+
+
+ +Bypasses [`ERC7984Restricted`](#ERC7984Restricted) `from` restriction check when performing a forced transfer or token recovery. + +
+
+ + + +
+
+

_checkRecipientRestriction(address account)

+
+

internal

+# +
+
+
+ +Bypasses [`ERC7984Restricted`](#ERC7984Restricted) `to` restriction check when performing a forced transfer or token recovery. + +
+
+ + + +
+
+

_requireNotPaused()

+
+

internal

+# +
+
+
+ +Bypasses `Pausable` check when performing a [`ERC7984Rwa.forceConfidentialTransferFrom`](#ERC7984Rwa-forceConfidentialTransferFrom-address-address-euint64-). + +
+
+ + + +
+
+

_isForceTransfer(bytes4 selector) → bool

+
+

internal

+#
-Internal function which checks restriction of the `from` account before a transfer. -Working with [`ERC7984._update`](#ERC7984-_update-address-address-euint64-) function. +Internal function which checks if the current function call should be treated as a force transfer.
- +
-

_checkRecipientRestriction(address account)

+

_msgSender() → address

internal

-# +#
-Internal function which checks restriction of the `to` account before a transfer. -Working with [`ERC7984._update`](#ERC7984-_update-address-address-euint64-) function. +Restrict overrides of `Context._msgSender`. Please use other account abstraction methods instead.
- +
-

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

+

_msgData() → bytes

-

event

-# +

internal

+# +
+
+
+ +Restrict overrides of `Context._msgData`. Please use other account abstraction methods instead. +
+ + +
+
+

AGENT_ROLE() → bytes32

+
+

public

+# +
+
-Emitted when a user account's restriction is updated. +Accounts granted the agent role have the following permissioned abilities: + +* Mint/Burn to/from a given address (does not require permission) +* Force transfer from a given address (does not require permission) +** Bypasses pause and restriction checks (not frozen) +* Pause/Unpause the contract +* Block/Unblock a given account +* Set frozen amount of tokens for a given account.
- +
-

UserRestricted(address account)

+

ERC7984RwaSelfRecoveryNotAllowed()

error

-# +#
-The operation failed because the user account is restricted. +The operation failed because the lost account is the same as the new account.
- +
-## `ERC7984Rwa` +## `ERC7984Votes` - +
```solidity -import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Rwa.sol"; +import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Votes.sol"; ``` -Extension of [`ERC7984`](#ERC7984) that supports confidential Real World Assets (RWAs). -This interface provides compliance checks, transfer controls and enforcement actions. +Extension of [`ERC7984`](#ERC7984) supporting confidential votes tracking and delegation. -
-

Modifiers

-
-- [onlyAdmin()](#ERC7984Rwa-onlyAdmin--) -- [onlyAgent()](#ERC7984Rwa-onlyAgent--) -
-
+The amount of confidential voting units an account has is equal to the balance of +that account. Voting power is taken into account when an account delegates votes to itself or to another +account.

Functions

-- [constructor(admin)](#ERC7984Rwa-constructor-address-) -- [supportsInterface(interfaceId)](#ERC7984Rwa-supportsInterface-bytes4-) -- [isAdmin(account)](#ERC7984Rwa-isAdmin-address-) -- [isAgent(account)](#ERC7984Rwa-isAgent-address-) -- [addAgent(account)](#ERC7984Rwa-addAgent-address-) -- [removeAgent(account)](#ERC7984Rwa-removeAgent-address-) -- [pause()](#ERC7984Rwa-pause--) -- [unpause()](#ERC7984Rwa-unpause--) -- [blockUser(account)](#ERC7984Rwa-blockUser-address-) -- [unblockUser(account)](#ERC7984Rwa-unblockUser-address-) -- [setConfidentialFrozen(account, encryptedAmount, inputProof)](#ERC7984Rwa-setConfidentialFrozen-address-externalEuint64-bytes-) -- [setConfidentialFrozen(account, encryptedAmount)](#ERC7984Rwa-setConfidentialFrozen-address-euint64-) -- [confidentialMint(to, encryptedAmount, inputProof)](#ERC7984Rwa-confidentialMint-address-externalEuint64-bytes-) -- [confidentialMint(to, encryptedAmount)](#ERC7984Rwa-confidentialMint-address-euint64-) -- [confidentialBurn(account, encryptedAmount, inputProof)](#ERC7984Rwa-confidentialBurn-address-externalEuint64-bytes-) -- [confidentialBurn(account, encryptedAmount)](#ERC7984Rwa-confidentialBurn-address-euint64-) -- [forceConfidentialTransferFrom(from, to, encryptedAmount, inputProof)](#ERC7984Rwa-forceConfidentialTransferFrom-address-address-externalEuint64-bytes-) -- [forceConfidentialTransferFrom(from, to, encryptedAmount)](#ERC7984Rwa-forceConfidentialTransferFrom-address-address-euint64-) -- [confidentialAvailable(account)](#ERC7984Rwa-confidentialAvailable-address-) -- [confidentialFrozen(account)](#ERC7984Rwa-confidentialFrozen-address-) -- [paused()](#ERC7984Rwa-paused--) -- [canTransact(account)](#ERC7984Rwa-canTransact-address-) -- [_update(from, to, encryptedAmount)](#ERC7984Rwa-_update-address-address-euint64-) -- [_forceUpdate(from, to, encryptedAmount)](#ERC7984Rwa-_forceUpdate-address-address-euint64-) -- [_checkSenderRestriction(account)](#ERC7984Rwa-_checkSenderRestriction-address-) -- [AGENT_ROLE()](#ERC7984Rwa-AGENT_ROLE-bytes32) -
-AccessControl - -- [hasRole(role, account)](#AccessControl-hasRole-bytes32-address-) -- [_checkRole(role)](#AccessControl-_checkRole-bytes32-) -- [_checkRole(role, account)](#AccessControl-_checkRole-bytes32-address-) -- [getRoleAdmin(role)](#AccessControl-getRoleAdmin-bytes32-) -- [grantRole(role, account)](#AccessControl-grantRole-bytes32-address-) -- [revokeRole(role, account)](#AccessControl-revokeRole-bytes32-address-) -- [renounceRole(role, callerConfirmation)](#AccessControl-renounceRole-bytes32-address-) -- [_setRoleAdmin(role, adminRole)](#AccessControl-_setRoleAdmin-bytes32-bytes32-) -- [_grantRole(role, account)](#AccessControl-_grantRole-bytes32-address-) -- [_revokeRole(role, account)](#AccessControl-_revokeRole-bytes32-address-) -- [DEFAULT_ADMIN_ROLE()](#AccessControl-DEFAULT_ADMIN_ROLE-bytes32) - -
+- [confidentialTotalSupply()](#ERC7984Votes-confidentialTotalSupply--) +- [_update(from, to, amount)](#ERC7984Votes-_update-address-address-euint64-) +- [_getVotingUnits(account)](#ERC7984Votes-_getVotingUnits-address-)
-Multicall +VotesConfidential -- [multicall(data)](#Multicall-multicall-bytes---) +- [clock()](#VotesConfidential-clock--) +- [CLOCK_MODE()](#VotesConfidential-CLOCK_MODE--) +- [getVotes(account)](#VotesConfidential-getVotes-address-) +- [getPastVotes(account, timepoint)](#VotesConfidential-getPastVotes-address-uint256-) +- [getPastTotalSupply(timepoint)](#VotesConfidential-getPastTotalSupply-uint256-) +- [delegates(account)](#VotesConfidential-delegates-address-) +- [delegate(delegatee)](#VotesConfidential-delegate-address-) +- [delegateBySig(delegatee, nonce, expiry, v, r, s)](#VotesConfidential-delegateBySig-address-uint256-uint256-uint8-bytes32-bytes32-) +- [_delegate(account, delegatee)](#VotesConfidential-_delegate-address-address-) +- [_transferVotingUnits(from, to, amount)](#VotesConfidential-_transferVotingUnits-address-address-euint64-) +- [_moveDelegateVotes(from, to, amount)](#VotesConfidential-_moveDelegateVotes-address-address-euint64-) +- [_validateTimepoint(timepoint)](#VotesConfidential-_validateTimepoint-uint256-)
-Pausable +HandleAccessManager -- [_requireNotPaused()](#Pausable-_requireNotPaused--) -- [_requirePaused()](#Pausable-_requirePaused--) -- [_pause()](#Pausable-_pause--) -- [_unpause()](#Pausable-_unpause--) +- [getHandleAllowance(handle, account, persistent)](#HandleAccessManager-getHandleAllowance-bytes32-address-bool-) +- [_validateHandleAllowance()](#HandleAccessManager-_validateHandleAllowance-bytes32-)
-ERC7984Restricted +EIP712 -- [getRestriction(account)](#ERC7984Restricted-getRestriction-address-) -- [_setRestriction(account, restriction)](#ERC7984Restricted-_setRestriction-address-enum-ERC7984Restricted-Restriction-) -- [_blockUser(account)](#ERC7984Restricted-_blockUser-address-) -- [_allowUser(account)](#ERC7984Restricted-_allowUser-address-) -- [_resetUser(account)](#ERC7984Restricted-_resetUser-address-) -- [_checkRestriction(account)](#ERC7984Restricted-_checkRestriction-address-) -- [_checkRecipientRestriction(account)](#ERC7984Restricted-_checkRecipientRestriction-address-) +- [_domainSeparatorV4()](#EIP712-_domainSeparatorV4--) +- [_hashTypedDataV4(structHash)](#EIP712-_hashTypedDataV4-bytes32-) +- [eip712Domain()](#EIP712-eip712Domain--) +- [_EIP712Name()](#EIP712-_EIP712Name--) +- [_EIP712Version()](#EIP712-_EIP712Version--)
-ERC7984Freezable +Nonces -- [_confidentialAvailable(account)](#ERC7984Freezable-_confidentialAvailable-address-) -- [_setConfidentialFrozen(account, encryptedAmount)](#ERC7984Freezable-_setConfidentialFrozen-address-euint64-) +- [nonces(owner)](#Nonces-nonces-address-) +- [_useNonce(owner)](#Nonces-_useNonce-address-) +- [_useCheckedNonce(owner, nonce)](#Nonces-_useCheckedNonce-address-uint256-)
ERC7984 +- [supportsInterface(interfaceId)](#ERC7984-supportsInterface-bytes4-) - [name()](#ERC7984-name--) - [symbol()](#ERC7984-symbol--) - [decimals()](#ERC7984-decimals--) - [contractURI()](#ERC7984-contractURI--) -- [confidentialTotalSupply()](#ERC7984-confidentialTotalSupply--) - [confidentialBalanceOf(account)](#ERC7984-confidentialBalanceOf-address-) - [isOperator(holder, spender)](#ERC7984-isOperator-address-address-) - [setOperator(operator, until)](#ERC7984-setOperator-address-uint48-) @@ -2407,796 +3649,877 @@ This interface provides compliance checks, transfer controls and enforcement act - [_transfer(from, to, amount)](#ERC7984-_transfer-address-address-euint64-) - [_transferAndCall(from, to, amount, data)](#ERC7984-_transferAndCall-address-address-euint64-bytes-) -
+
+
+
+ +
+

Events

+
+
+VotesConfidential + +- [DelegateVotesChanged(delegate, previousVotes, newVotes)](#VotesConfidential-DelegateVotesChanged-address-euint64-euint64-) +- [DelegateChanged(delegator, fromDelegate, toDelegate)](#VotesConfidential-DelegateChanged-address-address-address-) + +
+
+IERC5267 + +- [EIP712DomainChanged()](#IERC5267-EIP712DomainChanged--) + +
+
+ERC7984 + +- [AmountDiscloseRequested(encryptedAmount, requester)](#ERC7984-AmountDiscloseRequested-euint64-address-) + +
+
+IERC7984 + +- [OperatorSet(holder, operator, until)](#IERC7984-OperatorSet-address-address-uint48-) +- [ConfidentialTransfer(from, to, amount)](#IERC7984-ConfidentialTransfer-address-address-euint64-) +- [AmountDisclosed(encryptedAmount, amount)](#IERC7984-AmountDisclosed-euint64-uint64-) + +
+
+
+ +
+

Errors

+
+
+VotesConfidential + +- [VotesExpiredSignature(expiry)](#VotesConfidential-VotesExpiredSignature-uint256-) +- [ERC6372InconsistentClock()](#VotesConfidential-ERC6372InconsistentClock--) +- [ERC5805FutureLookup(timepoint, clock)](#VotesConfidential-ERC5805FutureLookup-uint256-uint48-) + +
+
+HandleAccessManager + +- [HandleAccessManagerNotAllowed(handle, account)](#HandleAccessManager-HandleAccessManagerNotAllowed-bytes32-address-) + +
+
+Nonces + +- [InvalidAccountNonce(account, currentNonce)](#Nonces-InvalidAccountNonce-address-uint256-) + +
+
+ERC7984 + +- [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) +- [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) +- [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) +- [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) +- [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) + +
+
+
+ + + +
+
+

confidentialTotalSupply() → euint64

+
+

public

+# +
+
+
+ +Returns the confidential total supply of the token. + +
+
+ + + +
+
+

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

+
+

internal

+# +
+
+
+ +Safely moves up to `amount` from `from` to `to`, or mints/burns if `from`/`to` is the zero address. +Emits a [`IERC7984.ConfidentialTransfer`](/confidential-contracts/api/interfaces#IERC7984-ConfidentialTransfer-address-address-euint64-) event with the successfully transferred amount. + +
+
+ + + +
+
+

_getVotingUnits(address account) → euint64

+
+

internal

+# +
+
+
+
-
-

Events

-
-
-Pausable + -- [Paused(account)](#Pausable-Paused-address-) -- [Unpaused(account)](#Pausable-Unpaused-address-) +
-
-
-ERC7984Restricted +## `ERC7984BalanceCapHookModule` -- [UserRestrictionUpdated(account, restriction)](#ERC7984Restricted-UserRestrictionUpdated-address-enum-ERC7984Restricted-Restriction-) + + + -
-
-ERC7984Freezable +
-- [TokensFrozen(account, encryptedAmount)](#ERC7984Freezable-TokensFrozen-address-euint64-) +```solidity +import "@openzeppelin/confidential-contracts/token/ERC7984/utils/ERC7984BalanceCapHookModule.sol"; +``` -
-
-ERC7984 +An ERC-7984 hook module that limits the balance of each investor. -- [AmountDiscloseRequested(encryptedAmount, requester)](#ERC7984-AmountDiscloseRequested-euint64-address-) +The cap is stored as an encrypted `euint64` value. The pre-transfer hook compares the recipient's prospective balance to the +encrypted cap and emits an encrypted compliance result via [`ERC7984HookModule._emitPreTransferResults`](#ERC7984HookModule-_emitPreTransferResults-address-address-address-euint64-ebool-bytes32-). -
-
-IERC7984 +This module is compatible with [`ERC7984Hooked`](#ERC7984Hooked). -- [OperatorSet(holder, operator, until)](#IERC7984-OperatorSet-address-address-uint48-) -- [ConfidentialTransfer(from, to, amount)](#IERC7984-ConfidentialTransfer-address-address-euint64-) -- [AmountDisclosed(encryptedAmount, amount)](#IERC7984-AmountDisclosed-euint64-uint64-) + +This module notifies senders of the result of the pre-transfer hook. This can be used to leak +information about the balance of the recipient. This is a potential security risk and should be used +with caution. Production use-cases may want to remove this notification. + -
+
+

Functions

+
+- [setMaxBalance(token, newMaxBalance, inputProof)](#ERC7984BalanceCapHookModule-setMaxBalance-address-externalEuint64-bytes-) +- [maxBalance(token)](#ERC7984BalanceCapHookModule-maxBalance-address-) +- [_setMaxBalance(token, newMaxBalance)](#ERC7984BalanceCapHookModule-_setMaxBalance-address-euint64-) +- [_preTransfer(token, from, to, encryptedAmount)](#ERC7984BalanceCapHookModule-_preTransfer-address-address-address-euint64-) +- [_onInstall(token, initData)](#ERC7984BalanceCapHookModule-_onInstall-address-bytes-)
-IAccessControl - -- [RoleAdminChanged(role, previousAdminRole, newAdminRole)](#IAccessControl-RoleAdminChanged-bytes32-bytes32-bytes32-) -- [RoleGranted(role, account, sender)](#IAccessControl-RoleGranted-bytes32-address-address-) -- [RoleRevoked(role, account, sender)](#IAccessControl-RoleRevoked-bytes32-address-address-) +ERC7984HookModule + +- [preTransfer(from, to, encryptedAmount)](#ERC7984HookModule-preTransfer-address-address-euint64-) +- [postTransfer(from, to, encryptedAmount)](#ERC7984HookModule-postTransfer-address-address-euint64-) +- [onInstall(initData)](#ERC7984HookModule-onInstall-bytes-) +- [supportsInterface(interfaceId)](#ERC7984HookModule-supportsInterface-bytes4-) +- [_postTransfer(, , , )](#ERC7984HookModule-_postTransfer-address-address-address-euint64-) +- [_getTokenHandleAllowance(token, handle)](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-) +- [_getTokenHandleAllowance(token, handle, persistent)](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-) +- [_emitPreTransferResults(token, from, to, encryptedAmount, compliant, context)](#ERC7984HookModule-_emitPreTransferResults-address-address-address-euint64-ebool-bytes32-) +- [_accessHandle(token, handle)](#ERC7984HookModule-_accessHandle-address-euint64-)
-

Errors

+

Events

+- [ERC7984BalanceCapHookModuleMaxBalanceSet(token, newMaxBalance)](#ERC7984BalanceCapHookModule-ERC7984BalanceCapHookModuleMaxBalanceSet-address-euint64-)
-Pausable - -- [EnforcedPause()](#Pausable-EnforcedPause--) -- [ExpectedPause()](#Pausable-ExpectedPause--) - -
-
-ERC7984Restricted +IERC7984HookModule -- [UserRestricted(account)](#ERC7984Restricted-UserRestricted-address-) +- [ERC7984HookModuleResult(token, from, to, encryptedAmount, result, context)](#IERC7984HookModule-ERC7984HookModuleResult-address-address-address-euint64-ebool-bytes32-)
-
-ERC7984 - -- [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) -- [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) -- [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) -- [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) -- [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-) +
+
-
+
+

Errors

+
-IAccessControl +ERC7984HookModule -- [AccessControlUnauthorizedAccount(account, neededRole)](#IAccessControl-AccessControlUnauthorizedAccount-address-bytes32-) -- [AccessControlBadConfirmation()](#IAccessControl-AccessControlBadConfirmation--) +- [ERC7984HookModuleUnauthorizedAccount(account)](#ERC7984HookModule-ERC7984HookModuleUnauthorizedAccount-address-) +- [ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984HookModule-ERC7984HookModuleUnauthorizedUseOfEncryptedAmount-euint64-address-)
- +
-

onlyAdmin()

+

setMaxBalance(address token, externalEuint64 newMaxBalance, bytes inputProof)

-

internal

-# +

public

+#
-
-Checks if the sender is an admin. +Sets the max balance for a given token `token` to the encrypted value `newMaxBalance`. + +`msg.sender` must have the agent role on `token`.
- +
-

onlyAgent()

+

maxBalance(address token) → euint64

-

internal

-# +

public

+#
-
-Checks if the sender is an agent. +Gets the encrypted max balance for a given token `token`. Returns the zero handle if unset.
- +
-

constructor(address admin)

+

_setMaxBalance(address token, euint64 newMaxBalance)

internal

-# +#
+Sets the encrypted max balance for a given token, grants the module persistent ACL, and emits an event. +
- +
-

supportsInterface(bytes4 interfaceId) → bool

+

_preTransfer(address token, address from, address to, euint64 encryptedAmount) → ebool result

-

public

-# +

internal

+#
+Internal function which runs before a transfer. Transient access is already granted to the module +for `encryptedAmount`. If additional handle access is needed from the token, call [`ERC7984HookModule._getTokenHandleAllowance`](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-). + + +ACL allowance on `encryptedAmount` is already checked for `msg.sender` in [`ERC7984HookModule.preTransfer`](#ERC7984HookModule-preTransfer-address-address-euint64-). + +
- +
-

isAdmin(address account) → bool

+

_onInstall(address token, bytes initData)

-

public

-# +

internal

+#
-Returns true if has admin role, false otherwise. +See [`ERC7984HookModule._onInstall`](#ERC7984HookModule-_onInstall-address-bytes-). The `initData` must contain the initial max balance for the token +along with the input proof for the max balance. These are encoded using standard ABI encoding.
- +
-

isAgent(address account) → bool

+

ERC7984BalanceCapHookModuleMaxBalanceSet(address indexed token, euint64 newMaxBalance)

-

public

-# +

event

+#
+
-Returns true if agent, false otherwise. +Emitted when the max balance for a given token is set.
- + -
-
-

addAgent(address account)

-
-

public

-# +
+ +## `ERC7984HolderCapHookModule` + + + + + +
+ +```solidity +import "@openzeppelin/confidential-contracts/token/ERC7984/utils/ERC7984HolderCapHookModule.sol"; +``` + +An ERC-7984 hook module that limits the number of holders for a given token. + + +This module must be installed prior to minting any tokens. After the total supply is initialized, +it is not possible to guarantee that the number of holders is 0, so the module can not be installed. + + + +This module may not function correctly with non-standard tokens such as fee on transfer. + + +
+

Functions

+
+- [setMaxHolderCount(token, maxHolderCount_)](#ERC7984HolderCapHookModule-setMaxHolderCount-address-uint64-) +- [maxHolderCount(token)](#ERC7984HolderCapHookModule-maxHolderCount-address-) +- [holderCount(token)](#ERC7984HolderCapHookModule-holderCount-address-) +- [_setMaxHolderCount(token, maxHolderCount_)](#ERC7984HolderCapHookModule-_setMaxHolderCount-address-uint64-) +- [_preTransfer(token, from, to, encryptedAmount)](#ERC7984HolderCapHookModule-_preTransfer-address-address-address-euint64-) +- [_postTransfer(token, from, to, encryptedAmount)](#ERC7984HolderCapHookModule-_postTransfer-address-address-address-euint64-) +- [_onInstall(token, initData)](#ERC7984HolderCapHookModule-_onInstall-address-bytes-) +
+ERC7984HookModule + +- [preTransfer(from, to, encryptedAmount)](#ERC7984HookModule-preTransfer-address-address-euint64-) +- [postTransfer(from, to, encryptedAmount)](#ERC7984HookModule-postTransfer-address-address-euint64-) +- [onInstall(initData)](#ERC7984HookModule-onInstall-bytes-) +- [supportsInterface(interfaceId)](#ERC7984HookModule-supportsInterface-bytes4-) +- [_getTokenHandleAllowance(token, handle)](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-) +- [_getTokenHandleAllowance(token, handle, persistent)](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-) +- [_emitPreTransferResults(token, from, to, encryptedAmount, compliant, context)](#ERC7984HookModule-_emitPreTransferResults-address-address-address-euint64-ebool-bytes32-) +- [_accessHandle(token, handle)](#ERC7984HookModule-_accessHandle-address-euint64-) + +
-
-Adds agent. +
+

Events

+
+- [ERC7984HolderCapHookModuleMaxHolderCountSet(token, newMaxHolderCount)](#ERC7984HolderCapHookModule-ERC7984HolderCapHookModuleMaxHolderCountSet-address-uint64-) +
+IERC7984HookModule + +- [ERC7984HookModuleResult(token, from, to, encryptedAmount, result, context)](#IERC7984HookModule-ERC7984HookModuleResult-address-address-address-euint64-ebool-bytes32-) +
- +
+

Errors

+
+- [ERC7984HolderCapHookModuleInvalidMaxHolderCount(maxHolderCount)](#ERC7984HolderCapHookModule-ERC7984HolderCapHookModuleInvalidMaxHolderCount-uint64-) +- [ERC7984HolderCapHookModuleTotalSupplyInitialized()](#ERC7984HolderCapHookModule-ERC7984HolderCapHookModuleTotalSupplyInitialized--) +
+ERC7984HookModule + +- [ERC7984HookModuleUnauthorizedAccount(account)](#ERC7984HookModule-ERC7984HookModuleUnauthorizedAccount-address-) +- [ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984HookModule-ERC7984HookModuleUnauthorizedUseOfEncryptedAmount-euint64-address-) + +
+
+
+ +
-

removeAgent(address account)

+

setMaxHolderCount(address token, uint64 maxHolderCount_)

public

-# +#
-Removes agent. +Sets the max number of holders for the given token `token` to `maxHolderCount_`. + +`msg.sender` must have the agent role on `token`
- +
-

pause()

+

maxHolderCount(address token) → uint64

public

-# +#
-Pauses contract. +Gets max number of holders for the given token `token`.
- +
-

unpause()

+

holderCount(address token) → euint64

public

-# +#
-Unpauses contract. +Gets current number of holders for the given token `token`.
- +
-

blockUser(address account)

+

_setMaxHolderCount(address token, uint64 maxHolderCount_)

-

public

-# +

internal

+#
-Blocks a user account. +Sets the max holder count for a given token to `maxHolderCount_` and emits an event.
- +
-

unblockUser(address account)

+

_preTransfer(address token, address from, address to, euint64 encryptedAmount) → ebool result

-

public

-# +

internal

+#
-Unblocks a user account. +Internal function which runs before a transfer. Transient access is already granted to the module +for `encryptedAmount`. If additional handle access is needed from the token, call [`ERC7984HookModule._getTokenHandleAllowance`](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-). + + +ACL allowance on `encryptedAmount` is already checked for `msg.sender` in [`ERC7984HookModule.preTransfer`](#ERC7984HookModule-preTransfer-address-address-euint64-). +
- +
-

setConfidentialFrozen(address account, externalEuint64 encryptedAmount, bytes inputProof)

+

_postTransfer(address token, address from, address to, euint64 encryptedAmount)

-

public

-# +

internal

+#
-Sets confidential frozen for an account with proof. +Internal function which performs operations after transfers. Transient access is already granted to the module +for `encryptedAmount`. If additional handle access is needed from the token, call [`ERC7984HookModule._getTokenHandleAllowance`](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-). + + +ACL allowance on `encryptedAmount` is already checked for `msg.sender` in [`ERC7984HookModule.postTransfer`](#ERC7984HookModule-postTransfer-address-address-euint64-). +
- +
-

setConfidentialFrozen(address account, euint64 encryptedAmount)

+

_onInstall(address token, bytes initData)

-

public

-# +

internal

+#
-Sets confidential frozen for an account. +See [`ERC7984HookModule._onInstall`](#ERC7984HookModule-_onInstall-address-bytes-). The `initData` must contain the initial max holder count for the token +as a standard ABI encoded uint64.
- +
-

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

+

ERC7984HolderCapHookModuleMaxHolderCountSet(address indexed token, uint64 newMaxHolderCount)

-

public

-# +

event

+#
+
-Mints confidential amount of tokens to account with proof. +Emitted when the max holder count for a given token is set.
- +
-

confidentialMint(address to, euint64 encryptedAmount) → euint64

+

ERC7984HolderCapHookModuleInvalidMaxHolderCount(uint64 maxHolderCount)

-

public

-# +

error

+#
-Mints confidential amount of tokens to account. +The new max holder count `maxHolderCount` is invalid.
- +
-

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

+

ERC7984HolderCapHookModuleTotalSupplyInitialized()

-

public

-# +

error

+#
-Burns confidential amount of tokens from account with proof. +
+
+ + + +
+ +## `ERC7984HookModule` + + + + + +
+ +```solidity +import "@openzeppelin/confidential-contracts/token/ERC7984/utils/ERC7984HookModule.sol"; +``` + +An abstract base contract for building ERC-7984 hook modules. Compatible with [`ERC7984Hooked`](#ERC7984Hooked). +
+

Functions

+
+- [preTransfer(from, to, encryptedAmount)](#ERC7984HookModule-preTransfer-address-address-euint64-) +- [postTransfer(from, to, encryptedAmount)](#ERC7984HookModule-postTransfer-address-address-euint64-) +- [onInstall(initData)](#ERC7984HookModule-onInstall-bytes-) +- [supportsInterface(interfaceId)](#ERC7984HookModule-supportsInterface-bytes4-) +- [_onInstall(, )](#ERC7984HookModule-_onInstall-address-bytes-) +- [_preTransfer(, , , )](#ERC7984HookModule-_preTransfer-address-address-address-euint64-) +- [_postTransfer(, , , )](#ERC7984HookModule-_postTransfer-address-address-address-euint64-) +- [_getTokenHandleAllowance(token, handle)](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-) +- [_getTokenHandleAllowance(token, handle, persistent)](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-) +- [_emitPreTransferResults(token, from, to, encryptedAmount, compliant, context)](#ERC7984HookModule-_emitPreTransferResults-address-address-address-euint64-ebool-bytes32-) +- [_accessHandle(token, handle)](#ERC7984HookModule-_accessHandle-address-euint64-)
- +
+

Events

+
+
+IERC7984HookModule + +- [ERC7984HookModuleResult(token, from, to, encryptedAmount, result, context)](#IERC7984HookModule-ERC7984HookModuleResult-address-address-address-euint64-ebool-bytes32-) -
-
-

confidentialBurn(address account, euint64 encryptedAmount) → euint64

-
-

public

-# +
-
- -Burns confidential amount of tokens from account. +
+

Errors

+
+- [ERC7984HookModuleUnauthorizedAccount(account)](#ERC7984HookModule-ERC7984HookModuleUnauthorizedAccount-address-) +- [ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984HookModule-ERC7984HookModuleUnauthorizedUseOfEncryptedAmount-euint64-address-)
- +
-

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

+

preTransfer(address from, address to, euint64 encryptedAmount) → ebool

public

-# +#
-Variant of `forceConfidentialTransferFrom-address-address-euint64` with an input proof. +Hook that runs before a transfer. Should not mutate token state. Module is already +granted transient access to `encryptedAmount`.
- +
-

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

+

postTransfer(address from, address to, euint64 encryptedAmount)

public

-# +#
-Force transfer callable by the role [`ERC7984Rwa.AGENT_ROLE`](#ERC7984Rwa-AGENT_ROLE-bytes32) which transfers tokens from `from` to `to` and -bypasses the [`ERC7984Restricted`](#ERC7984Restricted) (only on from) and [`++Pausable++`](https://docs.openzeppelin.com/contracts/api/utils#pausable) -checks. Frozen tokens are not transferred and must be unfrozen first. +Performs operation after transfer.
- +
-

confidentialAvailable(address account) → euint64

+

onInstall(bytes initData)

public

-# +#
-Returns the confidential available (unfrozen) balance of an account. Gives ACL allowance to `account`. +Performs operations after installation.
- +
-

confidentialFrozen(address account) → euint64

+

supportsInterface(bytes4 interfaceId) → bool

public

-# +#
-Returns the confidential frozen balance of an account. +Returns true if this contract implements the interface defined by +`interfaceId`. See the corresponding +[ERC section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) +to learn more about how these ids are created. + +This function call must use less than 30 000 gas.
- +
-

paused() → bool

+

_onInstall(address, bytes)

-

public

-# +

internal

+#
-Returns true if the contract is paused, and false otherwise. +Internal function which may be overridden by the derived contract to perform actions +when the module is installed. Should clean up dirty state from possible previous installations.
- +
-

canTransact(address account) → bool

+

_preTransfer(address, address, address, euint64) → ebool

-

public

-# +

internal

+#
-Returns whether a user account is allowed to interact with the token. +Internal function which runs before a transfer. Transient access is already granted to the module +for `encryptedAmount`. If additional handle access is needed from the token, call [`ERC7984HookModule._getTokenHandleAllowance`](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-). -Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist). + +ACL allowance on `encryptedAmount` is already checked for `msg.sender` in [`ERC7984HookModule.preTransfer`](#ERC7984HookModule-preTransfer-address-address-euint64-). +
- +
-

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

+

_postTransfer(address, address, address, euint64)

internal

-# +#
-Internal function which updates confidential balances while performing frozen and restriction compliance checks. +Internal function which performs operations after transfers. Transient access is already granted to the module +for `encryptedAmount`. If additional handle access is needed from the token, call [`ERC7984HookModule._getTokenHandleAllowance`](#ERC7984HookModule-_getTokenHandleAllowance-address-euint64-bool-). + + +ACL allowance on `encryptedAmount` is already checked for `msg.sender` in [`ERC7984HookModule.postTransfer`](#ERC7984HookModule-postTransfer-address-address-euint64-). +
- +
-

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

+

_getTokenHandleAllowance(address token, euint64 handle)

internal

-# +#
-Internal function which forces transfer of confidential amount of tokens from account to account by skipping compliance checks. +Allow modules to get access to token handles during transaction.
- +
-

_checkSenderRestriction(address account)

+

_getTokenHandleAllowance(address token, euint64 handle, bool persistent)

internal

-# +#
-Bypasses the `from` restriction check when performing a [`ERC7984Rwa.forceConfidentialTransferFrom`](#ERC7984Rwa-forceConfidentialTransferFrom-address-address-euint64-). +Allow modules to get access to token handles.
- +
-

AGENT_ROLE() → bytes32

+

_emitPreTransferResults(address token, address from, address to, euint64 encryptedAmount, ebool compliant, bytes32 context)

-

public

-# +

internal

+#
-Accounts granted the agent role have the following permissioned abilities: - -- Mint/Burn to/from a given address (does not require permission) -- Force transfer from a given address (does not require permission) - - Bypasses pause and restriction checks (not frozen) -- Pause/Unpause the contract -- Block/Unblock a given account -- Set frozen amount of tokens for a given account. - -
-
- - - -
- -## `ERC7984Votes` - - - - - -
- -```solidity -import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Votes.sol"; -``` - -Extension of [`ERC7984`](#ERC7984) supporting confidential votes tracking and delegation. - -The amount of confidential voting units an account has is equal to the balance of -that account. Voting power is taken into account when an account delegates votes to itself or to another -account. - -
-

Functions

-
-- [confidentialTotalSupply()](#ERC7984Votes-confidentialTotalSupply--) -- [_update(from, to, amount)](#ERC7984Votes-_update-address-address-euint64-) -- [_getVotingUnits(account)](#ERC7984Votes-_getVotingUnits-address-) -
-VotesConfidential - -- [clock()](#VotesConfidential-clock--) -- [CLOCK_MODE()](#VotesConfidential-CLOCK_MODE--) -- [getVotes(account)](#VotesConfidential-getVotes-address-) -- [getPastVotes(account, timepoint)](#VotesConfidential-getPastVotes-address-uint256-) -- [getPastTotalSupply(timepoint)](#VotesConfidential-getPastTotalSupply-uint256-) -- [delegates(account)](#VotesConfidential-delegates-address-) -- [delegate(delegatee)](#VotesConfidential-delegate-address-) -- [delegateBySig(delegatee, nonce, expiry, v, r, s)](#VotesConfidential-delegateBySig-address-uint256-uint256-uint8-bytes32-bytes32-) -- [_delegate(account, delegatee)](#VotesConfidential-_delegate-address-address-) -- [_transferVotingUnits(from, to, amount)](#VotesConfidential-_transferVotingUnits-address-address-euint64-) -- [_moveDelegateVotes(from, to, amount)](#VotesConfidential-_moveDelegateVotes-address-address-euint64-) -- [_validateTimepoint(timepoint)](#VotesConfidential-_validateTimepoint-uint256-) - -
-
-HandleAccessManager - -- [getHandleAllowance(handle, account, persistent)](#HandleAccessManager-getHandleAllowance-bytes32-address-bool-) -- [_validateHandleAllowance(handle)](#HandleAccessManager-_validateHandleAllowance-bytes32-) - -
-
-EIP712 - -- [_domainSeparatorV4()](#EIP712-_domainSeparatorV4--) -- [_hashTypedDataV4(structHash)](#EIP712-_hashTypedDataV4-bytes32-) -- [eip712Domain()](#EIP712-eip712Domain--) -- [_EIP712Name()](#EIP712-_EIP712Name--) -- [_EIP712Version()](#EIP712-_EIP712Version--) - -
-
-Nonces - -- [nonces(owner)](#Nonces-nonces-address-) -- [_useNonce(owner)](#Nonces-_useNonce-address-) -- [_useCheckedNonce(owner, nonce)](#Nonces-_useCheckedNonce-address-uint256-) - -
-
-ERC7984 - -- [supportsInterface(interfaceId)](#ERC7984-supportsInterface-bytes4-) -- [name()](#ERC7984-name--) -- [symbol()](#ERC7984-symbol--) -- [decimals()](#ERC7984-decimals--) -- [contractURI()](#ERC7984-contractURI--) -- [confidentialBalanceOf(account)](#ERC7984-confidentialBalanceOf-address-) -- [isOperator(holder, spender)](#ERC7984-isOperator-address-address-) -- [setOperator(operator, until)](#ERC7984-setOperator-address-uint48-) -- [confidentialTransfer(to, encryptedAmount, inputProof)](#ERC7984-confidentialTransfer-address-externalEuint64-bytes-) -- [confidentialTransfer(to, amount)](#ERC7984-confidentialTransfer-address-euint64-) -- [confidentialTransferFrom(from, to, encryptedAmount, inputProof)](#ERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes-) -- [confidentialTransferFrom(from, to, amount)](#ERC7984-confidentialTransferFrom-address-address-euint64-) -- [confidentialTransferAndCall(to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferAndCall-address-externalEuint64-bytes-bytes-) -- [confidentialTransferAndCall(to, amount, data)](#ERC7984-confidentialTransferAndCall-address-euint64-bytes-) -- [confidentialTransferFromAndCall(from, to, encryptedAmount, inputProof, data)](#ERC7984-confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes-) -- [confidentialTransferFromAndCall(from, to, amount, data)](#ERC7984-confidentialTransferFromAndCall-address-address-euint64-bytes-) -- [requestDiscloseEncryptedAmount(encryptedAmount)](#ERC7984-requestDiscloseEncryptedAmount-euint64-) -- [discloseEncryptedAmount(encryptedAmount, cleartextAmount, decryptionProof)](#ERC7984-discloseEncryptedAmount-euint64-uint64-bytes-) -- [_setOperator(holder, operator, until)](#ERC7984-_setOperator-address-address-uint48-) -- [_mint(to, amount)](#ERC7984-_mint-address-euint64-) -- [_burn(from, amount)](#ERC7984-_burn-address-euint64-) -- [_transfer(from, to, amount)](#ERC7984-_transfer-address-address-euint64-) -- [_transferAndCall(from, to, amount, data)](#ERC7984-_transferAndCall-address-address-euint64-bytes-) - -
-
-
- -
-

Events

-
-
-VotesConfidential - -- [DelegateVotesChanged(delegate, previousVotes, newVotes)](#VotesConfidential-DelegateVotesChanged-address-euint64-euint64-) -- [DelegateChanged(delegator, fromDelegate, toDelegate)](#VotesConfidential-DelegateChanged-address-address-address-) - -
-
-IERC5267 - -- [EIP712DomainChanged()](#IERC5267-EIP712DomainChanged--) - -
-
-ERC7984 - -- [AmountDiscloseRequested(encryptedAmount, requester)](#ERC7984-AmountDiscloseRequested-euint64-address-) - -
-
-IERC7984 - -- [OperatorSet(holder, operator, until)](#IERC7984-OperatorSet-address-address-uint48-) -- [ConfidentialTransfer(from, to, amount)](#IERC7984-ConfidentialTransfer-address-address-euint64-) -- [AmountDisclosed(encryptedAmount, amount)](#IERC7984-AmountDisclosed-euint64-uint64-) - -
-
-
- -
-

Errors

-
-
-VotesConfidential - -- [VotesExpiredSignature(expiry)](#VotesConfidential-VotesExpiredSignature-uint256-) -- [ERC6372InconsistentClock()](#VotesConfidential-ERC6372InconsistentClock--) -- [ERC5805FutureLookup(timepoint, clock)](#VotesConfidential-ERC5805FutureLookup-uint256-uint48-) - -
-
-HandleAccessManager - -- [HandleAccessManagerNotAllowed(handle, account)](#HandleAccessManager-HandleAccessManagerNotAllowed-bytes32-address-) - -
-
-Nonces - -- [InvalidAccountNonce(account, currentNonce)](#Nonces-InvalidAccountNonce-address-uint256-) - -
-
-ERC7984 +Optionally emit the result of the pre-transfer hook. -- [ERC7984InvalidReceiver(receiver)](#ERC7984-ERC7984InvalidReceiver-address-) -- [ERC7984InvalidSender(sender)](#ERC7984-ERC7984InvalidSender-address-) -- [ERC7984UnauthorizedSpender(holder, spender)](#ERC7984-ERC7984UnauthorizedSpender-address-address-) -- [ERC7984ZeroBalance(holder)](#ERC7984-ERC7984ZeroBalance-address-) -- [ERC7984UnauthorizedUseOfEncryptedAmount(amount, user)](#ERC7984-ERC7984UnauthorizedUseOfEncryptedAmount-euint64-address-) -- [ERC7984UnauthorizedCaller(caller)](#ERC7984-ERC7984UnauthorizedCaller-address-) -- [ERC7984InvalidGatewayRequest(requestId)](#ERC7984-ERC7984InvalidGatewayRequest-uint256-) +Grants persistent ACL on `compliant` to both this contract and `from`. -
- +
-

confidentialTotalSupply() → euint64

+

_accessHandle(address token, euint64 handle)

-

public

-# +

internal

+#
-Returns the confidential total supply of the token. +Get transient ACL allowance for the given handle from a contract that inherits [`HandleAccessManager`](/confidential-contracts/api/utils#HandleAccessManager). + +Additionally verifies that the token is authorized to access the handle.
- +
-

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

+

ERC7984HookModuleUnauthorizedAccount(address account)

-

internal

-# +

error

+#
+The caller `account` is not authorized to perform the operation. +
- +
-

_getVotingUnits(address account) → euint64

+

ERC7984HookModuleUnauthorizedUseOfEncryptedAmount(euint64 amount, address user)

-

internal

-# +

error

+#
+The caller `user` does not have access to the encrypted amount `amount`. +
@@ -3206,7 +4529,7 @@ Returns the confidential total supply of the token. ## `ERC7984Utils` - + diff --git a/content/confidential-contracts/api/utils.mdx b/content/confidential-contracts/api/utils.mdx index c66cc535..d7323025 100644 --- a/content/confidential-contracts/api/utils.mdx +++ b/content/confidential-contracts/api/utils.mdx @@ -26,7 +26,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t ## `FHESafeMath` - + @@ -51,6 +51,8 @@ This library may return an uninitialized value if all inputs are uninitialized. - [tryDecrease(oldValue, delta)](#FHESafeMath-tryDecrease-euint64-euint64-) - [tryAdd(a, b)](#FHESafeMath-tryAdd-euint64-euint64-) - [trySub(a, b)](#FHESafeMath-trySub-euint64-euint64-) +- [saturatingAdd(a, b)](#FHESafeMath-saturatingAdd-euint64-euint64-) +- [saturatingSub(a, b)](#FHESafeMath-saturatingSub-euint64-euint64-)
@@ -128,13 +130,49 @@ will be `a - b`. Otherwise, `success` will be false, and `res` will be 0.
+ + +
+
+

saturatingAdd(euint64 a, euint64 b) → euint64

+
+

internal

+# +
+
+
+ +Add `a` and `b` saturating at `type(uint64).max` on overflow. The returned value is the sum +of `a` and `b` if it does not overflow, otherwise `type(uint64).max`. + +
+
+ + + +
+
+

saturatingSub(euint64 a, euint64 b) → euint64

+
+

internal

+# +
+
+
+ +Subtract `b` from `a` saturating at zero on underflow. The returned value is `a - b` if +`a >= b`, otherwise 0. + +
+
+
## `HandleAccessManager` - + @@ -148,7 +186,7 @@ import "@openzeppelin/confidential-contracts/utils/HandleAccessManager.sol";

Functions

- [getHandleAllowance(handle, account, persistent)](#HandleAccessManager-getHandleAllowance-bytes32-address-bool-) -- [_validateHandleAllowance(handle)](#HandleAccessManager-_validateHandleAllowance-bytes32-) +- [_validateHandleAllowance()](#HandleAccessManager-_validateHandleAllowance-bytes32-)
@@ -185,7 +223,7 @@ This function call is validated by [`HandleAccessManager._validateHandleAllowanc
-

_validateHandleAllowance(bytes32 handle) → bool

+

_validateHandleAllowance(bytes32) → bool

internal

# @@ -193,7 +231,7 @@ This function call is validated by [`HandleAccessManager._validateHandleAllowanc
-Unimplemented function that must return true if the message sender is allowed to call +Validation function that must return true if the message sender is allowed to call [`HandleAccessManager.getHandleAllowance`](#HandleAccessManager-getHandleAllowance-bytes32-address-bool-) for the given handle.
@@ -220,7 +258,7 @@ Unimplemented function that must return true if the message sender is allowed to ## `CheckpointsConfidential` - + diff --git a/content/confidential-contracts/changelog.mdx b/content/confidential-contracts/changelog.mdx index d1ef1a63..1b8dadaf 100644 --- a/content/confidential-contracts/changelog.mdx +++ b/content/confidential-contracts/changelog.mdx @@ -2,6 +2,57 @@ title: Changelog --- + +# [v0.5.1](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/releases/tag/v0.5.1) - 2026-06-22 + +- `BatcherConfidential`: Initialize the zero value before unwrapping when dispatching a batch with no contributions. + + + +[Changes][v0.5.1] + + + +# [v0.5.0](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/releases/tag/v0.5.0) - 2026-06-17 + +### Token + +- `ERC7984`: Remove revert on transfer where the sender has an uninitialized balance. ([#357](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/357)) +- `ERC7984Hooked`: Add an `ERC7984` extension that calls external hooks before and after transfer of confidential tokens. ([#332](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/332)) +- `ERC7984HookModule`: Add a base hook module for building modules compatible with `ERC7984Hooked`. ([#351](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/351)) +- `ERC7984BalanceCapHookModule`: Add an example hook module that enforces a confidential balance cap for the token. ([#351](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/351)) +- `ERC7984HolderCapHookModule`: Add an example hook module that enforces a maximum number of holders for the token. ([#351](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/351)) +- `ERC7984Rwa`: Always call `_update` on transfers (even force). Bypass restriction via restriction override. ([#339](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/339)) +- `ERC7984Rwa`: Add token recovery functionality. ([#341](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/341)) +- `ERC7984Rwa`: Bypass recipient on RWA force transfer in addition to sender. ([#372](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/372)) +- `ERC7984Rwa`: Block overrides of `Context` functions (`_msgSender()`, `_msgData()`). ([#382](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/382)) +- `IERC7984Rwa`: Add token recovery function and event. ([#341](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/341)) + +### Finance + +- `BatcherConfidential`: Revert if underlying `toToken` balance changes during a partial route execution. ([#385](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/385)) + +### Utils + +- `FHESafeMath`: Add `saturatingAdd` and `saturatingSub` functions. ([#341](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/341)) +- `HandleAccessManager`: Return false by default in `_validateHandleAllowance`. ([#338](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/338)) + + + +[Changes][v0.5.0] + + + +# [v0.4.1](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/releases/tag/v0.4.1) - 2026-06-08 + +### Bug Fixes +- `BatcherConfidential`: Enable decryption of the `joinedAmount` in `BatcherConfidential`. ([#387](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/pull/387)) + + + +[Changes][v0.4.1] + + # [v0.4.0](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/releases/tag/v0.4.0) - 2026-03-30 @@ -111,6 +162,9 @@ Note: Confidential contracts are currently in a phase of rapid development--futu [Changes][v0.1.0] +[v0.5.1]: https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/compare/v0.5.0...v0.5.1 +[v0.5.0]: https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/compare/v0.4.1...v0.5.0 +[v0.4.1]: https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/compare/v0.4.0...v0.4.1 [v0.4.0]: https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/compare/v0.3.1...v0.4.0 [v0.3.1]: https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/compare/v0.3.0...v0.3.1 [v0.3.0]: https://github.com/OpenZeppelin/openzeppelin-confidential-contracts/compare/v0.2.0...v0.3.0 diff --git a/content/confidential-contracts/token.mdx b/content/confidential-contracts/token.mdx index 011b49de..09ad397c 100644 --- a/content/confidential-contracts/token.mdx +++ b/content/confidential-contracts/token.mdx @@ -41,7 +41,7 @@ Setting an operator for any amount of time allows the operator to _***take all o The token standard exposes transfer functions with and without callbacks. It is up to the caller to decide if a callback is necessary for the transfer. For smart contracts that support it, callbacks allow the operator approval step to be skipped and directly invoke the receiver contract via a callback. -Smart contracts that are the target of a callback must implement [`IERC7984Receiver`](/confidential-contracts/api/interfaces#IERC7984Receiver). After balances are updated for a transfer, the callback is triggered by calling the [`onConfidentialTransferReceived`](/confidential-contracts/api/interfaces#IERC7984Receiver-onConfidentialTransferReceived-address-address-euint64-bytes-) function. The function must either revert or return an `ebool` indicating success. If the callback returns false, the token transfer is reversed. +Smart contracts that are the target of a callback must implement [`IERC7984Receiver`](/confidential-contracts/api/interfaces#IERC7984Receiver). After balances are updated for a transfer, the callback is triggered by calling the [`onConfidentialTransferReceived`](/confidential-contracts/api/interfaces#IERC7984Receiver-onConfidentialTransferReceived-address-address-euint64-bytes-) function. The function must either revert or return an `ebool` indicating success. If the callback returns false, the ERC-7984 token contract attempts to refund the tokens from the recipient to the sender. ## Examples