@openzeppelin/confidential-contracts 0.3.0-rc.0 → 0.3.1

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 (32) hide show
  1. package/build/contracts/Checkpoints.json +2 -2
  2. package/build/contracts/CheckpointsConfidential.json +2 -2
  3. package/build/contracts/ERC7984.json +72 -38
  4. package/build/contracts/ERC7984ERC20Wrapper.json +159 -39
  5. package/build/contracts/ERC7984Freezable.json +72 -38
  6. package/build/contracts/ERC7984ObserverAccess.json +73 -39
  7. package/build/contracts/ERC7984Omnibus.json +72 -38
  8. package/build/contracts/ERC7984Restricted.json +74 -40
  9. package/build/contracts/ERC7984Rwa.json +55 -40
  10. package/build/contracts/ERC7984Utils.json +2 -2
  11. package/build/contracts/ERC7984Votes.json +80 -46
  12. package/build/contracts/FHESafeMath.json +2 -2
  13. package/build/contracts/IERC7984.json +19 -0
  14. package/finance/ERC7821WithExecutor.sol +3 -4
  15. package/finance/VestingWalletCliffConfidential.sol +3 -4
  16. package/finance/VestingWalletConfidential.sol +3 -4
  17. package/finance/VestingWalletConfidentialFactory.sol +1 -1
  18. package/interfaces/IERC7984.sol +4 -3
  19. package/interfaces/IERC7984Receiver.sol +1 -1
  20. package/interfaces/IERC7984Rwa.sol +2 -3
  21. package/package.json +2 -2
  22. package/token/ERC7984/ERC7984.sol +32 -25
  23. package/token/ERC7984/extensions/ERC7984ERC20Wrapper.sol +87 -40
  24. package/token/ERC7984/extensions/ERC7984Freezable.sol +13 -4
  25. package/token/ERC7984/extensions/ERC7984ObserverAccess.sol +2 -2
  26. package/token/ERC7984/extensions/ERC7984Omnibus.sol +3 -3
  27. package/token/ERC7984/extensions/ERC7984Restricted.sol +3 -11
  28. package/token/ERC7984/extensions/ERC7984Rwa.sol +38 -26
  29. package/token/ERC7984/extensions/ERC7984Votes.sol +1 -1
  30. package/token/ERC7984/utils/ERC7984Utils.sol +3 -2
  31. package/utils/FHESafeMath.sol +5 -2
  32. package/utils/structs/temporary-Checkpoints.sol +1 -1
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/extensions/ERC7984Freezable.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Freezable.sol)
3
3
 
4
4
  pragma solidity ^0.8.27;
5
5
 
@@ -31,8 +31,16 @@ abstract contract ERC7984Freezable is ERC7984 {
31
31
  return _frozenBalances[account];
32
32
  }
33
33
 
