@openzeppelin/confidential-contracts 0.2.0-rc.2 → 0.3.0-rc.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 (44) hide show
  1. package/build/contracts/Checkpoints.json +2 -2
  2. package/build/contracts/CheckpointsConfidential.json +3 -9
  3. package/build/contracts/{ConfidentialFungibleToken.json → ERC7984.json} +28 -33
  4. package/build/contracts/{ConfidentialFungibleTokenERC20Wrapper.json → ERC7984ERC20Wrapper.json} +34 -39
  5. package/build/contracts/ERC7984Freezable.json +666 -0
  6. package/build/contracts/ERC7984ObserverAccess.json +676 -0
  7. package/build/contracts/ERC7984Omnibus.json +994 -0
  8. package/build/contracts/ERC7984Restricted.json +677 -0
  9. package/build/contracts/ERC7984Rwa.json +1370 -0
  10. package/build/contracts/{ConfidentialFungibleTokenUtils.json → ERC7984Utils.json} +4 -4
  11. package/build/contracts/{ConfidentialFungibleTokenVotes.json → ERC7984Votes.json} +99 -81
  12. package/build/contracts/{TFHESafeMath.json → FHESafeMath.json} +4 -4
  13. package/build/contracts/HandleAccessManager.json +34 -0
  14. package/build/contracts/{IConfidentialFungibleToken.json → IERC7984.json} +15 -15
  15. package/build/contracts/{IConfidentialFungibleTokenReceiver.json → IERC7984Receiver.json} +2 -2
  16. package/build/contracts/IERC7984Rwa.json +797 -0
  17. package/build/contracts/VestingWalletCliffConfidential.json +3 -3
  18. package/build/contracts/VestingWalletConfidential.json +3 -3
  19. package/build/contracts/VestingWalletConfidentialFactory.json +18 -153
  20. package/build/contracts/VotesConfidential.json +23 -0
  21. package/finance/ERC7821WithExecutor.sol +2 -2
  22. package/finance/VestingWalletCliffConfidential.sol +15 -4
  23. package/finance/VestingWalletConfidential.sol +32 -20
  24. package/finance/VestingWalletConfidentialFactory.sol +34 -123
  25. package/governance/utils/VotesConfidential.sol +18 -4
  26. package/interfaces/{IConfidentialFungibleToken.sol → IERC7984.sol} +6 -6
  27. package/interfaces/{IConfidentialFungibleTokenReceiver.sol → IERC7984Receiver.sol} +3 -3
  28. package/interfaces/IERC7984Rwa.sol +64 -0
  29. package/package.json +4 -4
  30. package/token/{ConfidentialFungibleToken.sol → ERC7984/ERC7984.sol} +73 -84
  31. package/token/{extensions/ConfidentialFungibleTokenERC20Wrapper.sol → ERC7984/extensions/ERC7984ERC20Wrapper.sol} +36 -27
  32. package/token/ERC7984/extensions/ERC7984Freezable.sol +66 -0
  33. package/token/ERC7984/extensions/ERC7984ObserverAccess.sol +63 -0
  34. package/token/ERC7984/extensions/ERC7984Omnibus.sol +209 -0
  35. package/token/ERC7984/extensions/ERC7984Restricted.sol +118 -0
  36. package/token/ERC7984/extensions/ERC7984Rwa.sol +236 -0
  37. package/token/ERC7984/extensions/ERC7984Votes.sol +31 -0
  38. package/token/{utils/ConfidentialFungibleTokenUtils.sol → ERC7984/utils/ERC7984Utils.sol} +12 -12
  39. package/utils/FHESafeMath.sol +72 -0
  40. package/utils/HandleAccessManager.sol +29 -0
  41. package/utils/structs/CheckpointsConfidential.sol +1 -6
  42. package/utils/structs/temporary-Checkpoints.sol +2 -2
  43. package/token/extensions/ConfidentialFungibleTokenVotes.sol +0 -29
  44. package/utils/TFHESafeMath.sol +0 -37
