22
33pragma solidity ^ 0.8.27 ;
44
5- import {FHE, ebool, externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol " ;
5+ import {FHE, externalEuint64, euint64} from "@fhevm/solidity/lib/FHE.sol " ;
66import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol " ;
77import {ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol " ;
88import {Multicall} from "@openzeppelin/contracts/utils/Multicall.sol " ;
99import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol " ;
1010import {IERC7984 } from "./../../../interfaces/IERC7984.sol " ;
1111import {IERC7984Rwa } from "./../../../interfaces/IERC7984Rwa.sol " ;
12+ import {FHESafeMath} from "./../../../utils/FHESafeMath.sol " ;
1213import {ERC7984 } from "./../ERC7984.sol " ;
1314import {ERC7984Freezable } from "./ERC7984Freezable.sol " ;
1415import {ERC7984Restricted } from "./ERC7984Restricted.sol " ;
@@ -17,15 +18,7 @@ import {ERC7984Restricted} from "./ERC7984Restricted.sol";
1718 * @dev Extension of {ERC7984} that supports confidential Real World Assets (RWAs).
1819 * This interface provides compliance checks, transfer controls and enforcement actions.
1920 */
20- abstract contract ERC7984Rwa is
21- ERC7984 ,
22- ERC7984Freezable ,
23- ERC7984Restricted ,
24- Pausable ,
25- Multicall ,
26- ERC165 ,
27- AccessControl
28- {
21+ abstract contract ERC7984Rwa is ERC7984Freezable , ERC7984Restricted , Pausable , Multicall , ERC165 , AccessControl {
2922 bytes32 public constant AGENT_ROLE = keccak256 ("AGENT_ROLE " );
3023 // bytes4(keccak256("forceConfidentialTransferFrom(address,address,bytes32)"))
3124 bytes4 private constant FORCE_CONFIDENTIAL_TRANSFER_FROM_SIG = 0x6c9c3c85 ;
@@ -183,15 +176,21 @@ abstract contract ERC7984Rwa is
183176 address from ,
184177 address to ,
185178 euint64 encryptedAmount
186- ) internal override (ERC7984Freezable , ERC7984Restricted , ERC7984 ) whenNotPaused returns (euint64) {
179+ ) internal override (ERC7984Freezable , ERC7984Restricted ) whenNotPaused returns (euint64) {
187180 // frozen and restriction checks performed through inheritance
188181 return super ._update (from, to, encryptedAmount);
189182 }
190183
191184 /// @dev Internal function which forces transfer of confidential amount of tokens from account to account by skipping compliance checks.
192185 function _forceUpdate (address from , address to , euint64 encryptedAmount ) internal virtual returns (euint64) {
186+ euint64 senderFrozenAmount = confidentialFrozen (from);
187+ if (FHE.isInitialized (senderFrozenAmount)) {
188+ (, euint64 newFrozen ) = FHESafeMath.tryDecrease (senderFrozenAmount, encryptedAmount);
189+ _setConfidentialFrozen (from, newFrozen);
190+ }
191+
193192 // bypassing `from` restriction check with {_checkSenderRestriction}
194- // bypassing `from` frozen check with {_checkSenderAmountNotFrozenBeforeUpdate }
193+ // bypassing `from` frozen check with {confidentialAvailable }
195194 return super ._update (from, to, encryptedAmount); // still performing `to` restriction check
196195 }
197196
@@ -205,17 +204,12 @@ abstract contract ERC7984Rwa is
205204 super ._checkSenderRestriction (account);
206205 }
207206
208- /**
209- * @dev Bypasses the frozen check of the `from` account when performing a {forceConfidentialTransferFrom}.
210- */
211- function _checkSenderAmountNotFrozenBeforeUpdate (
212- address account ,
213- euint64 encryptedAmount
214- ) internal override returns (euint64) {
207+ function confidentialAvailable (address account ) public virtual override returns (euint64) {
215208 if (_isForceTransfer ()) {
216- return encryptedAmount;
209+ return confidentialBalanceOf (account);
210+ } else {
211+ return super .confidentialAvailable (account);
217212 }
218- return super ._checkSenderAmountNotFrozenBeforeUpdate (account, encryptedAmount);
219213 }
220214
221215 /// @dev Private function which checks if the called function is a {forceConfidentialTransferFrom}.
0 commit comments