34
- /// @dev Returns the confidential available (unfrozen) balance of an account. Up to {confidentialBalanceOf}.
34
+ /// @dev Returns the confidential available (unfrozen) balance of an account. Gives ACL allowance to `account`.
35
35
  function confidentialAvailable(address account) public virtual returns (euint64) {
36
+ euint64 amount = _confidentialAvailable(account);
37
+ FHE.allowThis(amount);
38
+ FHE.allow(amount, account);
39
+ return amount;
40
+ }
41
+
42
+ /// @dev Internal function to calculate the available balance of an account. Does not give any allowances.
43
+ function _confidentialAvailable(address account) internal virtual returns (euint64) {
36
44
  (ebool success, euint64 unfrozen) = FHESafeMath.tryDecrease(
37
45
  confidentialBalanceOf(account),
38
46
  confidentialFrozen(account)
@@ -54,11 +62,12 @@ abstract contract ERC7984Freezable is ERC7984 {
54
62
  * The `from` account must have sufficient unfrozen balance,
55
63
  * otherwise 0 tokens are transferred.
56
64
  * The default freezing behavior can be changed (for a pass-through for instance) by overriding
57
- * {confidentialAvailable}.
65
+ * {_confidentialAvailable}. The internal function is used for actual gating (not the public function)
66
+ * to avoid unnecessarily granting ACL allowances.
58
67
  */
59
68
  function _update(address from, address to, euint64 encryptedAmount) internal virtual override returns (euint64) {
60
69
  if (from != address(0)) {
61
- euint64 unfrozen = confidentialAvailable(from);
70
+ euint64 unfrozen = _confidentialAvailable(from);
62
71
  encryptedAmount = FHE.select(FHE.le(encryptedAmount, unfrozen), encryptedAmount, FHE.asEuint64(0));
63
72
  }
64
73
  return super._update(from, to, encryptedAmount);
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/extensions/ERC7984ObserverAccess.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984ObserverAccess.sol)
3
3
 
4
4
  pragma solidity ^0.8.27;
5
5
 
@@ -11,7 +11,7 @@ import {ERC7984} from "../ERC7984.sol";
11
11
  * permanent ACL access to its transfer and balance amounts. A observer can be added or removed at any point in time.
12
12
  */
13
13
  abstract contract ERC7984ObserverAccess is ERC7984 {
14
- mapping(address => address) private _observers;
14
+ mapping(address account => address) private _observers;
15
15
 
16
16
  /// @dev Emitted when the observer is changed for the given account `account`.
17
17
  event ERC7984ObserverAccessObserverSet(address account, address oldObserver, address newObserver);
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/extensions/ERC7984Omnibus.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Omnibus.sol)
3
3
 
4
4
  pragma solidity ^0.8.27;
5
5
 
@@ -189,8 +189,6 @@ abstract contract ERC7984Omnibus is ERC7984 {
189
189
  euint64 amount,
190
190
  bytes calldata data
191
191
  ) internal virtual returns (euint64) {
192
- euint64 transferred = confidentialTransferFromAndCall(omnibusFrom, omnibusTo, amount, data);
193
-
194
192
  FHE.allowThis(sender);
195
193
  FHE.allow(sender, omnibusFrom);
196
194
  FHE.allow(sender, omnibusTo);
@@ -199,6 +197,8 @@ abstract contract ERC7984Omnibus is ERC7984 {
199
197
  FHE.allow(recipient, omnibusFrom);
200
198
  FHE.allow(recipient, omnibusTo);
201
199
 
200
+ euint64 transferred = confidentialTransferFromAndCall(omnibusFrom, omnibusTo, amount, data);
201
+
202
202
  FHE.allowThis(transferred);
203
203
  FHE.allow(transferred, omnibusFrom);
204
204
  FHE.allow(transferred, omnibusTo);
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/extensions/ERC7984Restricted.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Restricted.sol)
3
3
 
4
4
  pragma solidity ^0.8.27;
5
5
 
@@ -38,14 +38,6 @@ abstract contract ERC7984Restricted is ERC7984 {
38
38
  * @dev Returns whether a user account is allowed to interact with the token.
39
39
  *
40
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
41
  */
50
42
  function isUserAllowed(address account) public view virtual returns (bool) {
51
43
  return getRestriction(account) != Restriction.BLOCKED; // i.e. DEFAULT && ALLOWED
@@ -59,7 +51,7 @@ abstract contract ERC7984Restricted is ERC7984 {
59
51
  * * `from` must be allowed to transfer tokens (see {isUserAllowed}).
60
52
  * * `to` must be allowed to receive tokens (see {isUserAllowed}).
61
53
  *
62
- * The default restriction behaviour can be changed (for a pass-through for instance) by overriding
54
+ * The default restriction behavior can be changed (for a pass-through for instance) by overriding
63
55
  * {_checkSenderRestriction} and/or {_checkRecipientRestriction}.
64
56
  */
65
57
  function _update(address from, address to, euint64 value) internal virtual override returns (euint64) {
@@ -91,7 +83,7 @@ abstract contract ERC7984Restricted is ERC7984 {
91
83
  _setRestriction(account, Restriction.DEFAULT);
92
84
  }
93
85
 
94
- /// @dev Checks if a user account is restricted. Reverts with {ERC20Restricted} if so.
86
+ /// @dev Checks if a user account is restricted. Reverts with {UserRestricted} if so.
95
87
  function _checkRestriction(address account) internal view virtual {
96
88
  require(isUserAllowed(account), UserRestricted(account));
97
89
  }
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/extensions/ERC7984Rwa.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/extensions/ERC7984Rwa.sol)
3
3
 
4
4
  pragma solidity ^0.8.27;
5
5
 
@@ -11,7 +11,6 @@ import {Multicall} from "@openzeppelin/contracts/utils/Multicall.sol";
11
11
  import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
12
12
  import {IERC7984} from "./../../../interfaces/IERC7984.sol";
13
13
  import {IERC7984Rwa} from "./../../../interfaces/IERC7984Rwa.sol";
14
- import {FHESafeMath} from "./../../../utils/FHESafeMath.sol";
15
14
  import {ERC7984} from "./../ERC7984.sol";
16
15
  import {ERC7984Freezable} from "./ERC7984Freezable.sol";
17
16
  import {ERC7984Restricted} from "./ERC7984Restricted.sol";
@@ -20,15 +19,17 @@ import {ERC7984Restricted} from "./ERC7984Restricted.sol";
20
19
  * @dev Extension of {ERC7984} that supports confidential Real World Assets (RWAs).
21
20
  * This interface provides compliance checks, transfer controls and enforcement actions.
22
21
  */
23
- abstract contract ERC7984Rwa is
24
- IERC7984Rwa,
25
- ERC7984Freezable,
26
- ERC7984Restricted,
27
- Pausable,
28
- Multicall,
29
- ERC165,
30
- AccessControl
31
- {
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
+ */
32
33
  bytes32 public constant AGENT_ROLE = keccak256("AGENT_ROLE");
33
34
 
34
35
  /// @dev Checks if the sender is an admin.
@@ -50,11 +51,8 @@ abstract contract ERC7984Rwa is
50
51
  /// @inheritdoc ERC165
51
52
  function supportsInterface(
52
53
  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);
54
+ ) public view virtual override(IERC165, ERC7984, AccessControl) returns (bool) {
55
+ return interfaceId == type(IERC7984Rwa).interfaceId || super.supportsInterface(interfaceId);
58
56
  }
59
57
 
60
58
  /// @dev Returns true if has admin role, false otherwise.
@@ -94,10 +92,10 @@ abstract contract ERC7984Rwa is
94
92
 
95
93
  /// @dev Unblocks a user account.
96
94
  function unblockUser(address account) public virtual onlyAgent {
97
- _allowUser(account);
95
+ _resetUser(account);
98
96
  }
99
97
 
100
- /// @dev Sets confidential frozen for an account.
98
+ /// @dev Sets confidential frozen for an account with proof.
101
99
  function setConfidentialFrozen(
102
100
  address account,
103
101
  externalEuint64 encryptedAmount,
@@ -106,7 +104,7 @@ abstract contract ERC7984Rwa is
106
104
  _setConfidentialFrozen(account, FHE.fromExternal(encryptedAmount, inputProof));
107
105
  }
108
106
 
109
- /// @dev Sets confidential frozen for an account with proof.
107
+ /// @dev Sets confidential frozen for an account.
110
108
  function setConfidentialFrozen(address account, euint64 encryptedAmount) public virtual onlyAgent {
111
109
  require(
112
110
  FHE.isAllowed(encryptedAmount, msg.sender),
@@ -121,7 +119,9 @@ abstract contract ERC7984Rwa is
121
119
  externalEuint64 encryptedAmount,
122
120
  bytes calldata inputProof
123
121
  ) public virtual onlyAgent returns (euint64) {
124
- return _mint(to, FHE.fromExternal(encryptedAmount, inputProof));
122
+ euint64 mintedAmount = _mint(to, FHE.fromExternal(encryptedAmount, inputProof));
123
+ FHE.allow(mintedAmount, msg.sender);
124
+ return mintedAmount;
125
125
  }
126
126
 
127
127
  /// @dev Mints confidential amount of tokens to account.
@@ -130,7 +130,9 @@ abstract contract ERC7984Rwa is
130
130
  FHE.isAllowed(encryptedAmount, msg.sender),
131
131
  ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
132
132
  );
133
- return _mint(to, encryptedAmount);
133
+ euint64 mintedAmount = _mint(to, encryptedAmount);
134
+ FHE.allow(mintedAmount, msg.sender);
135
+ return mintedAmount;
134
136
  }
135
137
 
136
138
  /// @dev Burns confidential amount of tokens from account with proof.
@@ -139,7 +141,9 @@ abstract contract ERC7984Rwa is
139
141
  externalEuint64 encryptedAmount,
140
142
  bytes calldata inputProof
141
143
  ) public virtual onlyAgent returns (euint64) {
142
- return _burn(account, FHE.fromExternal(encryptedAmount, inputProof));
144
+ euint64 burntAmount = _burn(account, FHE.fromExternal(encryptedAmount, inputProof));
145
+ FHE.allow(burntAmount, msg.sender);
146
+ return burntAmount;
143
147
  }
144
148
 
145
149
  /// @dev Burns confidential amount of tokens from account.
@@ -148,10 +152,12 @@ abstract contract ERC7984Rwa is
148
152
  FHE.isAllowed(encryptedAmount, msg.sender),
149
153
  ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
150
154
  );
151
- return _burn(account, encryptedAmount);
155
+ euint64 burntAmount = _burn(account, encryptedAmount);
156
+ FHE.allow(burntAmount, msg.sender);
157
+ return burntAmount;
152
158
  }
153
159
 
154
- /// @dev Forces transfer of confidential amount of tokens from account to account with proof by skipping compliance checks.
160
+ /// @dev Variant of {forceConfidentialTransferFrom-address-address-euint64} with an input proof.
155
161
  function forceConfidentialTransferFrom(
156
162
  address from,
157
163
  address to,
@@ -161,7 +167,11 @@ abstract contract ERC7984Rwa is
161
167
  return _forceUpdate(from, to, FHE.fromExternal(encryptedAmount, inputProof));
162
168
  }
163
169
 
164
- /// @dev Forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
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
+ */
165
175
  function forceConfidentialTransferFrom(
166
176
  address from,
167
177
  address to,
@@ -214,7 +224,9 @@ abstract contract ERC7984Rwa is
214
224
  function _forceUpdate(address from, address to, euint64 encryptedAmount) internal virtual returns (euint64) {
215
225
  // bypassing `from` restriction check with {_checkSenderRestriction}. Still performing `to` restriction check.
216
226
  // bypassing paused state by directly calling `super._update`
217
- return super._update(from, to, encryptedAmount);
227
+ euint64 transferred = super._update(from, to, encryptedAmount);
228
+ FHE.allow(transferred, msg.sender);
229
+ return transferred;
218
230
  }
219
231
 
220
232
  /**
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/extensions/ERC7984Votes.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";
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/utils/ERC7984Utils.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (token/ERC7984/utils/ERC7984Utils.sol)
3
3
  pragma solidity ^0.8.27;
4
4
 
5
5
  import {FHE, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
@@ -16,7 +16,8 @@ library ERC7984Utils {
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
18
  * {IERC7984Receiver-onConfidentialTransferReceived} and return an `ebool` indicating
19
- * whether the transfer was accepted or not. If the `ebool` is `false`, the transfer will be reversed.
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,
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (utils/FHESafeMath.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (utils/FHESafeMath.sol)
3
3
  pragma solidity ^0.8.24;
4
4
 
5
5
  import {FHE, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
@@ -7,6 +7,9 @@ import {FHE, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
7
7
  /**
8
8
  * @dev Library providing safe arithmetic operations for encrypted values
9
9
  * to handle potential overflows in FHE operations.
10
+ *
11
+ * NOTE: An uninitialized `euint64` value (equivalent to euint64.wrap(bytes32(0))) is evaluated as 0.
12
+ * This library will may return an uninitialized value if all inputs are uninitialized.
10
13
  */
11
14
  library FHESafeMath {
12
15
  /**
@@ -33,7 +36,7 @@ library FHESafeMath {
33
36
  if (!FHE.isInitialized(delta)) {
34
37
  return (FHE.asEbool(true), oldValue);
35
38
  }
36
- return (FHE.eq(oldValue, delta), oldValue);
39
+ return (FHE.eq(delta, 0), FHE.asEuint64(0));
37
40
  }
38
41
  success = FHE.ge(oldValue, delta);
39
42
  updated = FHE.select(success, FHE.sub(oldValue, delta), oldValue);
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (utils/structs/temporary-Checkpoints.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0) (utils/structs/temporary-Checkpoints.sol)
3
3
  // OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/Checkpoints.sol)
4
4
  // This file was procedurally generated from scripts/generate/templates/Checkpoints.js.
5
5
  // WARNING: This file is temporary and will be deleted once the latest version of the file is released in v5.5.0 of @openzeppelin/contracts.