@@ -0,0 +1,209 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.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
+ euint64 transferred = confidentialTransferFromAndCall(omnibusFrom, omnibusTo, amount, data);
193
+
194
+ FHE.allowThis(sender);
195
+ FHE.allow(sender, omnibusFrom);
196
+ FHE.allow(sender, omnibusTo);
197
+
198
+ FHE.allowThis(recipient);
199
+ FHE.allow(recipient, omnibusFrom);
200
+ FHE.allow(recipient, omnibusTo);
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,118 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.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
+ * To convert into an allowlist, override as:
43
+ *
44
+ * ```solidity
45
+ * function isUserAllowed(address account) public view virtual override returns (bool) {
46
+ * return getRestriction(account) == Restriction.ALLOWED;
47
+ * }
48
+ * ```
49
+ */
50
+ function isUserAllowed(address account) public view virtual returns (bool) {
51
+ return getRestriction(account) != Restriction.BLOCKED; // i.e. DEFAULT && ALLOWED
52
+ }
53
+
54
+ /**
55
+ * @dev See {ERC7984-_update}. Enforces transfer restrictions (excluding minting and burning).
56
+ *
57
+ * Requirements:
58
+ *
59
+ * * `from` must be allowed to transfer tokens (see {isUserAllowed}).
60
+ * * `to` must be allowed to receive tokens (see {isUserAllowed}).
61
+ *
62
+ * The default restriction behaviour can be changed (for a pass-through for instance) by overriding
63
+ * {_checkSenderRestriction} and/or {_checkRecipientRestriction}.
64
+ */
65
+ function _update(address from, address to, euint64 value) internal virtual override returns (euint64) {
66
+ _checkSenderRestriction(from);
67
+ _checkRecipientRestriction(to);
68
+ return super._update(from, to, value);
69
+ }
70
+
71
+ /// @dev Updates the restriction of a user account.
72
+ function _setRestriction(address account, Restriction restriction) internal virtual {
73
+ if (getRestriction(account) != restriction) {
74
+ _restrictions[account] = restriction;
75
+ emit UserRestrictionUpdated(account, restriction);
76
+ } // no-op if restriction is unchanged
77
+ }
78
+
79
+ /// @dev Convenience function to block a user account (set to BLOCKED).
80
+ function _blockUser(address account) internal virtual {
81
+ _setRestriction(account, Restriction.BLOCKED);
82
+ }
83
+
84
+ /// @dev Convenience function to allow a user account (set to ALLOWED).
85
+ function _allowUser(address account) internal virtual {
86
+ _setRestriction(account, Restriction.ALLOWED);
87
+ }
88
+
89
+ /// @dev Convenience function to reset a user account to default restriction.
90
+ function _resetUser(address account) internal virtual {
91
+ _setRestriction(account, Restriction.DEFAULT);
92
+ }
93
+
94
+ /// @dev Checks if a user account is restricted. Reverts with {ERC20Restricted} if so.
95
+ function _checkRestriction(address account) internal view virtual {
96
+ require(isUserAllowed(account), UserRestricted(account));
97
+ }
98
+
99
+ /**
100
+ * @dev Internal function which checks restriction of the `from` account before a transfer.
101
+ * Working with {_update} function.
102
+ */
103
+ function _checkSenderRestriction(address account) internal view virtual {
104
+ if (account != address(0)) {
105
+ _checkRestriction(account); // Not minting
106
+ }
107
+ }
108
+
109
+ /**
110
+ * @dev Internal function which checks restriction of the `to` account before a transfer.
111
+ * Working with {_update} function.
112
+ */
113
+ function _checkRecipientRestriction(address account) internal view virtual {
114
+ if (account != address(0)) {
115
+ _checkRestriction(account); // Not burning
116
+ }
117
+ }
118
+ }
@@ -0,0 +1,236 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.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 {FHESafeMath} from "./../../../utils/FHESafeMath.sol";
15
+ import {ERC7984} from "./../ERC7984.sol";
16
+ import {ERC7984Freezable} from "./ERC7984Freezable.sol";
17
+ import {ERC7984Restricted} from "./ERC7984Restricted.sol";
18
+
19
+ /**
20
+ * @dev Extension of {ERC7984} that supports confidential Real World Assets (RWAs).
21
+ * This interface provides compliance checks, transfer controls and enforcement actions.
22
+ */
23
+ abstract contract ERC7984Rwa is
24
+ IERC7984Rwa,
25
+ ERC7984Freezable,
26
+ ERC7984Restricted,
27
+ Pausable,
28
+ Multicall,
29
+ ERC165,
30
+ AccessControl
31
+ {
32
+ bytes32 public constant AGENT_ROLE = keccak256("AGENT_ROLE");
33
+
34
+ /// @dev Checks if the sender is an admin.
35
+ modifier onlyAdmin() {
36
+ _checkRole(DEFAULT_ADMIN_ROLE);
37
+ _;
38
+ }
39
+
40
+ /// @dev Checks if the sender is an agent.
41
+ modifier onlyAgent() {
42
+ _checkRole(AGENT_ROLE);
43
+ _;
44
+ }
45
+
46
+ constructor(address admin) {
47
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
48
+ }
49
+
50
+ /// @inheritdoc ERC165
51
+ function supportsInterface(
52
+ bytes4 interfaceId
53
+ ) public view virtual override(IERC165, ERC165, AccessControl) returns (bool) {
54
+ return
55
+ interfaceId == type(IERC7984Rwa).interfaceId ||
56
+ interfaceId == type(IERC7984).interfaceId ||
57
+ super.supportsInterface(interfaceId);
58
+ }
59
+
60
+ /// @dev Returns true if has admin role, false otherwise.
61
+ function isAdmin(address account) public view virtual returns (bool) {
62
+ return hasRole(DEFAULT_ADMIN_ROLE, account);
63
+ }
64
+
65
+ /// @dev Returns true if agent, false otherwise.
66
+ function isAgent(address account) public view virtual returns (bool) {
67
+ return hasRole(AGENT_ROLE, account);
68
+ }
69
+
70
+ /// @dev Adds agent.
71
+ function addAgent(address account) public virtual onlyAdmin {
72
+ _grantRole(AGENT_ROLE, account);
73
+ }
74
+
75
+ /// @dev Removes agent.
76
+ function removeAgent(address account) public virtual onlyAdmin {
77
+ _revokeRole(AGENT_ROLE, account);
78
+ }
79
+
80
+ /// @dev Pauses contract.
81
+ function pause() public virtual onlyAgent {
82
+ _pause();
83
+ }
84
+
85
+ /// @dev Unpauses contract.
86
+ function unpause() public virtual onlyAgent {
87
+ _unpause();
88
+ }
89
+
90
+ /// @dev Blocks a user account.
91
+ function blockUser(address account) public virtual onlyAgent {
92
+ _blockUser(account);
93
+ }
94
+
95
+ /// @dev Unblocks a user account.
96
+ function unblockUser(address account) public virtual onlyAgent {
97
+ _allowUser(account);
98
+ }
99
+
100
+ /// @dev Sets confidential frozen for an account.
101
+ function setConfidentialFrozen(
102
+ address account,
103
+ externalEuint64 encryptedAmount,
104
+ bytes calldata inputProof
105
+ ) public virtual onlyAgent {
106
+ _setConfidentialFrozen(account, FHE.fromExternal(encryptedAmount, inputProof));
107
+ }
108
+
109
+ /// @dev Sets confidential frozen for an account with proof.
110
+ function setConfidentialFrozen(address account, euint64 encryptedAmount) public virtual onlyAgent {
111
+ require(
112
+ FHE.isAllowed(encryptedAmount, msg.sender),
113
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
114
+ );
115
+ _setConfidentialFrozen(account, encryptedAmount);
116
+ }
117
+
118
+ /// @dev Mints confidential amount of tokens to account with proof.
119
+ function confidentialMint(
120
+ address to,
121
+ externalEuint64 encryptedAmount,
122
+ bytes calldata inputProof
123
+ ) public virtual onlyAgent returns (euint64) {
124
+ return _mint(to, FHE.fromExternal(encryptedAmount, inputProof));
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
+ return _mint(to, encryptedAmount);
134
+ }
135
+
136
+ /// @dev Burns confidential amount of tokens from account with proof.
137
+ function confidentialBurn(
138
+ address account,
139
+ externalEuint64 encryptedAmount,
140
+ bytes calldata inputProof
141
+ ) public virtual onlyAgent returns (euint64) {
142
+ return _burn(account, FHE.fromExternal(encryptedAmount, inputProof));
143
+ }
144
+
145
+ /// @dev Burns confidential amount of tokens from account.
146
+ function confidentialBurn(address account, euint64 encryptedAmount) public virtual onlyAgent returns (euint64) {
147
+ require(
148
+ FHE.isAllowed(encryptedAmount, msg.sender),
149
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
150
+ );
151
+ return _burn(account, encryptedAmount);
152
+ }
153
+
154
+ /// @dev Forces transfer of confidential amount of tokens from account to account with proof by skipping compliance checks.
155
+ function forceConfidentialTransferFrom(
156
+ address from,
157
+ address to,
158
+ externalEuint64 encryptedAmount,
159
+ bytes calldata inputProof
160
+ ) public virtual onlyAgent returns (euint64) {
161
+ return _forceUpdate(from, to, FHE.fromExternal(encryptedAmount, inputProof));
162
+ }
163
+
164
+ /// @dev Forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
165
+ function forceConfidentialTransferFrom(
166
+ address from,
167
+ address to,
168
+ euint64 encryptedAmount
169
+ ) public virtual onlyAgent returns (euint64 transferred) {
170
+ require(
171
+ FHE.isAllowed(encryptedAmount, msg.sender),
172
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
173
+ );
174
+ return _forceUpdate(from, to, encryptedAmount);
175
+ }
176
+
177
+ /// @inheritdoc ERC7984Freezable
178
+ function confidentialAvailable(
179
+ address account
180
+ ) public virtual override(IERC7984Rwa, ERC7984Freezable) returns (euint64) {
181
+ return super.confidentialAvailable(account);
182
+ }
183
+
184
+ /// @inheritdoc ERC7984Freezable
185
+ function confidentialFrozen(
186
+ address account
187
+ ) public view virtual override(IERC7984Rwa, ERC7984Freezable) returns (euint64) {
188
+ return super.confidentialFrozen(account);
189
+ }
190
+
191
+ /// @inheritdoc Pausable
192
+ function paused() public view virtual override(IERC7984Rwa, Pausable) returns (bool) {
193
+ return super.paused();
194
+ }
195
+
196
+ /// @inheritdoc ERC7984Restricted
197
+ function isUserAllowed(
198
+ address account
199
+ ) public view virtual override(IERC7984Rwa, ERC7984Restricted) returns (bool) {
200
+ return super.isUserAllowed(account);
201
+ }
202
+
203
+ /// @dev Internal function which updates confidential balances while performing frozen and restriction compliance checks.
204
+ function _update(
205
+ address from,
206
+ address to,
207
+ euint64 encryptedAmount
208
+ ) internal virtual override(ERC7984Freezable, ERC7984Restricted) whenNotPaused returns (euint64) {
209
+ // frozen and restriction checks performed through inheritance
210
+ return super._update(from, to, encryptedAmount);
211
+ }
212
+
213
+ /// @dev Internal function which forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
214
+ function _forceUpdate(address from, address to, euint64 encryptedAmount) internal virtual returns (euint64) {
215
+ // bypassing `from` restriction check with {_checkSenderRestriction}. Still performing `to` restriction check.
216
+ // bypassing paused state by directly calling `super._update`
217
+ return super._update(from, to, encryptedAmount);
218
+ }
219
+
220
+ /**
221
+ * @dev Bypasses the `from` restriction check when performing a {forceConfidentialTransferFrom}.
222
+ */
223
+ function _checkSenderRestriction(address account) internal view override {
224
+ if (_isForceTransfer()) {
225
+ return;
226
+ }
227
+ super._checkSenderRestriction(account);
228
+ }
229
+
230
+ /// @dev Private function which checks if the called function is a {forceConfidentialTransferFrom}.
231
+ function _isForceTransfer() private pure returns (bool) {
232
+ return
233
+ msg.sig == 0x6c9c3c85 || // bytes4(keccak256("forceConfidentialTransferFrom(address,address,bytes32)"))
234
+ msg.sig == 0x44fd6e40; // bytes4(keccak256("forceConfidentialTransferFrom(address,address,bytes32,bytes)"))
235
+ }
236
+ }
@@ -0,0 +1,31 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/extensions/ERC7984Votes.sol)
3
+ pragma solidity ^0.8.27;
4
+
5
+ import {euint64} from "@fhevm/solidity/lib/FHE.sol";
6
+ import {VotesConfidential} from "../../../governance/utils/VotesConfidential.sol";
7
+ import {ERC7984} from "./../ERC7984.sol";
8
+
9
+ /**
10
+ * @dev Extension of {ERC7984} supporting confidential votes tracking and delegation.
11
+ *
12
+ * The amount of confidential voting units an account has is equal to the balance of
13
+ * that account. Voing power is taken into account when an account delegates votes to itself or to another
14
+ * account.
15
+ */
16
+ abstract contract ERC7984Votes is ERC7984, VotesConfidential {
17
+ /// @inheritdoc ERC7984
18
+ function confidentialTotalSupply() public view virtual override(VotesConfidential, ERC7984) returns (euint64) {
19
+ return super.confidentialTotalSupply();
20
+ }
21
+
22
+ function _update(address from, address to, euint64 amount) internal virtual override returns (euint64 transferred) {
23
+ transferred = super._update(from, to, amount);
24
+
25
+ _transferVotingUnits(from, to, transferred);
26
+ }
27
+
28
+ function _getVotingUnits(address account) internal view virtual override returns (euint64) {
29
+ return confidentialBalanceOf(account);
30
+ }
31
+ }
@@ -1,21 +1,21 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0-rc.2) (token/utils/ConfidentialFungibleTokenUtils.sol)
3
- pragma solidity ^0.8.24;
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.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
18
+ * {IERC7984Receiver-onConfidentialTransferReceived} and return an `ebool` indicating
19
19
  * whether the transfer was accepted or not. If the `ebool` is `false`, the transfer will be reversed.
20
20
  */
21
21
  function checkOnTransferReceived(
@@ -26,13 +26,13 @@ library ConfidentialFungibleTokenUtils {
26
26
  bytes calldata data
27
27
  ) internal returns (ebool) {
28
28
  if (to.code.length > 0) {
29
- try
30
- IConfidentialFungibleTokenReceiver(to).onConfidentialTransferReceived(operator, from, amount, data)
31
- returns (ebool retval) {
29
+ try IERC7984Receiver(to).onConfidentialTransferReceived(operator, from, amount, data) returns (
30
+ ebool retval
31
+ ) {
32
32
  return retval;
33
33
  } catch (bytes memory reason) {
34
34
  if (reason.length == 0) {
35
- revert ConfidentialFungibleToken.ConfidentialFungibleTokenInvalidReceiver(to);
35
+ revert ERC7984.ERC7984InvalidReceiver(to);
36
36
  } else {
37
37
  assembly ("memory-safe") {
38
38
  revert(add(32, reason), mload(reason))