@openzeppelin/confidential-contracts 0.2.0 → 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 (33) 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} +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} +76 -81
  12. package/build/contracts/FHESafeMath.json +2 -2
  13. package/build/contracts/{IConfidentialFungibleToken.json → IERC7984.json} +15 -15
  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/VestingWalletConfidential.sol +6 -9
  18. package/finance/VestingWalletConfidentialFactory.sol +7 -12
  19. package/interfaces/{IConfidentialFungibleToken.sol → IERC7984.sol} +5 -5
  20. package/interfaces/{IConfidentialFungibleTokenReceiver.sol → IERC7984Receiver.sol} +3 -3
  21. package/interfaces/IERC7984Rwa.sol +64 -0
  22. package/package.json +4 -4
  23. package/token/{ConfidentialFungibleToken.sol → ERC7984/ERC7984.sol} +68 -76
  24. package/token/{extensions/ConfidentialFungibleTokenERC20Wrapper.sol → ERC7984/extensions/ERC7984ERC20Wrapper.sol} +18 -20
  25. package/token/ERC7984/extensions/ERC7984Freezable.sol +66 -0
  26. package/token/ERC7984/extensions/ERC7984ObserverAccess.sol +63 -0
  27. package/token/ERC7984/extensions/ERC7984Omnibus.sol +209 -0
  28. package/token/ERC7984/extensions/ERC7984Restricted.sol +118 -0
  29. package/token/ERC7984/extensions/ERC7984Rwa.sol +236 -0
  30. package/token/{extensions/ConfidentialFungibleTokenVotes.sol → ERC7984/extensions/ERC7984Votes.sol} +8 -14
  31. package/token/{utils/ConfidentialFungibleTokenUtils.sol → ERC7984/utils/ERC7984Utils.sol} +12 -12
  32. package/utils/FHESafeMath.sol +42 -7
  33. package/utils/structs/temporary-Checkpoints.sol +2 -2
@@ -55,7 +55,7 @@
55
55
  {
56
56
  "indexed": true,
57
57
  "internalType": "address",
58
- "name": "confidentialFungibleToken",
58
+ "name": "token",
59
59
  "type": "address"
60
60
  },
