@openzeppelin/confidential-contracts 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/build/contracts/Checkpoints.json +2 -2
  2. package/build/contracts/CheckpointsConfidential.json +2 -2
  3. package/build/contracts/{ConfidentialFungibleToken.json → ERC7984.json} +87 -58
  4. package/build/contracts/{ConfidentialFungibleTokenERC20Wrapper.json → ERC7984ERC20Wrapper.json} +143 -59
  5. package/build/contracts/ERC7984Freezable.json +700 -0
  6. package/build/contracts/ERC7984ObserverAccess.json +710 -0
  7. package/build/contracts/ERC7984Omnibus.json +1028 -0
  8. package/build/contracts/ERC7984Restricted.json +711 -0
  9. package/build/contracts/ERC7984Rwa.json +1385 -0
  10. package/build/contracts/{ConfidentialFungibleTokenUtils.json → ERC7984Utils.json} +4 -4
  11. package/build/contracts/{ConfidentialFungibleTokenVotes.json → ERC7984Votes.json} +142 -113
  12. package/build/contracts/FHESafeMath.json +2 -2
  13. package/build/contracts/{IConfidentialFungibleToken.json → IERC7984.json} +26 -7
  14. package/build/contracts/{IConfidentialFungibleTokenReceiver.json → IERC7984Receiver.json} +2 -2
  15. package/build/contracts/IERC7984Rwa.json +797 -0
  16. package/build/contracts/VestingWalletConfidentialFactory.json +2 -2
  17. package/finance/ERC7821WithExecutor.sol +3 -4
  18. package/finance/VestingWalletCliffConfidential.sol +3 -4
  19. package/finance/VestingWalletConfidential.sol +8 -12
  20. package/finance/VestingWalletConfidentialFactory.sol +7 -12
  21. package/interfaces/{IConfidentialFungibleToken.sol → IERC7984.sol} +6 -5
  22. package/interfaces/{IConfidentialFungibleTokenReceiver.sol → IERC7984Receiver.sol} +3 -3
  23. package/interfaces/IERC7984Rwa.sol +63 -0
  24. package/package.json +4 -4
  25. package/token/{ConfidentialFungibleToken.sol → ERC7984/ERC7984.sol} +81 -82
  26. package/token/{extensions/ConfidentialFungibleTokenERC20Wrapper.sol → ERC7984/extensions/ERC7984ERC20Wrapper.sol} +40 -35
  27. package/token/ERC7984/extensions/ERC7984Freezable.sol +75 -0
  28. package/token/ERC7984/extensions/ERC7984ObserverAccess.sol +63 -0
  29. package/token/ERC7984/extensions/ERC7984Omnibus.sol +209 -0
  30. package/token/ERC7984/extensions/ERC7984Restricted.sol +110 -0
  31. package/token/ERC7984/extensions/ERC7984Rwa.sol +248 -0
  32. package/token/{extensions/ConfidentialFungibleTokenVotes.sol → ERC7984/extensions/ERC7984Votes.sol} +8 -14
  33. package/token/{utils/ConfidentialFungibleTokenUtils.sol → ERC7984/utils/ERC7984Utils.sol} +14 -13
  34. package/utils/FHESafeMath.sol +45 -7
  35. package/utils/structs/temporary-Checkpoints.sol +2 -2
