diff --git a/contracts/contracts/ACL.sol b/contracts/contracts/ACL.sol index 4930b8c..7a9254c 100644 --- a/contracts/contracts/ACL.sol +++ b/contracts/contracts/ACL.sol @@ -7,6 +7,13 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import "../addresses/TFHEExecutorAddress.sol"; +/** + * @title ACL + * @notice The ACL (Access Control List) is a permission management system designed to + * control who can access, compute on, or decrypt encrypted values in fhEVM. + * By defining and enforcing these permissions, the ACL ensures that encrypted data remains secure while still being usable + * within authorized contexts. + */ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { /// @notice Returned if the delegatee contract is already delegatee for sender & delegator addresses. error AlreadyDelegated(); @@ -14,17 +21,33 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { /// @notice Returned if the sender is the delegatee address. error SenderCannotBeDelegateeAddress(); - /// @notice Returned if the sender address is not allowed for allow operations. + /// @notice Returned if the sender address is not allowed for allow operations. + /// @param sender Sender address. error SenderNotAllowed(address sender); - /// @notice Name of the contract + /// @notice Emitted when a list of handles is allowed for decryption. + /// @param handlesList List of handles allowed for decryption. + event AllowedForDecryption(uint256[] handlesList); + + /// @notice Emitted when a new delegate address is added. + /// @param sender Sender address + /// @param delegatee Delegatee address. + /// @param contractAddress Contract address. + event NewDelegation(address indexed sender, address indexed delegatee, address indexed contractAddress); + + /// @notice Name of the contract. string private constant CONTRACT_NAME = "ACL"; - /// @notice Version of the contract + /// @notice Major version of the contract. uint256 private constant MAJOR_VERSION = 0; + + /// @notice Minor version of the contract. uint256 private constant MINOR_VERSION = 1; + + /// @notice Patch version of the contract. uint256 private constant PATCH_VERSION = 0; + /// @notice TFHEExecutor address. address private constant tfheExecutorAddress = tfheExecutorAdd; /// @custom:storage-location erc7201:fhevm.storage.ACL @@ -37,20 +60,22 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { /// @dev keccak256(abi.encode(uint256(keccak256("fhevm.storage.ACL")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ACLStorageLocation = 0xa688f31953c2015baaf8c0a488ee1ee22eb0e05273cc1fd31ea4cbee42febc00; + /// @dev Returns the ACL storage location. function _getACLStorage() internal pure returns (ACLStorage storage $) { assembly { $.slot := ACLStorageLocation } } - /// @notice Getter function for the TFHEExecutor contract address + /// @notice Getter function for the TFHEExecutor contract address. + /// @return tfheExecutorAddress Address of the TFHEExecutor. function getTFHEExecutorAddress() public view virtual returns (address) { return tfheExecutorAddress; } - event NewDelegation(address indexed sender, address indexed delegatee, address indexed contractAddress); - event AllowedForDecryption(uint256[] handlesList); - + /** + * @dev Should revert when `msg.sender` is not authorized to upgrade the contract. + */ function _authorizeUpgrade(address _newImplementation) internal virtual override onlyOwner {} /// @custom:oz-upgrades-unsafe-allow constructor @@ -58,14 +83,19 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { _disableInitializers(); } - /// @notice Initializes the contract setting `initialOwner` as the initial owner + /** + * @notice Initializes the contract. + * @param initialOwner Initial owner address. + */ function initialize(address initialOwner) external initializer { __Ownable_init(initialOwner); } - // allowTransient use of `handle` for address `account`. - // The caller must be allowed to use `handle` for allowTransient() to succeed. If not, allowTransient() reverts. - // @note: The Coprocessor contract can always `allowTransient`, contrarily to `allow` + /** + * @notice Allows the use of `handle` by address `account` for this transaction. + * @dev The caller must be allowed to use `handle` for allowTransient() to succeed. If not, allowTransient() reverts. + * The Coprocessor contract can always `allowTransient`, contrarily to `allow`. + */ function allowTransient(uint256 handle, address account) public virtual { if (msg.sender != tfheExecutorAddress) { if (!isAllowed(handle, msg.sender)) { @@ -82,6 +112,9 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { } } + /** + * @notice Checks whether the account is allowed to use the handle in the same transaction (transient). + */ function allowedTransient(uint256 handle, address account) public view virtual returns (bool) { bool isAllowedTransient; bytes32 key = keccak256(abi.encodePacked(handle, account)); @@ -112,8 +145,10 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { } } - // Allow use of `handle` for address `account`. - // The caller must be allowed to use `handle` for allow() to succeed. If not, allow() reverts. + /** + * @notice Allows the use of `handle` for the address `account`. + * @dev The caller must be allowed to use `handle` for allow() to succeed. If not, allow() reverts. + */ function allow(uint256 handle, address account) external virtual { ACLStorage storage $ = _getACLStorage(); if (!isAllowed(handle, msg.sender)) { @@ -122,18 +157,27 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { $.persistedAllowedPairs[handle][account] = true; } - // Returns true if address `a` is allowed to use `c` and false otherwise. + /** + * @notice Returns `true` if address `a` is allowed to use `c` and `false` otherwise. + */ function persistAllowed(uint256 handle, address account) public view virtual returns (bool) { ACLStorage storage $ = _getACLStorage(); return $.persistedAllowedPairs[handle][account]; } - // Useful in the context of account abstraction for issuing reencryption requests from a smart contract account + /** + * @notice Returns whether the account is allowed to use the `handle` in the context of account + * abstraction for issuing reencryption requests from a smart contract account. + */ function isAllowed(uint256 handle, address account) public view virtual returns (bool) { return allowedTransient(handle, account) || persistAllowed(handle, account); } - function delegateAccountForContract(address delegatee, address delegateeContract) external virtual { + /** + * @notice Delegate the access of `handles` in the context of account abstraction for issuing reencryption + * requests from a smart contract account. + */ + function delegateAccount(address delegatee, address delegateeContract) external virtual { if (delegateeContract == msg.sender) { revert SenderCannotBeDelegateeAddress(); } @@ -142,10 +186,14 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { if ($.delegates[msg.sender][delegatee][delegateeContract]) { revert AlreadyDelegated(); } + $.delegates[msg.sender][delegatee][delegateeContract] = true; emit NewDelegation(msg.sender, delegatee, delegateeContract); } + /** + * @notice Returns whether the delegatee is allowed to access the handle. + */ function allowedOnBehalf( address delegatee, uint256 handle, @@ -159,6 +207,10 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { $.delegates[account][delegatee][contractAddress]; } + /** + * @notice Allows a list of handles to be decrypted. + * @param handlesList List of handles. + */ function allowForDecryption(uint256[] memory handlesList) external virtual { uint256 len = handlesList.length; ACLStorage storage $ = _getACLStorage(); @@ -172,13 +224,19 @@ contract ACL is UUPSUpgradeable, Ownable2StepUpgradeable { emit AllowedForDecryption(handlesList); } + /** + * @notice Checks whether a handle is allowed for decryption. + * @param handle Handle. + */ function isAllowedForDecryption(uint256 handle) public view virtual returns (bool) { ACLStorage storage $ = _getACLStorage(); return $.allowedForDecryption[handle]; } - /// @notice Getter for the name and version of the contract - /// @return string representing the name and the version of the contract + /** + * @notice Getter for the name and version of the contract. + * @return string Name and the version of the contract. + */ function getVersion() external pure virtual returns (string memory) { return string(