61
61
  {
@@ -78,7 +78,7 @@
78
78
  "inputs": [
79
79
  {
80
80
  "internalType": "address",
81
- "name": "confidentialFungibleToken",
81
+ "name": "token",
82
82
  "type": "address"
83
83
  },
84
84
  {
@@ -1,14 +1,14 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0) (finance/VestingWalletConfidential.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (finance/VestingWalletConfidential.sol)
3
3
  pragma solidity ^0.8.24;
4
4
 
5
5
  import {FHE, ebool, euint64, euint128} from "@fhevm/solidity/lib/FHE.sol";
6
6
  import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
7
7
  import {ReentrancyGuardTransient} from "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol";
8
- import {IConfidentialFungibleToken} from "./../interfaces/IConfidentialFungibleToken.sol";
8
+ import {IERC7984} from "./../interfaces/IERC7984.sol";
9
9
 
10
10
  /**
11
- * @dev A vesting wallet is an ownable contract that can receive ConfidentialFungibleTokens, and release these
11
+ * @dev A vesting wallet is an ownable contract that can receive ERC7984 tokens, and release these
12
12
  * assets to the wallet owner, also referred to as "beneficiary", according to a vesting schedule.
13
13
  *
14
14
  * Any assets transferred to this contract will follow the vesting schedule as if they were locked from the beginning.
@@ -63,7 +63,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
63
63
 
64
64
  /**
65
65
  * @dev Getter for the amount of releasable `token` tokens. `token` should be the address of an
66
- * {IConfidentialFungibleToken} contract.
66
+ * {IERC7984} contract.
67
67
  */
68
68
  function releasable(address token) public virtual returns (euint64) {
69
69
  euint128 vestedAmount_ = vestedAmount(token, uint48(block.timestamp));
@@ -80,7 +80,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
80
80
  function release(address token) public virtual nonReentrant {
81
81
  euint64 amount = releasable(token);
82
82
  FHE.allowTransient(amount, token);
83
- euint64 amountSent = IConfidentialFungibleToken(token).confidentialTransfer(owner(), amount);
83
+ euint64 amountSent = IERC7984(token).confidentialTransfer(owner(), amount);
84
84
 
85
85
  // This could overflow if the total supply is resent `type(uint128).max/type(uint64).max` times. This is an accepted risk.
86
86
  euint128 newReleasedAmount = FHE.add(released(token), amountSent);
@@ -96,10 +96,7 @@ abstract contract VestingWalletConfidential is OwnableUpgradeable, ReentrancyGua
96
96
  */
97
97
  function vestedAmount(address token, uint48 timestamp) public virtual returns (euint128) {
98
98
  return
99
- _vestingSchedule(
100
- FHE.add(released(token), IConfidentialFungibleToken(token).confidentialBalanceOf(address(this))),
101
- timestamp
102
- );
99
+ _vestingSchedule(FHE.add(released(token), IERC7984(token).confidentialBalanceOf(address(this))), timestamp);
103
100
  }
104
101
 
105
102
  /**
@@ -1,10 +1,10 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0) (finance/VestingWalletConfidentialFactory.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (finance/VestingWalletConfidentialFactory.sol)
3
3
  pragma solidity ^0.8.27;
4
4
 
5
5
  import {FHE, euint64, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
6
6
  import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
7
- import {IConfidentialFungibleToken} from "./../interfaces/IConfidentialFungibleToken.sol";
7
+ import {IERC7984} from "./../interfaces/IERC7984.sol";
8
8
 
9
9
  /**
10
10
  * @dev A factory which enables batch funding of vesting wallets.
@@ -23,7 +23,7 @@ abstract contract VestingWalletConfidentialFactory {
23
23
  /// @dev Emitted for each vesting wallet funded within a batch.
24
24
  event VestingWalletConfidentialFunded(
25
25
  address indexed vestingWalletConfidential,
26
- address indexed confidentialFungibleToken,
26
+ address indexed token,
27
27
  euint64 transferredAmount,
28
28
  bytes initArgs
29
29
  );
@@ -43,7 +43,7 @@ abstract contract VestingWalletConfidentialFactory {
43
43
  * Emits a {VestingWalletConfidentialFunded} event for each funded vesting plan.
44
44
  */
45
45
  function batchFundVestingWalletConfidential(
46
- address confidentialFungibleToken,
46
+ address token,
47
47
  VestingPlan[] calldata vestingPlans,
48
48
  bytes calldata inputProof
49
49
  ) public virtual {
@@ -55,19 +55,14 @@ abstract contract VestingWalletConfidentialFactory {
55
55
  address vestingWalletAddress = predictVestingWalletConfidential(vestingPlan.initArgs);
56
56
 
57
57
  euint64 encryptedAmount = FHE.fromExternal(vestingPlan.encryptedAmount, inputProof);
58
- FHE.allowTransient(encryptedAmount, confidentialFungibleToken);
59
- euint64 transferredAmount = IConfidentialFungibleToken(confidentialFungibleToken).confidentialTransferFrom(
58
+ FHE.allowTransient(encryptedAmount, token);
59
+ euint64 transferredAmount = IERC7984(token).confidentialTransferFrom(
60
60
  msg.sender,
61
61
  vestingWalletAddress,
62
62
  encryptedAmount
63
63
  );
64
64
 
65
- emit VestingWalletConfidentialFunded(
66
- vestingWalletAddress,
67
- confidentialFungibleToken,
68
- transferredAmount,
69
- vestingPlan.initArgs
70
- );
65
+ emit VestingWalletConfidentialFunded(vestingWalletAddress, token, transferredAmount, vestingPlan.initArgs);
71
66
  }
72
67
  }
73
68
 
@@ -1,11 +1,11 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0) (interfaces/IConfidentialFungibleToken.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (interfaces/IERC7984.sol)
3
3
  pragma solidity ^0.8.24;
4
4
 
5
5
  import {euint64, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
6
6
 
7
7
  /// @dev Draft interface for a confidential fungible token standard utilizing the Zama FHE library.
8
- interface IConfidentialFungibleToken {
8
+ interface IERC7984 {
9
9
  /**
10
10
  * @dev Emitted when the expiration timestamp for an operator `operator` is updated for a given `holder`.
11
11
  * The operator may move any amount of tokens on behalf of the holder until the timestamp `until`.
@@ -32,8 +32,8 @@ interface IConfidentialFungibleToken {
32
32
  /// @dev Returns the number of decimals of the token. Recommended to be 6.
33
33
  function decimals() external view returns (uint8);
34
34
 
35
- /// @dev Returns the token URI.
36
- function tokenURI() external view returns (string memory);
35
+ /// @dev Returns the contract URI. See [ERC-7572](https://eips.ethereum.org/EIPS/eip-7572) for details.
36
+ function contractURI() external view returns (string memory);
37
37
 
38
38
  /// @dev Returns the confidential total supply of the token.
39
39
  function confidentialTotalSupply() external view returns (euint64);
@@ -91,7 +91,7 @@ interface IConfidentialFungibleToken {
91
91
  * @dev Similar to {confidentialTransfer-address-externalEuint64-bytes} but with a callback to `to` after
92
92
  * the transfer.
93
93
  *
94
- * The callback is made to the {IConfidentialFungibleTokenReceiver-onConfidentialTransferReceived} function on the
94
+ * The callback is made to the {IERC7984Receiver-onConfidentialTransferReceived} function on the
95
95
  * to address with the actual transferred amount (may differ from the given `encryptedAmount`) and the given
96
96
  * data `data`.
97
97
  */
@@ -1,11 +1,11 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0) (interfaces/IConfidentialFungibleTokenReceiver.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (interfaces/IERC7984Receiver.sol)
3
3
  pragma solidity ^0.8.24;
4
4
 
5
5
  import {ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
6
6
 
7
- /// @dev Interface for contracts that can receive confidential token transfers with a callback.
8
- interface IConfidentialFungibleTokenReceiver {
7
+ /// @dev Interface for contracts that can receive ERC7984 transfers with a callback.
8
+ interface IERC7984Receiver {
9
9
  /**
10
10
  * @dev Called upon receiving a confidential token transfer. Returns an encrypted boolean indicating success
11
11
  * of the callback. If false is returned, the transfer must be reversed.
@@ -0,0 +1,64 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (interfaces/IERC7984Rwa.sol)
3
+ pragma solidity ^0.8.24;
4
+
5
+ import {externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol";
6
+ import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
7
+ import {IERC7984} from "./IERC7984.sol";
8
+
9
+ /// @dev Interface for confidential RWA contracts.
10
+ interface IERC7984Rwa is IERC7984, IERC165 {
11
+ /// @dev Returns true if the contract is paused, false otherwise.
12
+ function paused() external view returns (bool);
13
+ /// @dev Returns whether an account is allowed to interact with the token.
14
+ function isUserAllowed(address account) external view returns (bool);
15
+ /// @dev Returns the confidential frozen balance of an account.
16
+ function confidentialFrozen(address account) external view returns (euint64);
17
+ /// @dev Returns the confidential available (unfrozen) balance of an account. Up to {IERC7984-confidentialBalanceOf}.
18
+ function confidentialAvailable(address account) external returns (euint64);
19
+ /// @dev Pauses contract.
20
+ function pause() external;
21
+ /// @dev Unpauses contract.
22
+ function unpause() external;
23
+ /// @dev Blocks a user account.
24
+ function blockUser(address account) external;
25
+ /// @dev Unblocks a user account.
26
+ function unblockUser(address account) external;
27
+ /// @dev Sets confidential amount of token for an account as frozen with proof.
28
+ function setConfidentialFrozen(
29
+ address account,
30
+ externalEuint64 encryptedAmount,
31
+ bytes calldata inputProof
32
+ ) external;
33
+ /// @dev Sets confidential amount of token for an account as frozen.
34
+ function setConfidentialFrozen(address account, euint64 encryptedAmount) external;
35
+ /// @dev Mints confidential amount of tokens to account with proof.
36
+ function confidentialMint(
37
+ address to,
38
+ externalEuint64 encryptedAmount,
39
+ bytes calldata inputProof
40
+ ) external returns (euint64);
41
+ /// @dev Mints confidential amount of tokens to account.
42
+ function confidentialMint(address to, euint64 encryptedAmount) external returns (euint64);
43
+ /// @dev Burns confidential amount of tokens from account with proof.
44
+ function confidentialBurn(
45
+ address account,
46
+ externalEuint64 encryptedAmount,
47
+ bytes calldata inputProof
48
+ ) external returns (euint64);
49
+ /// @dev Burns confidential amount of tokens from account.
50
+ function confidentialBurn(address account, euint64 encryptedAmount) external returns (euint64);
51
+ /// @dev Forces transfer of confidential amount of tokens from account to account with proof by skipping compliance checks.
52
+ function forceConfidentialTransferFrom(
53
+ address from,
54
+ address to,
55
+ externalEuint64 encryptedAmount,
56
+ bytes calldata inputProof
57
+ ) external returns (euint64);
58
+ /// @dev Forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
59
+ function forceConfidentialTransferFrom(
60
+ address from,
61
+ address to,
62
+ euint64 encryptedAmount
63
+ ) external returns (euint64);
64
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openzeppelin/confidential-contracts",
3
3
  "description": "Smart Contract library for use with confidential coprocessors",
4
- "version": "0.2.0",
4
+ "version": "0.3.0-rc.0",
5
5
  "files": [
6
6
  "**/*.sol",
7
7
  "/build/contracts/*.json",
@@ -32,8 +32,8 @@
32
32
  },
33
33
  "homepage": "https://openzeppelin.com/contracts/",
34
34
  "peerDependencies": {
35
- "@fhevm/solidity": "0.7.0",
36
- "@openzeppelin/contracts": "^5.3.0",
37
- "@openzeppelin/contracts-upgradeable": "^5.3.0"
35
+ "@fhevm/solidity": "0.8.0",
36
+ "@openzeppelin/contracts": "^5.4.0",
37
+ "@openzeppelin/contracts-upgradeable": "^5.4.0"
38
38
  }
39
39
  }
@@ -1,14 +1,14 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // OpenZeppelin Confidential Contracts (last updated v0.2.0) (token/ConfidentialFungibleToken.sol)
2
+ // OpenZeppelin Confidential Contracts (last updated v0.3.0-rc.0) (token/ERC7984/ERC7984.sol)
3
3
  pragma solidity ^0.8.27;
4
4
 
5
5
  import {FHE, externalEuint64, ebool, euint64} from "@fhevm/solidity/lib/FHE.sol";
6
- import {IConfidentialFungibleToken} from "./../interfaces/IConfidentialFungibleToken.sol";
7
- import {FHESafeMath} from "./../utils/FHESafeMath.sol";
8
- import {ConfidentialFungibleTokenUtils} from "./utils/ConfidentialFungibleTokenUtils.sol";
6
+ import {IERC7984} from "./../../interfaces/IERC7984.sol";
7
+ import {FHESafeMath} from "./../../utils/FHESafeMath.sol";
8
+ import {ERC7984Utils} from "./utils/ERC7984Utils.sol";
9
9
 
10
10
  /**
11
- * @dev Reference implementation for {IConfidentialFungibleToken}.
11
+ * @dev Reference implementation for {IERC7984}.
12
12
  *
13
13
  * This contract implements a fungible token where balances and transfers are encrypted using the Zama fhEVM,
14
14
  * providing confidentiality to users. Token amounts are stored as encrypted, unsigned integers (`euint64`)
@@ -22,87 +22,86 @@ import {ConfidentialFungibleTokenUtils} from "./utils/ConfidentialFungibleTokenU
22
22
  * - Transfer and call pattern
23
23
  * - Safe overflow/underflow handling for FHE operations
24
24
  */
25
- abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
25
+ abstract contract ERC7984 is IERC7984 {
26
26
  mapping(address holder => euint64) private _balances;
27
27
  mapping(address holder => mapping(address spender => uint48)) private _operators;
28
- mapping(uint256 requestId => euint64 encryptedAmount) private _requestHandles;
29
28
  euint64 private _totalSupply;
30
29
  string private _name;
31
30
  string private _symbol;
32
- string private _tokenURI;
31
+ string private _contractURI;
33
32
 
34
33
  /// @dev The given receiver `receiver` is invalid for transfers.
35
- error ConfidentialFungibleTokenInvalidReceiver(address receiver);
34
+ error ERC7984InvalidReceiver(address receiver);
36
35
 
37
36
  /// @dev The given sender `sender` is invalid for transfers.
38
- error ConfidentialFungibleTokenInvalidSender(address sender);
37
+ error ERC7984InvalidSender(address sender);
39
38
 
40
39
  /// @dev The given holder `holder` is not authorized to spend on behalf of `spender`.
41
- error ConfidentialFungibleTokenUnauthorizedSpender(address holder, address spender);
40
+ error ERC7984UnauthorizedSpender(address holder, address spender);
42
41
 
43
42
  /// @dev The holder `holder` is trying to send tokens but has a balance of 0.
44
- error ConfidentialFungibleTokenZeroBalance(address holder);
43
+ error ERC7984ZeroBalance(address holder);
45
44
 
46
45
  /**
47
46
  * @dev The caller `user` does not have access to the encrypted amount `amount`.
48
47
  *
49
48
  * NOTE: Try using the equivalent transfer function with an input proof.
50
49
  */
51
- error ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(euint64 amount, address user);
50
+ error ERC7984UnauthorizedUseOfEncryptedAmount(euint64 amount, address user);
52
51
 
53
52
  /// @dev The given caller `caller` is not authorized for the current operation.
54
- error ConfidentialFungibleTokenUnauthorizedCaller(address caller);
53
+ error ERC7984UnauthorizedCaller(address caller);
55
54
 
56
55
  /// @dev The given gateway request ID `requestId` is invalid.
57
- error ConfidentialFungibleTokenInvalidGatewayRequest(uint256 requestId);
56
+ error ERC7984InvalidGatewayRequest(uint256 requestId);
58
57
 
59
- constructor(string memory name_, string memory symbol_, string memory tokenURI_) {
58
+ constructor(string memory name_, string memory symbol_, string memory contractURI_) {
60
59
  _name = name_;
61
60
  _symbol = symbol_;
62
- _tokenURI = tokenURI_;
61
+ _contractURI = contractURI_;
63
62
  }
64
63
 
65
- /// @inheritdoc IConfidentialFungibleToken
64
+ /// @inheritdoc IERC7984
66
65
  function name() public view virtual returns (string memory) {
67
66
  return _name;
68
67
  }
69
68
 
70
- /// @inheritdoc IConfidentialFungibleToken
69
+ /// @inheritdoc IERC7984
71
70
  function symbol() public view virtual returns (string memory) {
72
71
  return _symbol;
73
72
  }
74
73
 
75
- /// @inheritdoc IConfidentialFungibleToken
74
+ /// @inheritdoc IERC7984
76
75
  function decimals() public view virtual returns (uint8) {
77
76
  return 6;
78
77
  }
79
78
 
80
- /// @inheritdoc IConfidentialFungibleToken
81
- function tokenURI() public view virtual returns (string memory) {
82
- return _tokenURI;
79
+ /// @inheritdoc IERC7984
80
+ function contractURI() public view virtual returns (string memory) {
81
+ return _contractURI;
83
82
  }
84
83
 
85
- /// @inheritdoc IConfidentialFungibleToken
84
+ /// @inheritdoc IERC7984
86
85
  function confidentialTotalSupply() public view virtual returns (euint64) {
87
86
  return _totalSupply;
88
87
  }
89
88
 
90
- /// @inheritdoc IConfidentialFungibleToken
89
+ /// @inheritdoc IERC7984
91
90
  function confidentialBalanceOf(address account) public view virtual returns (euint64) {
92
91
  return _balances[account];
93
92
  }
94
93
 
95
- /// @inheritdoc IConfidentialFungibleToken
94
+ /// @inheritdoc IERC7984
96
95
  function isOperator(address holder, address spender) public view virtual returns (bool) {
97
96
  return holder == spender || block.timestamp <= _operators[holder][spender];
98
97
  }
99
98
 
100
- /// @inheritdoc IConfidentialFungibleToken
99
+ /// @inheritdoc IERC7984
101
100
  function setOperator(address operator, uint48 until) public virtual {
102
101
  _setOperator(msg.sender, operator, until);
103
102
  }
104
103
 
105
- /// @inheritdoc IConfidentialFungibleToken
104
+ /// @inheritdoc IERC7984
106
105
  function confidentialTransfer(
107
106
  address to,
108
107
  externalEuint64 encryptedAmount,
@@ -111,43 +110,37 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
111
110
  return _transfer(msg.sender, to, FHE.fromExternal(encryptedAmount, inputProof));
112
111
  }
113
112
 
114
- /// @inheritdoc IConfidentialFungibleToken
113
+ /// @inheritdoc IERC7984
115
114
  function confidentialTransfer(address to, euint64 amount) public virtual returns (euint64) {
116
- require(
117
- FHE.isAllowed(amount, msg.sender),
118
- ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
119
- );
115
+ require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
120
116
  return _transfer(msg.sender, to, amount);
121
117
  }
122
118
 
123
- /// @inheritdoc IConfidentialFungibleToken
119
+ /// @inheritdoc IERC7984
124
120
  function confidentialTransferFrom(
125
121
  address from,
126
122
  address to,
127
123
  externalEuint64 encryptedAmount,
128
124
  bytes calldata inputProof
129
125
  ) public virtual returns (euint64 transferred) {
130
- require(isOperator(from, msg.sender), ConfidentialFungibleTokenUnauthorizedSpender(from, msg.sender));
126
+ require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
131
127
  transferred = _transfer(from, to, FHE.fromExternal(encryptedAmount, inputProof));
132
128
  FHE.allowTransient(transferred, msg.sender);
133
129
  }
134
130
 
135
- /// @inheritdoc IConfidentialFungibleToken
131
+ /// @inheritdoc IERC7984
136
132
  function confidentialTransferFrom(
137
133
  address from,
138
134
  address to,
139
135
  euint64 amount
140
136
  ) public virtual returns (euint64 transferred) {
141
- require(
142
- FHE.isAllowed(amount, msg.sender),
143
- ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
144
- );
145
- require(isOperator(from, msg.sender), ConfidentialFungibleTokenUnauthorizedSpender(from, msg.sender));
137
+ require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
138
+ require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
146
139
  transferred = _transfer(from, to, amount);
147
140
  FHE.allowTransient(transferred, msg.sender);
148
141
  }
149
142
 
150
- /// @inheritdoc IConfidentialFungibleToken
143
+ /// @inheritdoc IERC7984
151
144
  function confidentialTransferAndCall(
152
145
  address to,
153
146
  externalEuint64 encryptedAmount,
@@ -158,21 +151,18 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
158
151
  FHE.allowTransient(transferred, msg.sender);
159
152
  }
160
153
 
161
- /// @inheritdoc IConfidentialFungibleToken
154
+ /// @inheritdoc IERC7984
162
155
  function confidentialTransferAndCall(
163
156
  address to,
164
157
  euint64 amount,
165
158
  bytes calldata data
166
159
  ) public virtual returns (euint64 transferred) {
167
- require(
168
- FHE.isAllowed(amount, msg.sender),
169
- ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
170
- );
160
+ require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
171
161
  transferred = _transferAndCall(msg.sender, to, amount, data);
172
162
  FHE.allowTransient(transferred, msg.sender);
173
163
  }
174
164
 
175
- /// @inheritdoc IConfidentialFungibleToken
165
+ /// @inheritdoc IERC7984
176
166
  function confidentialTransferFromAndCall(
177
167
  address from,
178
168
  address to,
@@ -180,29 +170,26 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
180
170
  bytes calldata inputProof,
181
171
  bytes calldata data
182
172
  ) public virtual returns (euint64 transferred) {
183
- require(isOperator(from, msg.sender), ConfidentialFungibleTokenUnauthorizedSpender(from, msg.sender));
173
+ require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
184
174
  transferred = _transferAndCall(from, to, FHE.fromExternal(encryptedAmount, inputProof), data);
185
175
  FHE.allowTransient(transferred, msg.sender);
186
176
  }
187
177
 
188
- /// @inheritdoc IConfidentialFungibleToken
178
+ /// @inheritdoc IERC7984
189
179
  function confidentialTransferFromAndCall(
190
180
  address from,
191
181
  address to,
192
182
  euint64 amount,
193
183
  bytes calldata data
194
184
  ) public virtual returns (euint64 transferred) {
195
- require(
196
- FHE.isAllowed(amount, msg.sender),
197
- ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(amount, msg.sender)
198
- );
199
- require(isOperator(from, msg.sender), ConfidentialFungibleTokenUnauthorizedSpender(from, msg.sender));
185
+ require(FHE.isAllowed(amount, msg.sender), ERC7984UnauthorizedUseOfEncryptedAmount(amount, msg.sender));
186
+ require(isOperator(from, msg.sender), ERC7984UnauthorizedSpender(from, msg.sender));
200
187
  transferred = _transferAndCall(from, to, amount, data);
201
188
  FHE.allowTransient(transferred, msg.sender);
202
189
  }
203
190
 
204
191
  /**
205
- * @dev Discloses an encrypted amount `encryptedAmount` publicly via an {IConfidentialFungibleToken-AmountDisclosed}
192
+ * @dev Discloses an encrypted amount `encryptedAmount` publicly via an {IERC7984-AmountDisclosed}
206
193
  * event. The caller and this contract must be authorized to use the encrypted amount on the ACL.
207
194
  *
208
195
  * NOTE: This is an asynchronous operation where the actual decryption happens off-chain and
@@ -210,29 +197,34 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
210
197
  */
211
198
  function discloseEncryptedAmount(euint64 encryptedAmount) public virtual {
212
199
  require(
213
- FHE.isAllowed(encryptedAmount, msg.sender) && FHE.isAllowed(encryptedAmount, address(this)),
214
- ConfidentialFungibleTokenUnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
200
+ FHE.isAllowed(encryptedAmount, msg.sender),
201
+ ERC7984UnauthorizedUseOfEncryptedAmount(encryptedAmount, msg.sender)
215
202
  );
216
203
 
217
204
  bytes32[] memory cts = new bytes32[](1);
218
205
  cts[0] = euint64.unwrap(encryptedAmount);
219
- uint256 requestID = FHE.requestDecryption(cts, this.finalizeDiscloseEncryptedAmount.selector);
220
- _requestHandles[requestID] = encryptedAmount;
206
+ FHE.requestDecryption(cts, this.finalizeDiscloseEncryptedAmount.selector);
221
207
  }
222
208
 
223
- /// @dev Finalizes a disclose encrypted amount request.
209
+ /**
210
+ * @dev Finalizes a disclose encrypted amount request.
211
+ * For gas saving purposes, the `requestId` might not be related to a
212
+ * {discloseEncryptedAmount} request. As a result, the current {finalizeDiscloseEncryptedAmount}
213
+ * function might emit a disclosed amount related to another decryption request context.
214
+ * In this case it would only display public information
215
+ * since the handle would have already been allowed for public decryption through a previous
216
+ * `FHE.requestDecryption` call.
217
+ * The downside of this behavior is that a {finalizeDiscloseEncryptedAmount} watcher might observe
218
+ * unexpected `AmountDisclosed` events.
219
+ */
224
220
  function finalizeDiscloseEncryptedAmount(
225
221
  uint256 requestId,
226
- uint64 amount,
227
- bytes[] memory signatures
222
+ bytes calldata cleartexts,
223
+ bytes calldata decryptionProof
228
224
  ) public virtual {
229
- FHE.checkSignatures(requestId, signatures);
230
-
231
- euint64 requestHandle = _requestHandles[requestId];
232
- require(FHE.isInitialized(requestHandle), ConfidentialFungibleTokenInvalidGatewayRequest(requestId));
233
- emit AmountDisclosed(requestHandle, amount);
234
-
235
- _requestHandles[requestId] = euint64.wrap(0);
225
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
226
+ euint64 requestHandle = euint64.wrap(FHE.loadRequestedHandles(requestId)[0]);
227
+ emit AmountDisclosed(requestHandle, abi.decode(cleartexts, (uint64)));
236
228
  }
237
229
 
238
230
  function _setOperator(address holder, address operator, uint48 until) internal virtual {
@@ -241,18 +233,18 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
241
233
  }
242
234
 
243
235
  function _mint(address to, euint64 amount) internal returns (euint64 transferred) {
244
- require(to != address(0), ConfidentialFungibleTokenInvalidReceiver(address(0)));
236
+ require(to != address(0), ERC7984InvalidReceiver(address(0)));
245
237
  return _update(address(0), to, amount);
246
238
  }
247
239
 
248
240
  function _burn(address from, euint64 amount) internal returns (euint64 transferred) {
249
- require(from != address(0), ConfidentialFungibleTokenInvalidSender(address(0)));
241
+ require(from != address(0), ERC7984InvalidSender(address(0)));
250
242
  return _update(from, address(0), amount);
251
243
  }
252
244
 
253
245
  function _transfer(address from, address to, euint64 amount) internal returns (euint64 transferred) {
254
- require(from != address(0), ConfidentialFungibleTokenInvalidSender(address(0)));
255
- require(to != address(0), ConfidentialFungibleTokenInvalidReceiver(address(0)));
246
+ require(from != address(0), ERC7984InvalidSender(address(0)));
247
+ require(to != address(0), ERC7984InvalidReceiver(address(0)));
256
248
  return _update(from, to, amount);
257
249
  }
258
250
 
@@ -266,7 +258,7 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
266
258
  euint64 sent = _transfer(from, to, amount);
267
259
 
268
260
  // Perform callback
269
- ebool success = ConfidentialFungibleTokenUtils.checkOnTransferReceived(msg.sender, from, to, sent, data);
261
+ ebool success = ERC7984Utils.checkOnTransferReceived(msg.sender, from, to, sent, data);
270
262
 
271
263
  // Try to refund if callback fails
272
264
  euint64 refund = _update(to, from, FHE.select(success, FHE.asEuint64(0), sent));
@@ -283,7 +275,7 @@ abstract contract ConfidentialFungibleToken is IConfidentialFungibleToken {
283
275
  _totalSupply = ptr;
284
276
  } else {
285
277
  euint64 fromBalance = _balances[from];
286
- require(FHE.isInitialized(fromBalance), ConfidentialFungibleTokenZeroBalance(from));
278
+ require(FHE.isInitialized(fromBalance), ERC7984ZeroBalance(from));
287
279
  (success, ptr) = FHESafeMath.tryDecrease(fromBalance, amount);
288
280
  FHE.allowThis(ptr);
289
281
  FHE.allow(ptr, from);