@@ -0,0 +1,209 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Omnibus.sol)
3
+
4
+ pragma solidity ^0.8.27;
5
+
6
+ import {FHE, euint64, externalEuint64, externalEaddress, eaddress} from "@fhevm/solidity/lib/FHE.sol";
7
+ import {ERC7984} from "../ERC7984.sol";
8
+
9
+ /**
10
+ * @dev Extension of {ERC7984} that emits additional events for omnibus transfers.
11
+ * These events contain encrypted addresses for the sub-account sender and recipient.
12
+ *
13
+ * NOTE: There is no onchain accounting for sub-accounts--integrators must track sub-account
14
+ * balances externally.
15
+ */
16
+ abstract contract ERC7984Omnibus is ERC7984 {
17
+ /**
18
+ * @dev Emitted when a confidential transfer is made representing the onchain settlement of
19
+ * an omnibus transfer from `sender` to `recipient` of amount `amount`. Settlement occurs between
20
+ * `omnibusFrom` and `omnibusTo` and is represented in a matching {IERC7984-ConfidentialTransfer} event.
21
+ *
22
+ * NOTE: `omnibusFrom` and `omnibusTo` get permanent ACL allowances for `sender` and `recipient`.
23
+ */
24
+ event OmnibusConfidentialTransfer(
25
+ address indexed omnibusFrom,
26
+ address indexed omnibusTo,
27
+ eaddress sender,
28
+ eaddress indexed recipient,
29
+ euint64 amount
30
+ );
31
+
32
+ /**
33
+ * @dev The caller `user` does not have access to the encrypted address `addr`.
34
+ *
35
+ * NOTE: Try using the equivalent transfer function with an input proof.
36
+ */
37
+ error ERC7984UnauthorizedUseOfEncryptedAddress(eaddress addr, address user);
38
+
39
+ /// @dev Wraps the {confidentialTransfer-address-externalEuint64-bytes} function and emits the {OmnibusConfidentialTransfer} event.
40
+ function confidentialTransferOmnibus(
41
+ address omnibusTo,
42
+ externalEaddress externalSender,
43
+ externalEaddress externalRecipient,
44
+ externalEuint64 externalAmount,
45
+ bytes calldata inputProof
46
+ ) public virtual returns (euint64) {
47
+ return
48
+ confidentialTransferFromOmnibus(
49
+ msg.sender,
50
+ omnibusTo,
51
+ externalSender,
52
+ externalRecipient,
53
+ externalAmount,
54
+ inputProof
55
+ );
56
+ }
57
+
58
+ /// @dev Wraps the {confidentialTransfer-address-euint64} function and emits the {OmnibusConfidentialTransfer} event.
59
+ function confidentialTransferOmnibus(
60
+ address omnibusTo,
61
+ eaddress sender,
62
+ eaddress recipient,
63
+ euint64 amount
64
+ ) public virtual returns (euint64) {
65
+ return confidentialTransferFromOmnibus(msg.sender, omnibusTo, sender, recipient, amount);
66
+ }
67
+
68
+ /// @dev Wraps the {confidentialTransferFrom-address-address-externalEuint64-bytes} function and emits the {OmnibusConfidentialTransfer} event.
69
+ function confidentialTransferFromOmnibus(
70
+ address omnibusFrom,
71
+ address omnibusTo,
72
+ externalEaddress externalSender,
73
+ externalEaddress externalRecipient,
74
+ externalEuint64 externalAmount,
75
+ bytes calldata inputProof
76
+ ) public virtual returns (euint64) {
77
+ eaddress sender = FHE.fromExternal(externalSender, inputProof);
78
+ eaddress recipient = FHE.fromExternal(externalRecipient, inputProof);
79
+ euint64 amount = FHE.fromExternal(externalAmount, inputProof);
80
+
81
+ return _confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount);
82
+ }
83
+
84
+ /// @dev Wraps the {confidentialTransferFrom-address-address-euint64} function and emits the {OmnibusConfidentialTransfer} event.
85
+ function confidentialTransferFromOmnibus(
86
+ address omnibusFrom,
87
+ address omnibusTo,
88
+ eaddress sender,
89
+ eaddress recipient,
90
+ euint64 amount
91
+ ) public virtual returns (euint64) {
92
+ require(FHE.isAllowed(sender, msg.sender), ERC7984UnauthorizedUseOfEncryptedAddress(sender, msg.sender));
93
+ require(FHE.isAllowed(recipient, msg.sender), ERC7984UnauthorizedUseOfEncryptedAddress(recipient, msg.sender));
94
+
95
+ return _confidentialTransferFromOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount);
96
+ }
97
+
98
+ /// @dev Wraps the {confidentialTransferAndCall-address-externalEuint64-bytes-bytes} function and emits the {OmnibusConfidentialTransfer} event.
99
+ function confidentialTransferAndCallOmnibus(
100
+ address omnibusTo,
101
+ externalEaddress externalSender,
102
+ externalEaddress externalRecipient,
103
+ externalEuint64 externalAmount,
104
+ bytes calldata inputProof,
105
+ bytes calldata data
106
+ ) public virtual returns (euint64) {
107
+ return
108
+ confidentialTransferFromAndCallOmnibus(
109
+ msg.sender,
110
+ omnibusTo,
111
+ externalSender,
112
+ externalRecipient,
113
+ externalAmount,
114
+ inputProof,
115
+ data
116
+ );
117
+ }
118
+
119
+ /// @dev Wraps the {confidentialTransferAndCall-address-euint64-bytes} function and emits the {OmnibusConfidentialTransfer} event.
120
+ function confidentialTransferAndCallOmnibus(
121
+ address omnibusTo,
122
+ eaddress sender,
123
+ eaddress recipient,
124
+ euint64 amount,
125
+ bytes calldata data
126
+ ) public virtual returns (euint64) {
127
+ return confidentialTransferFromAndCallOmnibus(msg.sender, omnibusTo, sender, recipient, amount, data);
128
+ }
129
+
130
+ /// @dev Wraps the {confidentialTransferFromAndCall-address-address-externalEuint64-bytes-bytes} function and emits the {OmnibusConfidentialTransfer} event.
131
+ function confidentialTransferFromAndCallOmnibus(
132
+ address omnibusFrom,
133
+ address omnibusTo,
134
+ externalEaddress externalSender,
135
+ externalEaddress externalRecipient,
136
+ externalEuint64 externalAmount,
137
+ bytes calldata inputProof,
138
+ bytes calldata data
139
+ ) public virtual returns (euint64) {
140
+ eaddress sender = FHE.fromExternal(externalSender, inputProof);
141
+ eaddress recipient = FHE.fromExternal(externalRecipient, inputProof);
142
+ euint64 amount = FHE.fromExternal(externalAmount, inputProof);
143
+
144
+ return _confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data);
145
+ }
146
+
147
+ /// @dev Wraps the {confidentialTransferFromAndCall-address-address-euint64-bytes} function and emits the {OmnibusConfidentialTransfer} event.
148
+ function confidentialTransferFromAndCallOmnibus(
149
+ address omnibusFrom,
150
+ address omnibusTo,
151
+ eaddress sender,
152
+ eaddress recipient,
153
+ euint64 amount,
154
+ bytes calldata data
155
+ ) public virtual returns (euint64) {
156
+ require(FHE.isAllowed(sender, msg.sender), ERC7984UnauthorizedUseOfEncryptedAddress(sender, msg.sender));
157
+ require(FHE.isAllowed(recipient, msg.sender), ERC7984UnauthorizedUseOfEncryptedAddress(recipient, msg.sender));
158
+
159
+ return _confidentialTransferFromAndCallOmnibus(omnibusFrom, omnibusTo, sender, recipient, amount, data);
160
+ }
161
+
162
+ /// @dev Handles the ACL allowances, does the transfer without a callback, and emits {OmnibusConfidentialTransfer}.
163
+ function _confidentialTransferFromOmnibus(
164
+ address omnibusFrom,
165
+ address omnibusTo,
166
+ eaddress sender,
167
+ eaddress recipient,
168
+ euint64 amount
169
+ ) internal virtual returns (euint64) {
170
+ FHE.allowThis(sender);
171
+ FHE.allow(sender, omnibusFrom);
172
+ FHE.allow(sender, omnibusTo);
173
+
174
+ FHE.allowThis(recipient);
175
+ FHE.allow(recipient, omnibusFrom);
176
+ FHE.allow(recipient, omnibusTo);
177
+
178
+ euint64 transferred = confidentialTransferFrom(omnibusFrom, omnibusTo, amount);
179
+ emit OmnibusConfidentialTransfer(omnibusFrom, omnibusTo, sender, recipient, transferred);
180
+ return transferred;
181
+ }
182
+
183
+ /// @dev Handles the ACL allowances, does the transfer with a callback, and emits {OmnibusConfidentialTransfer}.
184
+ function _confidentialTransferFromAndCallOmnibus(
185
+ address omnibusFrom,
186
+ address omnibusTo,
187
+ eaddress sender,
188
+ eaddress recipient,
189
+ euint64 amount,
190
+ bytes calldata data
191
+ ) internal virtual returns (euint64) {
192
+ FHE.allowThis(sender);
193
+ FHE.allow(sender, omnibusFrom);
194
+ FHE.allow(sender, omnibusTo);
195
+
196
+ FHE.allowThis(recipient);
197
+ FHE.allow(recipient, omnibusFrom);
198
+ FHE.allow(recipient, omnibusTo);
199
+
200
+ euint64 transferred = confidentialTransferFromAndCall(omnibusFrom, omnibusTo, amount, data);
201
+
202
+ FHE.allowThis(transferred);
203
+ FHE.allow(transferred, omnibusFrom);
204
+ FHE.allow(transferred, omnibusTo);
205
+
206
+ emit OmnibusConfidentialTransfer(omnibusFrom, omnibusTo, sender, recipient, transferred);
207
+ return transferred;
208
+ }
209
+ }
@@ -0,0 +1,110 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Restricted.sol)
3
+
4
+ pragma solidity ^0.8.27;
5
+
6
+ import {ERC7984, euint64} from "../ERC7984.sol";
7
+
8
+ /**
9
+ * @dev Extension of {ERC7984} that implements user account transfer restrictions through the
10
+ * {isUserAllowed} function. Inspired by
11
+ * https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Restricted.sol.
12
+ *
13
+ * By default, each account has no explicit restriction. The {isUserAllowed} function acts as
14
+ * a blocklist. Developers can override {isUserAllowed} to check that `restriction == ALLOWED`
15
+ * to implement an allowlist.
16
+ */
17
+ abstract contract ERC7984Restricted is ERC7984 {
18
+ enum Restriction {
19
+ DEFAULT, // User has no explicit restriction
20
+ BLOCKED, // User is explicitly blocked
21
+ ALLOWED // User is explicitly allowed
22
+ }
23
+
24
+ mapping(address account => Restriction) private _restrictions;
25
+
26
+ /// @dev Emitted when a user account's restriction is updated.
27
+ event UserRestrictionUpdated(address indexed account, Restriction restriction);
28
+
29
+ /// @dev The operation failed because the user account is restricted.
30
+ error UserRestricted(address account);
31
+
32
+ /// @dev Returns the restriction of a user account.
33
+ function getRestriction(address account) public view virtual returns (Restriction) {
34
+ return _restrictions[account];
35
+ }
36
+
37
+ /**
38
+ * @dev Returns whether a user account is allowed to interact with the token.
39
+ *
40
+ * Default implementation only disallows explicitly BLOCKED accounts (i.e. a blocklist).
41
+ */
42
+ function isUserAllowed(address account) public view virtual returns (bool) {
43
+ return getRestriction(account) != Restriction.BLOCKED; // i.e. DEFAULT && ALLOWED
44
+ }
45
+
46
+ /**
47
+ * @dev See {ERC7984-_update}. Enforces transfer restrictions (excluding minting and burning).
48
+ *
49
+ * Requirements:
50
+ *
51
+ * * `from` must be allowed to transfer tokens (see {isUserAllowed}).
52
+ * * `to` must be allowed to receive tokens (see {isUserAllowed}).
53
+ *
54
+ * The default restriction behavior can be changed (for a pass-through for instance) by overriding
55
+ * {_checkSenderRestriction} and/or {_checkRecipientRestriction}.
56
+ */
57
+ function _update(address from, address to, euint64 value) internal virtual override returns (euint64) {
58
+ _checkSenderRestriction(from);
59
+ _checkRecipientRestriction(to);
60
+ return super._update(from, to, value);
61
+ }
62
+
63
+ /// @dev Updates the restriction of a user account.
64
+ function _setRestriction(address account, Restriction restriction) internal virtual {
65
+ if (getRestriction(account) != restriction) {
66
+ _restrictions[account] = restriction;
67
+ emit UserRestrictionUpdated(account, restriction);
68
+ } // no-op if restriction is unchanged
69
+ }
70
+
71
+ /// @dev Convenience function to block a user account (set to BLOCKED).
72
+ function _blockUser(address account) internal virtual {
73
+ _setRestriction(account, Restriction.BLOCKED);
74
+ }
75
+
76
+ /// @dev Convenience function to allow a user account (set to ALLOWED).
77
+ function _allowUser(address account) internal virtual {
78
+ _setRestriction(account, Restriction.ALLOWED);
79
+ }
80
+
81
+ /// @dev Convenience function to reset a user account to default restriction.
82
+ function _resetUser(address account) internal virtual {
83
+ _setRestriction(account, Restriction.DEFAULT);
84
+ }
85
+
86
+ /// @dev Checks if a user account is restricted. Reverts with {UserRestricted} if so.
87
+ function _checkRestriction(address account) internal view virtual {
88
+ require(isUserAllowed(account), UserRestricted(account));
89
+ }
90
+
91
+ /**
92
+ * @dev Internal function which checks restriction of the `from` account before a transfer.
93
+ * Working with {_update} function.
94
+ */
95
+ function _checkSenderRestriction(address account) internal view virtual {
96
+ if (account != address(0)) {
97
+ _checkRestriction(account); // Not minting
98
+ }
99
+ }
100
+
101
+ /**
102
+ * @dev Internal function which checks restriction of the `to` account before a transfer.
103
+ * Working with {_update} function.
104
+ */
105
+ function _checkRecipientRestriction(address account) internal view virtual {
106
+ if (account != address(0)) {
107
+ _checkRestriction(account); // Not burning
108
+ }
109
+ }
110
+ }
@@ -0,0 +1,248 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Rwa.sol)
3
+
4
+ pragma solidity ^0.8.27;
5
+
6
+ import {FHE, externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol";
7
+ import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
8
+ import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
9
+ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
10
+ import {Multicall} from "@openzeppelin/contracts/utils/Multicall.sol";
11
+ import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
12
+ import {IERC7984} from "./../../../interfaces/IERC7984.sol";
13
+ import {IERC7984Rwa} from "./../../../interfaces/IERC7984Rwa.sol";
14
+ import {ERC7984} from "./../ERC7984.sol";
15
+ import {ERC7984Freezable} from "./ERC7984Freezable.sol";
16
+ import {ERC7984Restricted} from "./ERC7984Restricted.sol";
17
+
18
+ /**
19
+ * @dev Extension of {ERC7984} that supports confidential Real World Assets (RWAs).
20
+ * This interface provides compliance checks, transfer controls and enforcement actions.
21
+ */
22
+ abstract contract ERC7984Rwa is IERC7984Rwa, ERC7984Freezable, ERC7984Restricted, Pausable, Multicall, AccessControl {
23
+ /**
24
+ * @dev Accounts granted the agent role have the following permissioned abilities:
25
+ *
26
+ * - Mint/Burn to/from a given address (does not require permission)
27
+ * - Force transfer from a given address (does not require permission)
28
+ * - Bypasses pause and restriction checks (not frozen)
29
+ * - Pause/Unpause the contract
30
+ * - Block/Unblock a given account
31
+ * - Set frozen amount of tokens for a given account.
32
+ */
33
+ bytes32 public constant AGENT_ROLE = keccak256("AGENT_ROLE");
34
+
35
+ /// @dev Checks if the sender is an admin.
36
+ modifier onlyAdmin() {
37
+ _checkRole(DEFAULT_ADMIN_ROLE);
38
+ _;
39
+ }
40
+
41
+ /// @dev Checks if the sender is an agent.
42
+ modifier onlyAgent() {
43
+ _checkRole(AGENT_ROLE);
44
+ _;
45
+ }
46
+
47
+ constructor(address admin) {
48
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
49
+ }
50
+
51
+ /// @inheritdoc ERC165
52
+ function supportsInterface(
53
+ bytes4 interfaceId
54
+ ) public view virtual override(IERC165, ERC7984, AccessControl) returns (bool) {
55
+ return interfaceId == type(IERC7984Rwa).interfaceId || super.supportsInterface(interfaceId);
56
+ }
57
+
58
+ /// @dev Returns true if has admin role, false otherwise.
59
+ function isAdmin(address account) public view virtual returns (bool) {
60
+ return hasRole(DEFAULT_ADMIN_ROLE, account);
61
+ }
62
+
63
+ /// @dev Returns true if agent, false otherwise.
64
+ function isAgent(address account) public view virtual returns (bool) {
65
+ return hasRole(AGENT_ROLE, account);
66
+ }
67
+
68
+ /// @dev Adds agent.
69
+ function addAgent(address account) public virtual onlyAdmin {
70
+ _grantRole(AGENT_ROLE, account);
71
+ }
72
+
73
+ /// @dev Removes agent.
74
+ function removeAgent(address account) public virtual onlyAdmin {
75
+ _revokeRole(AGENT_ROLE, account);
76
+ }
77
+
78
+ /// @dev Pauses contract.
79
+ function pause() public virtual onlyAgent {
80
+ _pause();
81
+ }
82
+
83
+ /// @dev Unpauses contract.
84
+ function unpause() public virtual onlyAgent {
85
+ _unpause();
86
+ }
87
+
88
+ /// @dev Blocks a user account.
89
+ function blockUser(address account) public virtual onlyAgent {
90
+ _blockUser(account);
91
+ }
92
+
93
+ /// @dev Unblocks a user account.
94
+ function unblockUser(address account) public virtual onlyAgent {
95
+ _resetUser(account);
96
+ }
97
+
98
+ /// @dev Sets confidential frozen for an account with proof.
99
+ function setConfidentialFrozen(
100
+ address account,
101
+ externalEuint64 encryptedAmount,
102
+ bytes calldata inputProof
103
+ ) public virtual onlyAgent {
104
+ _setConfidentialFrozen(account, FHE.fromExternal(encryptedAmount, inputProof));
105
+ }
106
+
107
+ /// @dev Sets confidential frozen for an account.
108
+ function setConfidentialFrozen(address account, euint64 encryptedAmount) public virtual onlyAgent {
109
+ require(
110
+ FHE.isAllowed(encryptedAmount, msg.sender),
111
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
112
+ );
113
+ _setConfidentialFrozen(account, encryptedAmount);
114
+ }
115
+
116
+ /// @dev Mints confidential amount of tokens to account with proof.
117
+ function confidentialMint(
118
+ address to,
119
+ externalEuint64 encryptedAmount,
120
+ bytes calldata inputProof
121
+ ) public virtual onlyAgent returns (euint64) {
122
+ euint64 mintedAmount = _mint(to, FHE.fromExternal(encryptedAmount, inputProof));
123
+ FHE.allow(mintedAmount, msg.sender);
124
+ return mintedAmount;
125
+ }
126
+
127
+ /// @dev Mints confidential amount of tokens to account.
128
+ function confidentialMint(address to, euint64 encryptedAmount) public virtual onlyAgent returns (euint64) {
129
+ require(
130
+ FHE.isAllowed(encryptedAmount, msg.sender),
131
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
132
+ );
133
+ euint64 mintedAmount = _mint(to, encryptedAmount);
134
+ FHE.allow(mintedAmount, msg.sender);
135
+ return mintedAmount;
136
+ }
137
+
138
+ /// @dev Burns confidential amount of tokens from account with proof.
139
+ function confidentialBurn(
140
+ address account,
141
+ externalEuint64 encryptedAmount,
142
+ bytes calldata inputProof
143
+ ) public virtual onlyAgent returns (euint64) {
144
+ euint64 burntAmount = _burn(account, FHE.fromExternal(encryptedAmount, inputProof));
145
+ FHE.allow(burntAmount, msg.sender);
146
+ return burntAmount;
147
+ }
148
+
149
+ /// @dev Burns confidential amount of tokens from account.
150
+ function confidentialBurn(address account, euint64 encryptedAmount) public virtual onlyAgent returns (euint64) {
151
+ require(
152
+ FHE.isAllowed(encryptedAmount, msg.sender),
153
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
154
+ );
155
+ euint64 burntAmount = _burn(account, encryptedAmount);
156
+ FHE.allow(burntAmount, msg.sender);
157
+ return burntAmount;
158
+ }
159
+
160
+ /// @dev Variant of {forceConfidentialTransferFrom-address-address-euint64} with an input proof.
161
+ function forceConfidentialTransferFrom(
162
+ address from,
163
+ address to,
164
+ externalEuint64 encryptedAmount,
165
+ bytes calldata inputProof
166
+ ) public virtual onlyAgent returns (euint64) {
167
+ return _forceUpdate(from, to, FHE.fromExternal(encryptedAmount, inputProof));
168
+ }
169
+
170
+ /**
171
+ * @dev Force transfer callable by the role {AGENT_ROLE} which transfers tokens from `from` to `to` and
172
+ * bypasses the {ERC7984Restricted} (only on from) and https://docs.openzeppelin.com/contracts/api/utils#pausable[`++Pausable++`]
173
+ * checks. Frozen tokens are not transferred and must be unfrozen first.
174
+ */
175
+ function forceConfidentialTransferFrom(
176
+ address from,
177
+ address to,
178
+ euint64 encryptedAmount
179
+ ) public virtual onlyAgent returns (euint64 transferred) {
180
+ require(
181
+ FHE.isAllowed(encryptedAmount, msg.sender),
182
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
183
+ );
184
+ return _forceUpdate(from, to, encryptedAmount);
185
+ }
186
+
187
+ /// @inheritdoc ERC7984Freezable
188
+ function confidentialAvailable(
189
+ address account
190
+ ) public virtual override(IERC7984Rwa, ERC7984Freezable) returns (euint64) {
191
+ return super.confidentialAvailable(account);
192
+ }
193
+
194
+ /// @inheritdoc ERC7984Freezable
195
+ function confidentialFrozen(
196
+ address account
197
+ ) public view virtual override(IERC7984Rwa, ERC7984Freezable) returns (euint64) {
198
+ return super.confidentialFrozen(account);
199
+ }
200
+
201
+ /// @inheritdoc Pausable
202
+ function paused() public view virtual override(IERC7984Rwa, Pausable) returns (bool) {
203
+ return super.paused();
204
+ }
205
+
206
+ /// @inheritdoc ERC7984Restricted
207
+ function isUserAllowed(
208
+ address account
209
+ ) public view virtual override(IERC7984Rwa, ERC7984Restricted) returns (bool) {
210
+ return super.isUserAllowed(account);
211
+ }
212
+
213
+ /// @dev Internal function which updates confidential balances while performing frozen and restriction compliance checks.
214
+ function _update(
215
+ address from,
216
+ address to,
217
+ euint64 encryptedAmount
218
+ ) internal virtual override(ERC7984Freezable, ERC7984Restricted) whenNotPaused returns (euint64) {
219
+ // frozen and restriction checks performed through inheritance
220
+ return super._update(from, to, encryptedAmount);
221
+ }
222
+
223
+ /// @dev Internal function which forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
224
+ function _forceUpdate(address from, address to, euint64 encryptedAmount) internal virtual returns (euint64) {
225
+ // bypassing `from` restriction check with {_checkSenderRestriction}. Still performing `to` restriction check.
226
+ // bypassing paused state by directly calling `super._update`
227
+ euint64 transferred = super._update(from, to, encryptedAmount);
228
+ FHE.allow(transferred, msg.sender);
229
+ return transferred;
230
+ }
231
+
232
+ /**
233
+ * @dev Bypasses the `from` restriction check when performing a {forceConfidentialTransferFrom}.
234
+ */
235
+ function _checkSenderRestriction(address account) internal view override {
236
+ if (_isForceTransfer()) {
237
+ return;
238
+ }
239
+ super._checkSenderRestriction(account);
240
+ }
241
+
242
+ /// @dev Private function which checks if the called function is a {forceConfidentialTransferFrom}.
243
+ function _isForceTransfer() private pure returns (bool) {
244
+ return
245
+ msg.sig == 0x6c9c3c85 || // bytes4(keccak256("forceConfidentialTransferFrom(address,address,bytes32)"))
246
+ msg.sig == 0x44fd6e40; // bytes4(keccak256("forceConfidentialTransferFrom(address,address,bytes32,bytes)"))
247
+ }
248
+ }
@@ -1,27 +1,21 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0) (token/extensions/ConfidentialFungibleTokenVotes.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Votes.sol)
3
3
  pragma solidity ^0.8.27;
