diff --git a/content/confidential-contracts/api/finance.mdx b/content/confidential-contracts/api/finance.mdx
index faa9990d..cc04cac5 100644
--- a/content/confidential-contracts/api/finance.mdx
+++ b/content/confidential-contracts/api/finance.mdx
@@ -23,7 +23,7 @@ For convenience, this directory also includes:
## `ERC7821WithExecutor`
-
+
@@ -145,7 +145,7 @@ function _erc7821AuthorizedExecutor(
## `VestingWalletCliffConfidential`
-
+
@@ -328,7 +328,7 @@ The specified cliff duration is larger than the vesting duration.
## `VestingWalletConfidential`
-
+
@@ -338,7 +338,7 @@ The specified cliff duration is larger than the vesting duration.
import "@openzeppelin/confidential-contracts/finance/VestingWalletConfidential.sol";
```
-A vesting wallet is an ownable contract that can receive ConfidentialFungibleTokens, and release these
+A vesting wallet is an ownable contract that can receive ERC7984 tokens, and release these
assets to the wallet owner, also referred to as "beneficiary", according to a vesting schedule.
Any assets transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
@@ -506,7 +506,7 @@ Amount of token already released
Getter for the amount of releasable `token` tokens. `token` should be the address of an
-[`IConfidentialFungibleToken`](./interfaces#IConfidentialFungibleToken) contract.
+[`IERC7984`](/confidential-contracts/api/interfaces#IERC7984) contract.
@@ -622,7 +622,7 @@ Emitted when releasable vested tokens are released.
## `VestingWalletConfidentialFactory`
-
+
@@ -641,7 +641,7 @@ functions remain unimplemented to allow for custom implementations of the vestin
Functions
- [constructor()](#VestingWalletConfidentialFactory-constructor--)
-- [batchFundVestingWalletConfidential(confidentialFungibleToken, vestingPlans, inputProof)](#VestingWalletConfidentialFactory-batchFundVestingWalletConfidential-address-struct-VestingWalletConfidentialFactory-VestingPlan---bytes-)
+- [batchFundVestingWalletConfidential(token, vestingPlans, inputProof)](#VestingWalletConfidentialFactory-batchFundVestingWalletConfidential-address-struct-VestingWalletConfidentialFactory-VestingPlan---bytes-)
- [createVestingWalletConfidential(initArgs)](#VestingWalletConfidentialFactory-createVestingWalletConfidential-bytes-)
- [predictVestingWalletConfidential(initArgs)](#VestingWalletConfidentialFactory-predictVestingWalletConfidential-bytes-)
- [_validateVestingWalletInitArgs(initArgs)](#VestingWalletConfidentialFactory-_validateVestingWalletInitArgs-bytes-)
@@ -654,7 +654,7 @@ functions remain unimplemented to allow for custom implementations of the vestin
#
diff --git a/content/confidential-contracts/api/governance.mdx b/content/confidential-contracts/api/governance.mdx
index d8607c00..3df0fd38 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`
-
+
@@ -33,7 +33,7 @@ This contract keeps a history (checkpoints) of each account's confidential vote
voting power can be delegated either by calling the [`VotesConfidential.delegate`](#VotesConfidential-delegate-address-) function directly, or by providing
a signature to be used with [`VotesConfidential.delegateBySig`](#VotesConfidential-delegateBySig-address-uint256-uint256-uint8-bytes32-bytes32-). Confidential voting power handles can be queried
through the public accessors [`VotesConfidential.getVotes`](#VotesConfidential-getVotes-address-) and [`VotesConfidential.getPastVotes`](#VotesConfidential-getPastVotes-address-uint256-) but can only be decrypted by accounts
-allowed to access them. Ensure that [`HandleAccessManager._validateHandleAllowance`](./utils#HandleAccessManager-_validateHandleAllowance-bytes32-) is implemented properly, allowing all
+allowed to access them. Ensure that [`HandleAccessManager._validateHandleAllowance`](/confidential-contracts/api/utils#HandleAccessManager-_validateHandleAllowance-bytes32-) is implemented properly, allowing all
necessary addresses to access voting power handles.
By default, voting units does not account for voting power. This makes transfers of underlying
diff --git a/content/confidential-contracts/api/index.mdx b/content/confidential-contracts/api/index.mdx
index 2a562ff0..87f9575e 100644
--- a/content/confidential-contracts/api/index.mdx
+++ b/content/confidential-contracts/api/index.mdx
@@ -12,7 +12,8 @@ Smart contract token utilities and implementations for ERC7984, a confidential t
- **[ERC7984Freezable](./api/token#ERC7984Freezable)** - Extension with freezing mechanism
- **[ERC7984ObserverAccess](./api/token#ERC7984ObserverAccess)** - Extension allowing observers to access transfer amounts
- **[ERC7984Restricted](./api/token#ERC7984Restricted)** - Extension implementing user account transfer restrictions
-- **[ERC7984Votes](./api/token#ERC7984Votes)** - Extension supporting confidential votes tracking and delegation
+- **[ERC7984Omnibus](./api/token#ERC7984Omnibus)** - Extension for omnibus transfers with encrypted sub-account addresses
+- **[ERC7984Rwa](./api/token#ERC7984Rwa)** - Extension supporting confidential Real World Assets with compliance checks
- **[ERC7984Utils](./api/token#ERC7984Utils)** - Utility library for ERC7984 functions
### [Finance](./api/finance)
@@ -33,6 +34,7 @@ Core interfaces for interacting with confidential contracts.
- **[IERC7984](./api/interfaces#IERC7984)** - Interface for confidential fungible token standard
- **[IERC7984Receiver](./api/interfaces#IERC7984Receiver)** - Interface for contracts receiving ERC7984 transfers with callbacks
+- **[IERC7984Rwa](./api/interfaces#IERC7984Rwa)** - Interface for confidential RWA contracts
### [Utils](./api/utils)
Miscellaneous contracts and libraries with utility functions for confidential contracts.
diff --git a/content/confidential-contracts/api/interfaces.mdx b/content/confidential-contracts/api/interfaces.mdx
index cda9fb86..d706866a 100644
--- a/content/confidential-contracts/api/interfaces.mdx
+++ b/content/confidential-contracts/api/interfaces.mdx
@@ -5,27 +5,27 @@ description: "Smart contract interfaces utilities and implementations"
These interfaces are available as `.sol` files and are useful to interact with third party contracts that implement them.
-* [`IConfidentialFungibleToken`](#IConfidentialFungibleToken)
-* [`IConfidentialFungibleTokenReceiver`](#IConfidentialFungibleTokenReceiver)
+* [`IERC7984`](#IERC7984)
+* [`IERC7984Receiver`](#IERC7984Receiver)
## Core
-[`IConfidentialFungibleToken`](#IConfidentialFungibleToken)
-[`IConfidentialFungibleTokenReceiver`](#IConfidentialFungibleTokenReceiver)
+[`IERC7984`](#IERC7984)
+[`IERC7984Receiver`](#IERC7984Receiver)
-
+
```solidity
-import "@openzeppelin/confidential-contracts/interfaces/IConfidentialFungibleToken.sol";
+import "@openzeppelin/confidential-contracts/interfaces/IERC7984.sol";
```
Draft interface for a confidential fungible token standard utilizing the Zama FHE library.
@@ -33,42 +33,45 @@ Draft interface for a confidential fungible token standard utilizing the Zama FH
-Similar to #IConfidentialFungibleToken-confidentialTransfer-address-externalEuint64-bytes- but without an input proof. The caller
+Similar to #IERC7984-confidentialTransfer-address-externalEuint64-bytes- but without an input proof. The caller
*must* already be allowed by ACL for the given `amount`.
-
+
confidentialTransferFrom(address from, address to, externalEuint64 encryptedAmount, bytes inputProof) → euint64
-Similar to #IConfidentialFungibleToken-confidentialTransferFrom-address-address-externalEuint64-bytes- but without an input proof.
+Similar to #IERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes- but without an input proof.
The caller *must* be already allowed by ACL for the given `amount`.
-Similar to #IConfidentialFungibleToken-confidentialTransfer-address-externalEuint64-bytes- but with a callback to `to` after
+Similar to #IERC7984-confidentialTransfer-address-externalEuint64-bytes- but with a callback to `to` after
the transfer.
-The callback is made to the [`IConfidentialFungibleTokenReceiver.onConfidentialTransferReceived`](#IConfidentialFungibleTokenReceiver-onConfidentialTransferReceived-address-address-euint64-bytes-) function on the
+The callback is made to the [`IERC7984Receiver.onConfidentialTransferReceived`](#IERC7984Receiver-onConfidentialTransferReceived-address-address-euint64-bytes-) function on the
to address with the actual transferred amount (may differ from the given `encryptedAmount`) and the given
data `data`.
-
+
confidentialTransferAndCall(address to, euint64 amount, bytes data) → euint64 transferred
-Similar to #IConfidentialFungibleToken-confidentialTransfer-address-euint64- but with a callback to `to` after the transfer.
+Similar to #IERC7984-confidentialTransfer-address-euint64- but with a callback to `to` after the transfer.
-Similar to #IConfidentialFungibleToken-confidentialTransferFrom-address-address-externalEuint64-bytes- but with a callback to `to`
+Similar to #IERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes- but with a callback to `to`
after the transfer.
-Similar to #IConfidentialFungibleToken-confidentialTransferFrom-address-address-euint64- but with a callback to `to`
+Similar to #IERC7984-confidentialTransferFrom-address-address-euint64- but with a callback to `to`
after the transfer.
```solidity
-import "@openzeppelin/confidential-contracts/interfaces/IConfidentialFungibleTokenReceiver.sol";
+import "@openzeppelin/confidential-contracts/interfaces/IERC7984Receiver.sol";
```
-Interface for contracts that can receive confidential token transfers with a callback.
+Interface for contracts that can receive ERC7984 transfers with a callback.
+
+Returns the confidential available (unfrozen) balance of an account. Up to [`IERC7984.confidentialBalanceOf`](#IERC7984-confidentialBalanceOf-address-).
+
+
+
+Forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
+
+
+
+
diff --git a/content/confidential-contracts/api/token.mdx b/content/confidential-contracts/api/token.mdx
index d747f38f..b234ac54 100644
--- a/content/confidential-contracts/api/token.mdx
+++ b/content/confidential-contracts/api/token.mdx
@@ -3,38 +3,48 @@ title: "Token"
description: "Smart contract token utilities and implementations"
---
-This set of interfaces, contracts, and utilities are all related to the evolving Confidential Token Standard. The standard utilizes the Zama fhEVM co-processor for manipulating FHE values. All amounts are stored on-chain as ciphertext handles (or pointers) to values stored on the co-processor.
+This set of interfaces, contracts, and utilities are all related to `ERC7984`, an evolving confidential token standard. The standard utilizes the Zama fhEVM co-processor for manipulating FHE values. All amounts are stored on-chain as ciphertext handles (or pointers) to values stored on the co-processor.
-* [`ConfidentialFungibleToken`](#ConfidentialFungibleToken): Implementation of [`IConfidentialFungibleToken`](./interfaces#IConfidentialFungibleToken).
-* [`ConfidentialFungibleTokenERC20Wrapper`](#ConfidentialFungibleTokenERC20Wrapper): Extension of [`ConfidentialFungibleToken`](#ConfidentialFungibleToken) which wraps an `ERC20` into a confidential token. The wrapper allows for free conversion in both directions at a fixed rate.
-* [`ConfidentialFungibleTokenUtils`](#ConfidentialFungibleTokenUtils): A library that provides the on-transfer callback check used by [`ConfidentialFungibleToken`](#ConfidentialFungibleToken).
+* [`ERC7984`](#ERC7984): Implementation of [`IERC7984`](/confidential-contracts/api/interfaces#IERC7984).
+* [`ERC7984ERC20Wrapper`](#ERC7984ERC20Wrapper): Extension of [`ERC7984`](#ERC7984) which wraps an `ERC20` into a confidential token. The wrapper allows for free conversion in both directions at a fixed rate.
+* [`ERC7984Freezable`](#ERC7984Freezable): An extension of [`ERC7984`](#ERC7984), which allows accounts granted the "freezer" role to freeze and unfreeze tokens.
+* [`ERC7984ObserverAccess`](#ERC7984ObserverAccess): An extension of [`ERC7984`](#ERC7984), which allows each account to add an observer who is given access to their transfer and balance amounts.
+* [`ERC7984Restricted`](#ERC7984Restricted): An extension of [`ERC7984`](#ERC7984) that implements user account transfer restrictions.
+* [`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.
+* [`ERC7984Utils`](#ERC7984Utils): A library that provides the on-transfer callback check used by [`ERC7984`](#ERC7984).
## Core
-[`ConfidentialFungibleToken`](#ConfidentialFungibleToken)
+[`ERC7984`](#ERC7984)
## Extensions
-[`ConfidentialFungibleTokenERC20Wrapper`](#ConfidentialFungibleTokenERC20Wrapper)
+[`ERC7984ERC20Wrapper`](#ERC7984ERC20Wrapper)
+[`ERC7984Freezable`](#ERC7984Freezable)
+[`ERC7984ObserverAccess`](#ERC7984ObserverAccess)
+[`ERC7984Restricted`](#ERC7984Restricted)
+[`ERC7984Omnibus`](#ERC7984Omnibus)
+[`ERC7984Rwa`](#ERC7984Rwa)
## Utilities
-[`ConfidentialFungibleTokenUtils`](#ConfidentialFungibleTokenUtils)
+[`ERC7984Utils`](#ERC7984Utils)
-
+
```solidity
-import "@openzeppelin/confidential-contracts/token/ConfidentialFungibleToken.sol";
+import "@openzeppelin/confidential-contracts/token/ERC7984/ERC7984.sol";
```
-Reference implementation for [`IConfidentialFungibleToken`](./interfaces#IConfidentialFungibleToken).
+Reference implementation for [`IERC7984`](/confidential-contracts/api/interfaces#IERC7984).
This contract implements a fungible token where balances and transfers are encrypted using the Zama fhEVM,
providing confidentiality to users. Token amounts are stored as encrypted, unsigned integers (`euint64`)
@@ -51,67 +61,75 @@ Key features:
+
+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.
+
+
-Similar to interfaces#IConfidentialFungibleToken-confidentialTransfer-address-externalEuint64-bytes- but without an input proof. The caller
+Similar to interfaces#IERC7984-confidentialTransfer-address-externalEuint64-bytes- but without an input proof. The caller
*must* already be allowed by ACL for the given `amount`.
-Similar to interfaces#IConfidentialFungibleToken-confidentialTransferFrom-address-address-externalEuint64-bytes- but without an input proof.
+Similar to interfaces#IERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes- but without an input proof.
The caller *must* be already allowed by ACL for the given `amount`.
-Similar to interfaces#IConfidentialFungibleToken-confidentialTransfer-address-externalEuint64-bytes- but with a callback to `to` after
+Similar to interfaces#IERC7984-confidentialTransfer-address-externalEuint64-bytes- but with a callback to `to` after
the transfer.
-The callback is made to the [`IConfidentialFungibleTokenReceiver.onConfidentialTransferReceived`](./interfaces#IConfidentialFungibleTokenReceiver-onConfidentialTransferReceived-address-address-euint64-bytes-) function on the
+The callback is made to the [`IERC7984Receiver.onConfidentialTransferReceived`](/confidential-contracts/api/interfaces#IERC7984Receiver-onConfidentialTransferReceived-address-address-euint64-bytes-) function on the
to address with the actual transferred amount (may differ from the given `encryptedAmount`) and the given
data `data`.
-
+
confidentialTransferAndCall(address to, euint64 amount, bytes data) → euint64 transferred
-Similar to interfaces#IConfidentialFungibleToken-confidentialTransfer-address-euint64- but with a callback to `to` after the transfer.
+Similar to interfaces#IERC7984-confidentialTransfer-address-euint64- but with a callback to `to` after the transfer.
-Similar to interfaces#IConfidentialFungibleToken-confidentialTransferFrom-address-address-externalEuint64-bytes- but with a callback to `to`
+Similar to interfaces#IERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes- but with a callback to `to`
after the transfer.
-Similar to interfaces#IConfidentialFungibleToken-confidentialTransferFrom-address-address-euint64- but with a callback to `to`
+Similar to interfaces#IERC7984-confidentialTransferFrom-address-address-euint64- but with a callback to `to`
after the transfer.
-Discloses an encrypted amount `encryptedAmount` publicly via an [`IConfidentialFungibleToken.AmountDisclosed`](./interfaces#IConfidentialFungibleToken-AmountDisclosed-euint64-uint64-)
-event. The caller and this contract must be authorized to use the encrypted amount on the ACL.
+Starts the process to disclose an encrypted amount `encryptedAmount` publicly by making it
+publicly decryptable. Emits the [`ERC7984.AmountDiscloseRequested`](#ERC7984-AmountDiscloseRequested-euint64-address-) event.
-This is an asynchronous operation where the actual decryption happens off-chain and
-[`ConfidentialFungibleToken.finalizeDiscloseEncryptedAmount`](#ConfidentialFungibleToken-finalizeDiscloseEncryptedAmount-uint256-uint64-bytes---) is called with the result.
+Both `msg.sender` and `address(this)` must have permission to access the encrypted amount
+`encryptedAmount` to request disclosure of the encrypted amount `encryptedAmount`.
-Finalizes a disclose encrypted amount request.
+Publicly discloses an encrypted value with a given decryption proof. Emits the [`IERC7984.AmountDisclosed`](/confidential-contracts/api/interfaces#IERC7984-AmountDisclosed-euint64-uint64-) event.
+
+
+May not be tied to a prior request via [`ERC7984.requestDiscloseEncryptedAmount`](#ERC7984-requestDiscloseEncryptedAmount-euint64-).
+
```solidity
-import "@openzeppelin/confidential-contracts/token/extensions/ConfidentialFungibleTokenERC20Wrapper.sol";
+import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol";
```
-A wrapper contract built on top of [`ConfidentialFungibleToken`](#ConfidentialFungibleToken) that allows wrapping an `ERC20` token
-into a confidential fungible token. The wrapper contract implements the `IERC1363Receiver` interface
+A wrapper contract built on top of [`ERC7984`](#ERC7984) that allows wrapping an `ERC20` token
+into an `ERC7984` token. The wrapper contract implements the `IERC1363Receiver` interface
which allows users to transfer `ERC1363` tokens directly to the wrapper with a callback to wrap the tokens.
@@ -690,83 +752,94 @@ tokens such as fee-on-transfer or other deflationary-type tokens are not support
`ERC1363` callback function which wraps tokens to the address specified in `data` or
the address `from` (if no address is specified in `data`). This function refunds any excess tokens
-sent beyond the nearest multiple of [`ConfidentialFungibleTokenERC20Wrapper.rate`](#ConfidentialFungibleTokenERC20Wrapper-rate--). See [`ConfidentialFungibleTokenERC20Wrapper.wrap`](#ConfidentialFungibleTokenERC20Wrapper-wrap-address-uint256-) from more details on wrapping tokens.
+sent beyond the nearest multiple of [`ERC7984ERC20Wrapper.rate`](#ERC7984ERC20Wrapper-rate--). See [`ERC7984ERC20Wrapper.wrap`](#ERC7984ERC20Wrapper-wrap-address-uint256-) from more details on wrapping tokens.
Wraps amount `amount` of the underlying token into a confidential token and sends it to
-`to`. Tokens are exchanged at a fixed rate specified by [`ConfidentialFungibleTokenERC20Wrapper.rate`](#ConfidentialFungibleTokenERC20Wrapper-rate--) such that `amount / rate()` confidential
-tokens are sent. Amount transferred in is rounded down to the nearest multiple of [`ConfidentialFungibleTokenERC20Wrapper.rate`](#ConfidentialFungibleTokenERC20Wrapper-rate--).
+`to`. Tokens are exchanged at a fixed rate specified by [`ERC7984ERC20Wrapper.rate`](#ERC7984ERC20Wrapper-rate--) such that `amount / rate()` confidential
+tokens are sent. Amount transferred in is rounded down to the nearest multiple of [`ERC7984ERC20Wrapper.rate`](#ERC7984ERC20Wrapper-rate--).
@@ -880,8 +953,7 @@ Unwraps tokens from `from` and sends the underlying tokens to `to`. The caller m
or be an approved operator for `from`. `amount * rate()` underlying tokens are sent to `to`.
-This is an asynchronous function and waits for decryption to be completed off-chain before disbursing
-tokens.
+The unwrap request created by this function must be finalized by calling [`ERC7984ERC20Wrapper.finalizeUnwrap`](#ERC7984ERC20Wrapper-finalizeUnwrap-euint64-uint64-bytes-).
The caller *must* already be approved by ACL for the given `amount`.
@@ -890,49 +962,49 @@ The caller *must* already be approved by ACL for the given `amount`.
-
+
unwrap(address from, address to, externalEuint64 encryptedAmount, bytes inputProof)
-Variant of [`ConfidentialFungibleTokenERC20Wrapper.unwrap`](#ConfidentialFungibleTokenERC20Wrapper-unwrap-address-address-externalEuint64-bytes-) that passes an `inputProof` which approves the caller for the `encryptedAmount`
+Variant of [`ERC7984ERC20Wrapper.unwrap`](#ERC7984ERC20Wrapper-unwrap-address-address-externalEuint64-bytes-) that passes an `inputProof` which approves the caller for the `encryptedAmount`
in the ACL.
-Fills an unwrap request for a given request id related to a decrypted unwrap amount.
+Fills an unwrap request for a given cipher-text `burntAmount` with the `cleartextAmount` and `decryptionProof`.
Returns the default number of decimals of the underlying ERC-20 token that is being wrapped.
-Used as a default fallback when [`ConfidentialFungibleTokenERC20Wrapper._tryGetAssetDecimals`](#ConfidentialFungibleTokenERC20Wrapper-_tryGetAssetDecimals-contract-IERC20-) fails to fetch decimals of the underlying
+Used as a default fallback when [`ERC7984ERC20Wrapper._tryGetAssetDecimals`](#ERC7984ERC20Wrapper-_tryGetAssetDecimals-contract-IERC20-) fails to fetch decimals of the underlying
ERC-20 token.
+
+Returns the maximum number that will be used for [`IERC7984.decimals`](/confidential-contracts/api/interfaces#IERC7984-decimals--) by the wrapper.
+
+
+
+```solidity
+import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Freezable.sol";
+```
+
+Extension of [`ERC7984`](#ERC7984) that implements a confidential
+freezing mechanism that can be managed by an authorized account with
+[`IERC7984Rwa.setConfidentialFrozen`](/confidential-contracts/api/interfaces#IERC7984Rwa-setConfidentialFrozen-address-euint64-) functions.
+
+The freezing mechanism provides the guarantee to the contract owner
+(e.g. a DAO or a well-configured multisig) that a specific confidential
+amount of tokens held by an account won't be transferable until those
+tokens are unfrozen.
+
+Inspired by https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Freezable.sol
+
+
+
+See [`ERC7984._update`](#ERC7984-_update-address-address-euint64-).
+
+The `from` account must have sufficient unfrozen balance,
+otherwise 0 tokens are transferred.
+The default freezing behavior can be changed (for a pass-through for instance) by overriding
+[`ERC7984Freezable._confidentialAvailable`](#ERC7984Freezable-_confidentialAvailable-address-). The internal function is used for actual gating (not the public function)
+to avoid unnecessarily granting ACL allowances.
+
+
+
+```solidity
+import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984ObserverAccess.sol";
+```
+
+Extension of [`ERC7984`](#ERC7984) that allows each account to add a observer who is given
+permanent ACL access to its transfer and balance amounts. A observer can be added or removed at any point in time.
+
+
+
+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)`).
+
+
-Returns the maximum number that will be used for [`IConfidentialFungibleToken.decimals`](./interfaces#IConfidentialFungibleToken-decimals--) by the wrapper.
+
+
+```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.
+
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransfer-address-externalEuint64-bytes- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransfer-address-euint64- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransferFrom-address-address-externalEuint64-bytes- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransferFrom-address-address-euint64- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransferAndCall-address-externalEuint64-bytes-bytes- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransferAndCall-address-euint64-bytes- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Wraps the interfaces#IERC7984-confidentialTransferFromAndCall-address-address-euint64-bytes- function and emits the [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-) event.
+
+
+
+Handles the ACL allowances, does the transfer without a callback, and emits [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-).
+
+
+
+Handles the ACL allowances, does the transfer with a callback, and emits [`ERC7984Omnibus.OmnibusConfidentialTransfer`](#ERC7984Omnibus-OmnibusConfidentialTransfer-address-address-eaddress-eaddress-euint64-).
+
+
+
+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`.
+
+
+
+
+```solidity
+import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Restricted.sol";
+```
+
+Extension of [`ERC7984`](#ERC7984) that implements user account transfer restrictions through the
+[`IERC7984Rwa.isUserAllowed`](/confidential-contracts/api/interfaces#IERC7984Rwa-isUserAllowed-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 [`IERC7984Rwa.isUserAllowed`](/confidential-contracts/api/interfaces#IERC7984Rwa-isUserAllowed-address-) function acts as
+a blocklist. Developers can override [`IERC7984Rwa.isUserAllowed`](/confidential-contracts/api/interfaces#IERC7984Rwa-isUserAllowed-address-) to check that `restriction == ALLOWED`
+to implement an allowlist.
+
+
+
+Returns whether a user account is allowed to interact with the token.
+
+Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist).
+
+
+
+
+
+
+
+
+
_update(address from, address to, euint64 value) → euint64
+
+See [`ERC7984._update`](#ERC7984-_update-address-address-euint64-). Enforces transfer restrictions (excluding minting and burning).
+
+Requirements:
+
+* `from` must be allowed to transfer tokens (see [`IERC7984Rwa.isUserAllowed`](/confidential-contracts/api/interfaces#IERC7984Rwa-isUserAllowed-address-)).
+* `to` must be allowed to receive tokens (see [`IERC7984Rwa.isUserAllowed`](/confidential-contracts/api/interfaces#IERC7984Rwa-isUserAllowed-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-).
+
+
+
+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 restriction of the `to` account before a transfer.
+Working with [`ERC7984._update`](#ERC7984-_update-address-address-euint64-) function.
+
+
+
+```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.
+
+
+
+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.
+
+
+
+Returns whether a user account is allowed to interact with the token.
+
+Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist).
+
+
+
+
+
+
+
+
+
_update(address from, address to, euint64 encryptedAmount) → euint64
+
+Bypasses the `from` restriction check when performing a [`IERC7984Rwa.forceConfidentialTransferFrom`](/confidential-contracts/api/interfaces#IERC7984Rwa-forceConfidentialTransferFrom-address-address-euint64-).
+
+
+
+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.
```solidity
-import "@openzeppelin/confidential-contracts/token/extensions/ConfidentialFungibleTokenVotes.sol";
+import "@openzeppelin/confidential-contracts/token/ERC7984/extensions/ERC7984Votes.sol";
```
-Extension of [`ConfidentialFungibleToken`](#ConfidentialFungibleToken) supporting confidential votes tracking and delegation.
+Extension of [`ERC7984`](#ERC7984) supporting confidential votes tracking and delegation.
-The amount of confidential voting units an account has is equal to the confidential token balance of
+The amount of confidential voting units an account has is equal to the balance of
that account. Voing power is taken into account when an account delegates votes to itself or to another
account.
```solidity
-import "@openzeppelin/confidential-contracts/token/utils/ConfidentialFungibleTokenUtils.sol";
+import "@openzeppelin/confidential-contracts/token/ERC7984/utils/ERC7984Utils.sol";
```
-Library that provides common [`ConfidentialFungibleToken`](#ConfidentialFungibleToken) utility functions.
+Library that provides common [`ERC7984`](#ERC7984) utility functions.
Functions
-- [checkOnTransferReceived(operator, from, to, amount, data)](#ConfidentialFungibleTokenUtils-checkOnTransferReceived-address-address-address-euint64-bytes-)
+- [checkOnTransferReceived(operator, from, to, amount, data)](#ERC7984Utils-checkOnTransferReceived-address-address-address-euint64-bytes-)
Performs a transfer callback to the recipient of the transfer `to`. Should be invoked
-after all transfers "withCallback" on a [`ConfidentialFungibleToken`](#ConfidentialFungibleToken).
+after all transfers "withCallback" on a [`ERC7984`](#ERC7984).
The transfer callback is not invoked on the recipient if the recipient has no code (i.e. is an EOA). If the
recipient has non-zero code, it must implement
-[`IConfidentialFungibleTokenReceiver.onConfidentialTransferReceived`](./interfaces#IConfidentialFungibleTokenReceiver-onConfidentialTransferReceived-address-address-euint64-bytes-) and return an `ebool` indicating
-whether the transfer was accepted or not. If the `ebool` is `false`, the transfer will be reversed.
+[`IERC7984Receiver.onConfidentialTransferReceived`](/confidential-contracts/api/interfaces#IERC7984Receiver-onConfidentialTransferReceived-address-address-euint64-bytes-) and return an `ebool` indicating
+whether the transfer was accepted or not. If the `ebool` is `false`, the transfer function
+should try to refund the `from` address.
diff --git a/content/confidential-contracts/api/utils.mdx b/content/confidential-contracts/api/utils.mdx
index 600364e3..05cb49e4 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`
-
+
@@ -39,11 +39,18 @@ import "@openzeppelin/confidential-contracts/utils/FHESafeMath.sol";
Library providing safe arithmetic operations for encrypted values
to handle potential overflows in FHE operations.
+
+An uninitialized `euint64` value (equivalent to euint64.wrap(bytes32(0))) is evaluated as 0.
+This library will may return an uninitialized value if all inputs are uninitialized.
+
+
+
+Try to add `a` and `b`. If the operation is successful, `success` will be true and `res`
+will be the sum of `a` and `b`. Otherwise, `success` will be false, and `res` will be 0.
+
+
+
+
+
+
+
+
+
trySub(euint64 a, euint64 b) → ebool success, euint64 res
+
+Try to subtract `b` from `a`. If the operation is successful, `success` will be true and `res`
+will be `a - b`. Otherwise, `success` will be false, and `res` will be 0.
+
+
+
+
## `HandleAccessManager`
-
+
@@ -156,7 +199,7 @@ Unimplemented function that must revert if the message sender is not allowed to
## `CheckpointsConfidential`
-
+
@@ -504,7 +547,7 @@ Returns checkpoint at given position.
## `Checkpoints`
-
+
@@ -515,7 +558,7 @@ import "@openzeppelin/confidential-contracts/utils/structs/temporary-Checkpoints
```
This library defines the `Trace*` struct, for checkpointing values as they change at different points in
-time, and later looking up past values by block number. See [`VotesConfidential`](./governance#VotesConfidential) as an example.
+time, and later looking up past values by block number. See [`VotesConfidential`](/confidential-contracts/api/governance#VotesConfidential) as an example.
To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new
checkpoint for the current transaction block using the [`CheckpointsConfidential.push`](#CheckpointsConfidential-push-struct-CheckpointsConfidential-TraceEuint64-uint256-euint64-) function.
diff --git a/examples/SwapERC7984ToERC20.sol b/examples/SwapERC7984ToERC20.sol
index 920dc710..09d7fd38 100644
--- a/examples/SwapERC7984ToERC20.sol
+++ b/examples/SwapERC7984ToERC20.sol
@@ -1,15 +1,15 @@
// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.24;
+pragma solidity ^0.8.27;
import {FHE, externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol";
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC7984} from "@openzeppelin/confidential-contracts/interfaces/IERC7984.sol";
-contract SwapConfidentialToERC20 {
- error SwapConfidentialToERC20InvalidGatewayRequest(uint256 requestId);
+contract SwapERC7984ToERC20 {
+ error SwapERC7984ToERC20InvalidFinalization(euint64 amount);
- mapping(uint256 requestId => address) private _receivers;
+ mapping(euint64 amount => address) private _receivers;
IERC7984 private _fromToken;
IERC20 private _toToken;
@@ -23,22 +23,21 @@ contract SwapConfidentialToERC20 {
FHE.allowTransient(amount, address(_fromToken));
euint64 amountTransferred = _fromToken.confidentialTransferFrom(msg.sender, address(this), amount);
- bytes32[] memory cts = new bytes32[](1);
- cts[0] = euint64.unwrap(amountTransferred);
- uint256 requestID = FHE.requestDecryption(cts, this.finalizeSwap.selector);
-
- // register who is getting the tokens
- _receivers[requestID] = msg.sender;
+ FHE.makePubliclyDecryptable(amountTransferred);
+ _receivers[amountTransferred] = msg.sender;
}
- function finalizeSwap(uint256 requestID, uint64 amount, bytes[] memory signatures) public virtual {
- FHE.checkSignatures(requestID, signatures);
- address to = _receivers[requestID];
- require(to != address(0), SwapConfidentialToERC20InvalidGatewayRequest(requestID));
- delete _receivers[requestID];
+ function finalizeSwap(euint64 amount, uint64 cleartextAmount, bytes calldata decryptionProof) public virtual {
+ bytes32[] memory handles = new bytes32[](1);
+ handles[0] = euint64.unwrap(amount);
+
+ FHE.checkSignatures(handles, abi.encode(cleartextAmount), decryptionProof);
+ address to = _receivers[amount];
+ require(to != address(0), SwapERC7984ToERC20InvalidFinalization(amount));
+ delete _receivers[amount];
- if (amount != 0) {
- SafeERC20.safeTransfer(_toToken, to, amount);
+ if (cleartextAmount != 0) {
+ SafeERC20.safeTransfer(_toToken, to, cleartextAmount);
}
}
}