4
4
 
5
5
  import {euint64} from "@fhevm/solidity/lib/FHE.sol";
6
- import {VotesConfidential} from "./../../governance/utils/VotesConfidential.sol";
7
- import {ConfidentialFungibleToken} from "./../ConfidentialFungibleToken.sol";
6
+ import {VotesConfidential} from "../../../governance/utils/VotesConfidential.sol";
7
+ import {ERC7984} from "./../ERC7984.sol";
8
8
 
9
9
  /**
10
- * @dev Extension of {ConfidentialFungibleToken} supporting confidential votes tracking and delegation.
10
+ * @dev Extension of {ERC7984} supporting confidential votes tracking and delegation.
11
11
  *
12
- * The amount of confidential voting units an account has is equal to the confidential token balance of
12
+ * The amount of confidential voting units an account has is equal to the balance of
13
13
  * that account. Voing power is taken into account when an account delegates votes to itself or to another
14
14
  * account.
15
15
  */
16
- abstract contract ConfidentialFungibleTokenVotes is ConfidentialFungibleToken, VotesConfidential {
17
- /// @inheritdoc ConfidentialFungibleToken
18
- function confidentialTotalSupply()
19
- public
20
- view
21
- virtual
22
- override(VotesConfidential, ConfidentialFungibleToken)
23
- returns (euint64)
24
- {
16
+ abstract contract ERC7984Votes is ERC7984, VotesConfidential {
17
+ /// @inheritdoc ERC7984
18
+ function confidentialTotalSupply() public view virtual override(VotesConfidential, ERC7984) returns (euint64) {
25
19
  return super.confidentialTotalSupply();
26
20
  }
27
21
 
@@ -1,22 +1,23 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0) (token/utils/ConfidentialFungibleTokenUtils.sol)
3
- pragma solidity ^0.8.24;
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/utils/ERC7984Utils.sol)
3
+ pragma solidity ^0.8.27;
4
4
 
5
5
  import {FHE, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
6
6
 
7
- import {IConfidentialFungibleTokenReceiver} from "../../interfaces/IConfidentialFungibleTokenReceiver.sol";
8
- import {ConfidentialFungibleToken} from "../ConfidentialFungibleToken.sol";
7
+ import {IERC7984Receiver} from "../../../interfaces/IERC7984Receiver.sol";
8
+ import {ERC7984} from "../ERC7984.sol";
9
9
 
10
- /// @dev Library that provides common {ConfidentialFungibleToken} utility functions.
11
- library ConfidentialFungibleTokenUtils {
10
+ /// @dev Library that provides common {ERC7984} utility functions.
11
+ library ERC7984Utils {
12
12
  /**
13
13
  * @dev Performs a transfer callback to the recipient of the transfer `to`. Should be invoked
14
- * after all transfers "withCallback" on a {ConfidentialFungibleToken}.
14
+ * after all transfers "withCallback" on a {ERC7984}.
15
15
  *
16
16
  * The transfer callback is not invoked on the recipient if the recipient has no code (i.e. is an EOA). If the
17
17
  * recipient has non-zero code, it must implement
18
- * {IConfidentialFungibleTokenReceiver-onConfidentialTransferReceived} and return an `ebool` indicating
19
- * whether the transfer was accepted or not. If the `ebool` is `false`, the transfer will be reversed.
18
+ * {IERC7984Receiver-onConfidentialTransferReceived} and return an `ebool` indicating
19
+ * whether the transfer was accepted or not. If the `ebool` is `false`, the transfer function
20
+ * should try to refund the `from` address.
20
21
  */
21
22
  function checkOnTransferReceived(
22
23
  address operator,
@@ -26,13 +27,13 @@ library ConfidentialFungibleTokenUtils {
26
27
  bytes calldata data
27
28
  ) internal returns (ebool) {
28
29
  if (to.code.length > 0) {
29
- try
30
- IConfidentialFungibleTokenReceiver(to).onConfidentialTransferReceived(operator, from, amount, data)
31
- returns (ebool retval) {
30
+ try IERC7984Receiver(to).onConfidentialTransferReceived(operator, from, amount, data) returns (
31
+ ebool retval
32
+ ) {
32
33
  return retval;
33
34
  } catch (bytes memory reason) {
34
35
  if (reason.length == 0) {
35
- revert ConfidentialFungibleToken.ConfidentialFungibleTokenInvalidReceiver(to);
36
+ revert ERC7984.ERC7984InvalidReceiver(to);
36
37
  } else {
37
38
  assembly ("memory-safe") {
38
39
  revert(add(32, reason), mload(reason))