diff --git a/coprocessor/fhevm-engine/host-listener/src/database/tfhe_event_propagate.rs b/coprocessor/fhevm-engine/host-listener/src/database/tfhe_event_propagate.rs index 5359a7c61..a59885298 100644 --- a/coprocessor/fhevm-engine/host-listener/src/database/tfhe_event_propagate.rs +++ b/coprocessor/fhevm-engine/host-listener/src/database/tfhe_event_propagate.rs @@ -551,10 +551,10 @@ impl Database { AclContractEvents::Initialized(initialized) => { warn!(event = ?initialized, "unhandled Acl::Initialized event"); } - AclContractEvents::DelegatedAccount(delegate_account) => { + AclContractEvents::DelegatedForUserDecryption(delegate_account) => { warn!( event = ?delegate_account, - "unhandled Acl::DelegatedAccount event" + "unhandled Acl::DelegatedForUserDecryption event" ); } AclContractEvents::OwnershipTransferStarted( @@ -565,10 +565,12 @@ impl Database { "unhandled Acl::OwnershipTransferStarted event" ); } - AclContractEvents::RevokedDelegation(revoked_delegation) => { + AclContractEvents::RevokedDelegationForUserDecryption( + revoked_delegation, + ) => { warn!( event = ?revoked_delegation, - "unhandled Acl::RevokedDelegation event" + "unhandled Acl::RevokedDelegationForUserDecryption event" ); } AclContractEvents::OwnershipTransferred(ownership_transferred) => { @@ -779,10 +781,10 @@ pub fn acl_result_handles(event: &Log) -> Vec { allowed_for_decryption.handlesList.clone() } AclContractEvents::Initialized(_) - | AclContractEvents::DelegatedAccount(_) + | AclContractEvents::DelegatedForUserDecryption(_) | AclContractEvents::OwnershipTransferStarted(_) | AclContractEvents::OwnershipTransferred(_) - | AclContractEvents::RevokedDelegation(_) + | AclContractEvents::RevokedDelegationForUserDecryption(_) | AclContractEvents::Upgraded(_) | AclContractEvents::Paused(_) | AclContractEvents::Unpaused(_) => vec![], diff --git a/host-contracts/contracts/ACL.sol b/host-contracts/contracts/ACL.sol index 6801ffb17..8399aee55 100644 --- a/host-contracts/contracts/ACL.sol +++ b/host-contracts/contracts/ACL.sol @@ -44,25 +44,22 @@ contract ACL is */ error DelegateCannotBeContractAddress(address contractAddress); - /// @notice Returned if the requested expiry date for delegation is after the next year. - error ExpiryDateAfterOneYear(); - /** - * @notice Returned if the requested expiry date was already set to same expiry for (delegate,contractAddress). + * @notice Returned if the requested expiration date was already set to same expiration for (delegate,contractAddress). * @param delegator The address of the account that delegates access to its handles. * @param delegate The address of the account that receives the delegation. * @param contractAddress The contract address to delegate access to. - * @param expiryDate The expiration date for the intended delegation. + * @param expirationDate The expiration date for the intended delegation. */ - error ExpiryDateAlreadySetToSameValue( + error ExpirationDateAlreadySetToSameValue( address delegator, address delegate, address contractAddress, - uint256 expiryDate + uint256 expirationDate ); - /// @notice Returned if the requested expiry date array is before the next hour. - error ExpiryDateBeforeOneHour(); + /// @notice Returned if the requested expiration date for user decryption delegation is before the next hour. + error ExpirationDateBeforeOneHour(); /// @notice Returned if the handlesList array is empty. error HandlesListIsEmpty(); @@ -97,13 +94,13 @@ contract ACL is error SenderNotAllowed(address sender); /** - * @notice Struct that represents a delegation. + * @notice Struct that represents a user decryption delegation. * @dev The `delegationCounter` is incremented at each delegation or revocation * to allow off-chain clients to track changes. */ - struct Delegation { - /// @notice Date when the delegation expires. - uint64 expiryDate; + struct UserDecryptionDelegation { + /// @notice Date when the user decryption delegation expires. + uint64 expirationDate; /// @notice The last block number when a delegation or revocation happened. uint64 lastBlockDelegateOrRevoke; /// @notice Counter that tracks the order of each delegation or revocation. @@ -114,7 +111,10 @@ contract ACL is struct ACLStorage { mapping(bytes32 handle => mapping(address account => bool isAllowed)) persistedAllowedPairs; mapping(bytes32 handle => bool isAllowedForDecryption) allowedForDecryption; - mapping(address account => mapping(address delegate => mapping(address contractAddress => Delegation delegation))) delegations; + // prettier-ignore + mapping(address account => + mapping(address delegate => mapping(address contractAddress => UserDecryptionDelegation delegation))) + userDecryptionDelegations; } /// @notice Name of the contract. @@ -224,34 +224,33 @@ contract ACL is } /** - * @notice Delegates the access of handles, for instance, in the context of account - * abstraction for issuing user decryption requests from a smart contract account. + * @notice Delegates an account the access to handles for user decryption, for instance, in the context of account + * abstraction for issuing user decryption requests from a smart contract account. * @param delegate The address of the account that receives the delegation. * @param contractAddress The contract address to delegate access to. - * @param expiryDate Expiry date in seconds, between 1 hour and 1 year in the future. + * @param expirationDate Expiration date in seconds, between 1 hour and 1 year in the future. */ - function delegateAccount( + function delegateForUserDecryption( address delegate, address contractAddress, - uint64 expiryDate + uint64 expirationDate ) public virtual whenNotPaused { - if (expiryDate < block.timestamp + 1 hours) { - revert ExpiryDateBeforeOneHour(); - } - if (expiryDate > block.timestamp + 365 days) { - revert ExpiryDateAfterOneYear(); + if (expirationDate < block.timestamp + 1 hours) { + revert ExpirationDateBeforeOneHour(); } ACLStorage storage $ = _getACLStorage(); - Delegation storage delegation = $.delegations[msg.sender][delegate][contractAddress]; + UserDecryptionDelegation storage userDecryptionDelegation = $.userDecryptionDelegations[msg.sender][delegate][ + contractAddress + ]; uint256 blockNumber = block.number; - if (delegation.lastBlockDelegateOrRevoke == blockNumber) { + if (userDecryptionDelegation.lastBlockDelegateOrRevoke == blockNumber) { revert AlreadyDelegatedOrRevokedInSameBlock(msg.sender, delegate, contractAddress, blockNumber); } // Set the last block where the delegation happened. - delegation.lastBlockDelegateOrRevoke = uint64(blockNumber); + userDecryptionDelegation.lastBlockDelegateOrRevoke = uint64(blockNumber); if (contractAddress == msg.sender) { revert SenderCannotBeContractAddress(contractAddress); @@ -263,51 +262,59 @@ contract ACL is revert DelegateCannotBeContractAddress(contractAddress); } - uint64 newExpiryDate = expiryDate; - uint64 oldExpiryDate = delegation.expiryDate; - if (oldExpiryDate == newExpiryDate) { - revert ExpiryDateAlreadySetToSameValue(msg.sender, delegate, contractAddress, oldExpiryDate); + uint64 oldExpirationDate = userDecryptionDelegation.expirationDate; + uint64 newExpirationDate = expirationDate; + if (oldExpirationDate == newExpirationDate) { + revert ExpirationDateAlreadySetToSameValue(msg.sender, delegate, contractAddress, oldExpirationDate); } - // Set the delegation expiry date. - delegation.expiryDate = newExpiryDate; + // Set the delegation expiration date. + userDecryptionDelegation.expirationDate = newExpirationDate; - emit DelegatedAccount( + emit DelegatedForUserDecryption( msg.sender, delegate, contractAddress, - delegation.delegationCounter++, - oldExpiryDate, - newExpiryDate + ++userDecryptionDelegation.delegationCounter, + oldExpirationDate, + newExpirationDate ); } /** - * @notice Revokes delegated access to handles. + * @notice Revokes the access to handles for user decryption delegated to an account. * @param delegate The address of the account that receives the delegation. * @param contractAddress The contract address to delegate access to. */ - function revokeDelegation(address delegate, address contractAddress) public virtual whenNotPaused { + function revokeDelegationForUserDecryption(address delegate, address contractAddress) public virtual whenNotPaused { ACLStorage storage $ = _getACLStorage(); - Delegation storage delegation = $.delegations[msg.sender][delegate][contractAddress]; + UserDecryptionDelegation storage userDecryptionDelegation = $.userDecryptionDelegations[msg.sender][delegate][ + contractAddress + ]; uint256 blockNumber = block.number; - if (delegation.lastBlockDelegateOrRevoke == blockNumber) { + if (userDecryptionDelegation.lastBlockDelegateOrRevoke == blockNumber) { revert AlreadyDelegatedOrRevokedInSameBlock(msg.sender, delegate, contractAddress, blockNumber); } // Set the last block where the revocation happened. - delegation.lastBlockDelegateOrRevoke = uint64(blockNumber); + userDecryptionDelegation.lastBlockDelegateOrRevoke = uint64(blockNumber); - uint64 oldExpiryDate = delegation.expiryDate; - if (oldExpiryDate == 0) { + uint64 oldExpirationDate = userDecryptionDelegation.expirationDate; + if (oldExpirationDate == 0) { revert NotDelegatedYet(msg.sender, delegate, contractAddress); } - // Reset the delegation expiry date. - delegation.expiryDate = 0; + // Reset the delegation expiration date. + userDecryptionDelegation.expirationDate = 0; - emit RevokedDelegation(msg.sender, delegate, contractAddress, delegation.delegationCounter++, oldExpiryDate); + emit RevokedDelegationForUserDecryption( + msg.sender, + delegate, + contractAddress, + ++userDecryptionDelegation.delegationCounter, + oldExpirationDate + ); } /** @@ -332,43 +339,22 @@ contract ACL is } /** - * @notice Returns whether the delegate is allowed to access the handle via delegated user decryption. + * @notice Get the expiration date of a delegation for user decryption. * @param delegate The address of the account that receives the delegation. * @param delegator The address of the account that delegates access to its handles. - * @param handle Handle. * @param contractAddress The contract address to delegate access to. - * @return isAllowed Whether the handle can be accessed. + * @return expirationDate The expiration date for the user decryption delegation (0 means delegation is inactive). */ - function allowedOnBehalf( - address delegate, - address delegator, - address contractAddress, - bytes32 handle - ) public view virtual returns (bool) { - ACLStorage storage $ = _getACLStorage(); - Delegation storage delegation = $.delegations[delegator][delegate][contractAddress]; - return - $.persistedAllowedPairs[handle][delegator] && - $.persistedAllowedPairs[handle][contractAddress] && - delegation.expiryDate >= block.timestamp; - } - - /** - * @notice Get the delegation expiry date. - * @param delegate The address of the account that receives the delegation. - * @param delegator The address of the account that delegates access to its handles. - * @param contractAddress The contract address to delegate access to. - * @return expiryDate the expiryDate (0 means delegation is inactive). - */ - function getDelegationExpiryDate( + function getUserDecryptionDelegationExpirationDate( address delegate, address delegator, address contractAddress ) public view virtual returns (uint64) { ACLStorage storage $ = _getACLStorage(); - Delegation storage delegation = $.delegations[delegator][delegate][contractAddress]; - uint64 expiryDate = delegation.expiryDate; - return expiryDate; + UserDecryptionDelegation storage userDecryptionDelegation = $.userDecryptionDelegations[delegator][delegate][ + contractAddress + ]; + return userDecryptionDelegation.expirationDate; } /** @@ -424,6 +410,30 @@ contract ACL is return $.allowedForDecryption[handle]; } + /** + * @notice Returns whether an account is delegated to access the handle for user decryption. + * @param delegate The address of the account that receives the delegation. + * @param delegator The address of the account that delegates access to its handles. + * @param handle The handle to check for delegated user decryption. + * @param contractAddress The contract address to delegate access to. + * @return isDelegatedForUserDecryption Whether the handle can be accessed for delegated user decryption. + */ + function isHandleDelegatedForUserDecryption( + address delegator, + address delegate, + address contractAddress, + bytes32 handle + ) public view virtual returns (bool) { + ACLStorage storage $ = _getACLStorage(); + UserDecryptionDelegation storage userDecryptionDelegation = $.userDecryptionDelegations[delegator][delegate][ + contractAddress + ]; + return + $.persistedAllowedPairs[handle][delegator] && + $.persistedAllowedPairs[handle][contractAddress] && + userDecryptionDelegation.expirationDate >= block.timestamp; + } + /** * @notice Returns `true` if address `a` is allowed to use `c` and `false` otherwise. * @param handle Handle. diff --git a/host-contracts/contracts/ACLEvents.sol b/host-contracts/contracts/ACLEvents.sol index ea902dddf..35a6d19bd 100644 --- a/host-contracts/contracts/ACLEvents.sol +++ b/host-contracts/contracts/ACLEvents.sol @@ -13,14 +13,14 @@ contract ACLEvents { /// @param handlesList List of handles allowed for decryption. event AllowedForDecryption(address indexed caller, bytes32[] handlesList); - /// @notice Emitted when an account delegation is requested. + /// @notice Emitted when an account is delegated for user decryption. /// @param delegator The address of the account that delegates access to its handles. /// @param delegate The address of the account that receives the delegation. /// @param contractAddress The contract address to delegate access to. /// @param delegationCounter Delegation counter. /// @param oldExpiryDate Previous Expiry Date. /// @param newExpiryDate New Expiry Date. - event DelegatedAccount( + event DelegatedForUserDecryption( address indexed delegator, address indexed delegate, address contractAddress, @@ -29,13 +29,13 @@ contract ACLEvents { uint64 newExpiryDate ); - /// @notice Emitted when a delegation is revoked. + /// @notice Emitted when a delegation for user decryption is revoked. /// @param delegator The address of the account that delegates access to its handles. /// @param delegate The address of the account that receives the delegation. /// @param contractAddress The contract address to delegate access to. /// @param delegationCounter Delegation counter. /// @param oldExpiryDate Previous Expiry Date. - event RevokedDelegation( + event RevokedDelegationForUserDecryption( address indexed delegator, address indexed delegate, address contractAddress, diff --git a/host-contracts/docs/contract_selectors.txt b/host-contracts/docs/contract_selectors.txt index 4f3916f6f..299124b6f 100644 --- a/host-contracts/docs/contract_selectors.txt +++ b/host-contracts/docs/contract_selectors.txt @@ -1,151 +1,149 @@ ACL -╭----------+-----------------------------------------------------------------------+--------------------------------------------------------------------╮ -| Type | Signature | Selector | -+=======================================================================================================================================================+ -| Function | UPGRADE_INTERFACE_VERSION() | 0xad3cb1cc | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | acceptOwnership() | 0x79ba5097 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | allow(bytes32,address) | 0xb9496b62 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | allowForDecryption(bytes32[]) | 0xfadd2246 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | allowTransient(bytes32,address) | 0x3e395cec | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | allowedOnBehalf(address,address,address,bytes32) | 0xf7d20385 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | allowedTransient(bytes32,address) | 0x74b79a5a | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | cleanTransientStorage() | 0x35334c23 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | delegateAccount(address,address,uint64) | 0xe4296c26 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | getDelegationExpiryDate(address,address,address) | 0x946675f1 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | getFHEVMExecutorAddress() | 0x268d6d31 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | getPauserSetAddress() | 0x2490fc9a | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | getVersion() | 0x0d8e6e2c | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | initializeFromEmptyProxy() | 0x39f73810 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | isAllowed(bytes32,address) | 0x82027b6d | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | isAllowedForDecryption(bytes32) | 0xc0d02943 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | isPauser(address) | 0x46fbf68e | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | multicall(bytes[]) | 0xac9650d8 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | owner() | 0x8da5cb5b | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | pause() | 0x8456cb59 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | paused() | 0x5c975abb | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | pendingOwner() | 0xe30c3978 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | persistAllowed(bytes32,address) | 0x1e2f86ba | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | proxiableUUID() | 0x52d1902d | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | reinitializeV2() | 0xc4115874 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | renounceOwnership() | 0x715018a6 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | revokeDelegation(address,address) | 0x785f99c3 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | transferOwnership(address) | 0xf2fde38b | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | unpause() | 0x3f4ba83a | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Function | upgradeToAndCall(address,bytes) | 0x4f1ef286 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | Allowed(address,address,bytes32) | 0xe2e1decee6e05ee246cd7c7f1337d25cdfd41dcbdcf8c57b61630be56cc7366a | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | AllowedForDecryption(address,bytes32[]) | 0xd913ac93a959116526793ef772233273d5249597d33cddfdc34f29920541fd0a | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | DelegatedAccount(address,address,address,uint64,uint64,uint64) | 0x548cdb22ed72bcfa83e87f723c52cb12fde97ca7ebd669370c86b1ccb5e250cc | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | Initialized(uint64) | 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | OwnershipTransferStarted(address,address) | 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | OwnershipTransferred(address,address) | 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | Paused(address) | 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | RevokedDelegation(address,address,address,uint64,uint64) | 0x640c51ed30cf80d32eb5cb883798c5ead298ae2f53608818e4aa298e4ba7931b | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | Unpaused(address) | 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Event | Upgraded(address) | 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | AddressEmptyCode(address) | 0x9996b315 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | AlreadyDelegatedOrRevokedInSameBlock(address,address,address,uint256) | 0xf0ec8aec | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | DelegateCannotBeContractAddress(address) | 0xadf169da | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | ERC1967InvalidImplementation(address) | 0x4c9c8ce3 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | ERC1967NonPayable() | 0xb398979f | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | EnforcedPause() | 0xd93c0665 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | ExpectedPause() | 0x8dfc202b | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | ExpiryDateAfterOneYear() | 0x555ad512 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | ExpiryDateAlreadySetToSameValue(address,address,address,uint256) | 0xf9e1b776 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | ExpiryDateBeforeOneHour() | 0xa8e78e0a | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | FailedCall() | 0xd6bda275 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | HandlesListIsEmpty() | 0x70bd1996 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | InvalidInitialization() | 0xf92ee8a9 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | NotDelegatedYet(address,address,address) | 0xc227e905 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | NotInitializing() | 0xd7e6bcf8 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | NotInitializingFromEmptyProxy() | 0x6f4f731f | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | NotPauser(address) | 0x206a346e | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | OwnableInvalidOwner(address) | 0x1e4fbdf7 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | OwnableUnauthorizedAccount(address) | 0x118cdaa7 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | SenderCannotBeContractAddress(address) | 0x61241b58 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | SenderCannotBeDelegate(address) | 0x230daafc | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | SenderNotAllowed(address) | 0xd0d25976 | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | UUPSUnauthorizedCallContext() | 0xe07c8dba | -|----------+-----------------------------------------------------------------------+--------------------------------------------------------------------| -| Error | UUPSUnsupportedProxiableUUID(bytes32) | 0xaa1d49a4 | -╰----------+-----------------------------------------------------------------------+--------------------------------------------------------------------╯ +╭----------+---------------------------------------------------------------------------+--------------------------------------------------------------------╮ +| Type | Signature | Selector | ++===========================================================================================================================================================+ +| Function | UPGRADE_INTERFACE_VERSION() | 0xad3cb1cc | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | acceptOwnership() | 0x79ba5097 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | allow(bytes32,address) | 0xb9496b62 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | allowForDecryption(bytes32[]) | 0xfadd2246 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | allowTransient(bytes32,address) | 0x3e395cec | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | allowedTransient(bytes32,address) | 0x74b79a5a | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | cleanTransientStorage() | 0x35334c23 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | delegateForUserDecryption(address,address,uint64) | 0x04f61a95 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | getFHEVMExecutorAddress() | 0x268d6d31 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | getPauserSetAddress() | 0x2490fc9a | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | getUserDecryptionDelegationExpirationDate(address,address,address) | 0x3f462dbe | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | getVersion() | 0x0d8e6e2c | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | initializeFromEmptyProxy() | 0x39f73810 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | isAllowed(bytes32,address) | 0x82027b6d | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | isAllowedForDecryption(bytes32) | 0xc0d02943 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | isHandleDelegatedForUserDecryption(address,address,address,bytes32) | 0xd09c0dee | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | isPauser(address) | 0x46fbf68e | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | multicall(bytes[]) | 0xac9650d8 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | owner() | 0x8da5cb5b | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | pause() | 0x8456cb59 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | paused() | 0x5c975abb | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | pendingOwner() | 0xe30c3978 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | persistAllowed(bytes32,address) | 0x1e2f86ba | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | proxiableUUID() | 0x52d1902d | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | reinitializeV2() | 0xc4115874 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | renounceOwnership() | 0x715018a6 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | revokeDelegationForUserDecryption(address,address) | 0x669e6316 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | transferOwnership(address) | 0xf2fde38b | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | unpause() | 0x3f4ba83a | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Function | upgradeToAndCall(address,bytes) | 0x4f1ef286 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | Allowed(address,address,bytes32) | 0xe2e1decee6e05ee246cd7c7f1337d25cdfd41dcbdcf8c57b61630be56cc7366a | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | AllowedForDecryption(address,bytes32[]) | 0xd913ac93a959116526793ef772233273d5249597d33cddfdc34f29920541fd0a | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | DelegatedForUserDecryption(address,address,address,uint64,uint64,uint64) | 0x527b025d7ff06689c1ab9d32dfd7881c964cce72ce8ac5b2fe1d3be8cfda5bfc | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | Initialized(uint64) | 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | OwnershipTransferStarted(address,address) | 0x38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | OwnershipTransferred(address,address) | 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | Paused(address) | 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | RevokedDelegationForUserDecryption(address,address,address,uint64,uint64) | 0x7aca80b6b7928b9038f186e3d9922a0fc5d52c398fbf144725c142c52a5277e4 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | Unpaused(address) | 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | Upgraded(address) | 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | AddressEmptyCode(address) | 0x9996b315 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | AlreadyDelegatedOrRevokedInSameBlock(address,address,address,uint256) | 0xf0ec8aec | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | DelegateCannotBeContractAddress(address) | 0xadf169da | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | ERC1967InvalidImplementation(address) | 0x4c9c8ce3 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | ERC1967NonPayable() | 0xb398979f | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | EnforcedPause() | 0xd93c0665 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | ExpectedPause() | 0x8dfc202b | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | ExpirationDateAlreadySetToSameValue(address,address,address,uint256) | 0x39a48202 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | ExpirationDateBeforeOneHour() | 0xcabc2529 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | FailedCall() | 0xd6bda275 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | HandlesListIsEmpty() | 0x70bd1996 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | InvalidInitialization() | 0xf92ee8a9 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | NotDelegatedYet(address,address,address) | 0xc227e905 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | NotInitializing() | 0xd7e6bcf8 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | NotInitializingFromEmptyProxy() | 0x6f4f731f | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | NotPauser(address) | 0x206a346e | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | OwnableInvalidOwner(address) | 0x1e4fbdf7 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | OwnableUnauthorizedAccount(address) | 0x118cdaa7 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | SenderCannotBeContractAddress(address) | 0x61241b58 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | SenderCannotBeDelegate(address) | 0x230daafc | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | SenderNotAllowed(address) | 0xd0d25976 | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | UUPSUnauthorizedCallContext() | 0xe07c8dba | +|----------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Error | UUPSUnsupportedProxiableUUID(bytes32) | 0xaa1d49a4 | +╰----------+---------------------------------------------------------------------------+--------------------------------------------------------------------╯ ACLEvents -╭-------+----------------------------------------------------------------+--------------------------------------------------------------------╮ -| Type | Signature | Selector | -+=============================================================================================================================================+ -| Event | Allowed(address,address,bytes32) | 0xe2e1decee6e05ee246cd7c7f1337d25cdfd41dcbdcf8c57b61630be56cc7366a | -|-------+----------------------------------------------------------------+--------------------------------------------------------------------| -| Event | AllowedForDecryption(address,bytes32[]) | 0xd913ac93a959116526793ef772233273d5249597d33cddfdc34f29920541fd0a | -|-------+----------------------------------------------------------------+--------------------------------------------------------------------| -| Event | DelegatedAccount(address,address,address,uint64,uint64,uint64) | 0x548cdb22ed72bcfa83e87f723c52cb12fde97ca7ebd669370c86b1ccb5e250cc | -|-------+----------------------------------------------------------------+--------------------------------------------------------------------| -| Event | RevokedDelegation(address,address,address,uint64,uint64) | 0x640c51ed30cf80d32eb5cb883798c5ead298ae2f53608818e4aa298e4ba7931b | -╰-------+----------------------------------------------------------------+--------------------------------------------------------------------╯ +╭-------+---------------------------------------------------------------------------+--------------------------------------------------------------------╮ +| Type | Signature | Selector | ++========================================================================================================================================================+ +| Event | Allowed(address,address,bytes32) | 0xe2e1decee6e05ee246cd7c7f1337d25cdfd41dcbdcf8c57b61630be56cc7366a | +|-------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | AllowedForDecryption(address,bytes32[]) | 0xd913ac93a959116526793ef772233273d5249597d33cddfdc34f29920541fd0a | +|-------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | DelegatedForUserDecryption(address,address,address,uint64,uint64,uint64) | 0x527b025d7ff06689c1ab9d32dfd7881c964cce72ce8ac5b2fe1d3be8cfda5bfc | +|-------+---------------------------------------------------------------------------+--------------------------------------------------------------------| +| Event | RevokedDelegationForUserDecryption(address,address,address,uint64,uint64) | 0x7aca80b6b7928b9038f186e3d9922a0fc5d52c398fbf144725c142c52a5277e4 | +╰-------+---------------------------------------------------------------------------+--------------------------------------------------------------------╯ FHEEvents diff --git a/host-contracts/test/acl/acl.t.sol b/host-contracts/test/acl/acl.t.sol index 3ba8384a6..a9e014ef2 100644 --- a/host-contracts/test/acl/acl.t.sol +++ b/host-contracts/test/acl/acl.t.sol @@ -11,8 +11,19 @@ import {ACLEvents} from "../../contracts/ACLEvents.sol"; import {EmptyUUPSProxyACL} from "../../contracts/emptyProxyACL/EmptyUUPSProxyACL.sol"; import {fhevmExecutorAdd, pauserSetAdd, aclAdd} from "../../addresses/FHEVMHostAddresses.sol"; +contract MockACL is ACL { + function getUserDecryptionDelegation( + address delegator, + address delegate, + address contractAddress + ) public view returns (UserDecryptionDelegation memory) { + ACLStorage storage $ = _getACLStorage(); + return $.userDecryptionDelegations[delegator][delegate][contractAddress]; + } +} + contract ACLTest is Test { - ACL internal acl; + MockACL internal acl; PauserSet internal pauserSet; address internal constant owner = address(456); @@ -23,7 +34,7 @@ contract ACLTest is Test { address internal fhevmExecutor; /** - * @dev Grants permissions for a hnadle for an account for testing purposes. + * @dev Grants permissions for a handle for an account for testing purposes. * * @param handle The handle identifier. * @param account The account to grant permissions to. @@ -37,9 +48,9 @@ contract ACLTest is Test { } function _upgradeProxy() internal { - implementation = address(new ACL()); + implementation = address(new MockACL()); UnsafeUpgrades.upgradeProxy(proxy, implementation, abi.encodeCall(acl.initializeFromEmptyProxy, ()), owner); - acl = ACL(proxy); + acl = MockACL(proxy); fhevmExecutor = acl.getFHEVMExecutorAddress(); } @@ -176,7 +187,7 @@ contract ACLTest is Test { * @dev Tests that the sender can delegate to another account only if both contract and sender addresses are allowed * to use the handle. */ - function test_CanDelegateAccountButItIsAllowedOnBehalfOnlyIfBothContractAndSenderAreAllowed( + function test_CanDelegateForUserDecryptionAndIsHandleDelegatedForUserDecryptionOnlyIfBothContractAndSenderAreAllowed( bytes32 handle, address sender, address delegate, @@ -187,50 +198,60 @@ contract ACLTest is Test { vm.assume(sender != delegate); vm.assume(delegate != contractAddress); - ACL.Delegation memory delegation; - uint64 expiryDate = uint64(block.timestamp) + 7 hours; - uint64 oldExpiryDate = delegation.expiryDate; - uint64 newExpiryDate = expiryDate; - uint64 delegationCounter = delegation.delegationCounter++; + ACL.UserDecryptionDelegation memory userDecryptionDelegation; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; + uint64 oldExpirationDate = userDecryptionDelegation.expirationDate; + uint64 newExpirationDate = expirationDate; vm.prank(sender); vm.expectEmit(address(acl)); - emit ACLEvents.DelegatedAccount( + emit ACLEvents.DelegatedForUserDecryption( sender, delegate, contractAddress, - delegationCounter, - oldExpiryDate, - newExpiryDate + ++userDecryptionDelegation.delegationCounter, + oldExpirationDate, + newExpirationDate ); - acl.delegateAccount(delegate, contractAddress, expiryDate); - vm.assertFalse(acl.allowedOnBehalf(delegate, sender, contractAddress, handle)); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); - /// @dev The sender and the delegate contract must be allowed to use the handle before it delegates. + /// @dev Check that even that the delegation was made, neither the delegator nor the contract are allowed to use the handle. + vm.assertFalse(acl.isHandleDelegatedForUserDecryption(sender, delegate, contractAddress, handle)); + + /// @dev The delegator and the contract must be allowed to use the handle before it delegates. _allowHandle(handle, sender); - vm.assertFalse(acl.allowedOnBehalf(delegate, sender, contractAddress, handle)); + vm.assertFalse(acl.isHandleDelegatedForUserDecryption(sender, delegate, contractAddress, handle)); _allowHandle(handle, contractAddress); - vm.assertTrue(acl.allowedOnBehalf(delegate, sender, contractAddress, handle)); + vm.assertTrue(acl.isHandleDelegatedForUserDecryption(sender, delegate, contractAddress, handle)); + + /// @dev Check that the delegation is stored correctly. + ACL.UserDecryptionDelegation memory storedUserDecryptionDelegation = acl.getUserDecryptionDelegation( + sender, + delegate, + contractAddress + ); + assertEq(storedUserDecryptionDelegation.expirationDate, expirationDate); + assertEq(storedUserDecryptionDelegation.delegationCounter, userDecryptionDelegation.delegationCounter); } /** * @dev Tests that the sender cannot delegate in the same block twice. */ - function test_CannotDelegateAccountInSameBlockTwice( + function test_CannotDelegateForUserDecryptionInSameBlockTwice( bytes32 handle, address sender, address delegate, address contractAddress ) public { /// @dev We call the other test to avoid repeating the same code. - test_CanDelegateAccountButItIsAllowedOnBehalfOnlyIfBothContractAndSenderAreAllowed( + test_CanDelegateForUserDecryptionAndIsHandleDelegatedForUserDecryptionOnlyIfBothContractAndSenderAreAllowed( handle, sender, delegate, contractAddress ); - uint64 expiryDate = uint64(block.timestamp) + 7 hours; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; vm.prank(sender); vm.expectRevert( @@ -242,27 +263,31 @@ contract ACLTest is Test { block.number ) ); - acl.delegateAccount(delegate, contractAddress, expiryDate); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); } /** - * @dev Tests that the sender cannot delegate account if delegate and contract address are the same. + * @dev Tests that the sender cannot delegate for user decryption if delegate and contract address are the same. */ - function test_CannotDelegateAccountForSameDelegateAndContractAddress(address sender, address delegate) public { + function test_CannotDelegateForUserDecryptionForSameDelegateAndContractAddress( + address sender, + address delegate + ) public { _upgradeProxy(); vm.assume(sender != delegate); - uint64 expiryDate = uint64(block.timestamp) + 7 hours; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; vm.prank(sender); vm.expectRevert(abi.encodeWithSelector(ACL.DelegateCannotBeContractAddress.selector, delegate)); - acl.delegateAccount(delegate, delegate, expiryDate); + acl.delegateForUserDecryption(delegate, delegate, expirationDate); } /** - * @dev Tests that the sender cannot delegate with expiry date before one hour. + * @dev Tests that the user decryption delegation cannot be created with the same expiration date. */ - function test_CannotDelegateAccountWithExpiryDateBeforeOneHour( + function test_CannotDelegateUserDecryptionWithSameExpirationDate( + bytes32 handle, address sender, address delegate, address contractAddress @@ -272,17 +297,32 @@ contract ACLTest is Test { vm.assume(sender != delegate); vm.assume(delegate != contractAddress); - uint64 expiryDate = uint64(block.timestamp); + /// @dev Delegate user decryption for the first time. + uint64 expirationDate = uint64(block.timestamp) + 7 hours; + vm.prank(sender); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); + + /// @dev Increase block number to avoid "AlreadyDelegatedOrRevokedInSameBlock" error. + vm.roll(block.number + 1); + /// @dev Delegate user decryption for the second time with the same expiration date. vm.prank(sender); - vm.expectRevert(ACL.ExpiryDateBeforeOneHour.selector); - acl.delegateAccount(delegate, contractAddress, expiryDate); + vm.expectRevert( + abi.encodeWithSelector( + ACL.ExpirationDateAlreadySetToSameValue.selector, + sender, + delegate, + contractAddress, + expirationDate + ) + ); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); } /** - * @dev Tests that the sender cannot delegate with expiry date after one year. + * @dev Tests that the sender cannot delegate for user decryption with expiration date before one hour. */ - function test_CannotDelegateAccountWithExpiryDateAfterOneYear( + function test_CannotDelegateForUserDecryptionWithExpirationDateBeforeOneHour( address sender, address delegate, address contractAddress @@ -292,11 +332,11 @@ contract ACLTest is Test { vm.assume(sender != delegate); vm.assume(delegate != contractAddress); - uint64 expiryDate = uint64(block.timestamp) + 366 days; + uint64 expirationDate = uint64(block.timestamp); vm.prank(sender); - vm.expectRevert(ACL.ExpiryDateAfterOneYear.selector); - acl.delegateAccount(delegate, contractAddress, expiryDate); + vm.expectRevert(ACL.ExpirationDateBeforeOneHour.selector); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); } /** @@ -304,11 +344,11 @@ contract ACLTest is Test { */ function test_CannotDelegateIfSenderIsContractAddress(address sender, address delegate) public { _upgradeProxy(); - uint64 expiryDate = uint64(block.timestamp) + 7 hours; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; vm.prank(sender); vm.expectRevert(abi.encodeWithSelector(ACL.SenderCannotBeContractAddress.selector, sender)); - acl.delegateAccount(delegate, sender, expiryDate); + acl.delegateForUserDecryption(delegate, sender, expirationDate); } /** @@ -317,18 +357,17 @@ contract ACLTest is Test { function test_CannotDelegateIfSenderIsDelegate(address sender, address contractAddress) public { _upgradeProxy(); vm.assume(sender != contractAddress); - uint64 expiryDate = uint64(block.timestamp) + 7 hours; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; vm.prank(sender); vm.expectRevert(abi.encodeWithSelector(ACL.SenderCannotBeDelegate.selector, sender)); - acl.delegateAccount(sender, contractAddress, expiryDate); + acl.delegateForUserDecryption(sender, contractAddress, expirationDate); } /** - * @dev Tests that the sender cannot delegate if account is not allowed to use the handle. + * @dev Tests that the sender can revoke delegation for user decryption if the sender has already delegated. */ - function test_CannotDelegateAccountIfAccountNotAllowed( - bytes32 handle, + function test_CanRevokeDelegationForUserDecryption( address sender, address delegate, address contractAddress @@ -337,56 +376,104 @@ contract ACLTest is Test { vm.assume(sender != contractAddress); vm.assume(sender != delegate); vm.assume(delegate != contractAddress); - /// @dev Only the delegate contract must be allowed to use the handle before it delegates. - _allowHandle(handle, contractAddress); - ACL.Delegation memory delegation; - uint64 expiryDate = uint64(block.timestamp) + 7 hours; - uint64 oldExpiryDate = delegation.expiryDate; - uint64 newExpiryDate = expiryDate; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; + uint64 oldExpirationDate = expirationDate; + + /// @dev Delegate the account first. + vm.prank(sender); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); + + /// @dev After delegation above, the counter should be 2. + uint64 revokeDelegationCounter = 2; + + /// @dev Increase block number to avoid "AlreadyDelegatedOrRevokedInSameBlock" error. + vm.roll(block.number + 1); vm.prank(sender); vm.expectEmit(address(acl)); - emit ACLEvents.DelegatedAccount( + emit ACLEvents.RevokedDelegationForUserDecryption( sender, delegate, contractAddress, - delegation.delegationCounter++, - oldExpiryDate, - newExpiryDate + revokeDelegationCounter, + oldExpirationDate ); + acl.revokeDelegationForUserDecryption(delegate, contractAddress); - acl.delegateAccount(delegate, contractAddress, expiryDate); - - vm.assertFalse(acl.allowedOnBehalf(delegate, sender, contractAddress, handle)); + /// @dev Check that the delegation is stored correctly after revocation. + ACL.UserDecryptionDelegation memory storedUserDecryptionDelegation = acl.getUserDecryptionDelegation( + sender, + delegate, + contractAddress + ); + assertEq(storedUserDecryptionDelegation.expirationDate, 0); + assertEq(storedUserDecryptionDelegation.delegationCounter, revokeDelegationCounter); } /** - * @dev Tests that the sender can revoke delegation if the sender has already delegated. + * @dev Tests that the delegation and revocation counter is stored in a sequential order. */ - function test_CanRevokeDelegation(address sender, address delegate, address contractAddress) public { + function test_UserDecryptionDelegationAndRevocationCounterIsSequential( + bytes32 handle, + address sender, + address delegate, + address contractAddress + ) public { _upgradeProxy(); vm.assume(sender != contractAddress); vm.assume(sender != delegate); vm.assume(delegate != contractAddress); + uint64 userDecryptionDelegationCounter = 0; - uint64 expiryDate = uint64(block.timestamp) + 7 hours; - uint64 oldExpiryDate = expiryDate; + /// @dev Delegate user decryption for the first time. + uint64 expirationDate = uint64(block.timestamp) + 3 hours; + vm.prank(sender); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); + ACL.UserDecryptionDelegation memory userDecryptionDelegation = acl.getUserDecryptionDelegation( + sender, + delegate, + contractAddress + ); + assertEq(userDecryptionDelegation.delegationCounter, ++userDecryptionDelegationCounter); - /// @dev Delegate the account first. + /// @dev Increase block number to avoid "AlreadyDelegatedOrRevokedInSameBlock" error. + vm.roll(block.number + 1); + + /// @dev Delegate user decryption for the second time. + expirationDate = uint64(block.timestamp) + 5 hours; vm.prank(sender); - acl.delegateAccount(delegate, contractAddress, expiryDate); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); + userDecryptionDelegation = acl.getUserDecryptionDelegation(sender, delegate, contractAddress); + assertEq(userDecryptionDelegation.delegationCounter, ++userDecryptionDelegationCounter); - // After delegation above, the counter should be 1. - uint64 delegationCounter = 1; + /// @dev Increase block number to avoid "AlreadyDelegatedOrRevokedInSameBlock" error. + vm.roll(block.number + 1); + + /// @dev Revoke user decryption delegation for the first time. + vm.prank(sender); + acl.revokeDelegationForUserDecryption(delegate, contractAddress); + userDecryptionDelegation = acl.getUserDecryptionDelegation(sender, delegate, contractAddress); + assertEq(userDecryptionDelegation.delegationCounter, ++userDecryptionDelegationCounter); - // Increase block number to avoid "AlreadyDelegatedOrRevokedInSameBlock" error. + /// @dev Increase block number to avoid "AlreadyDelegatedOrRevokedInSameBlock" error. vm.roll(block.number + 1); + /// @dev Delegate user decryption for the second time. + expirationDate = uint64(block.timestamp) + 7 hours; vm.prank(sender); - vm.expectEmit(address(acl)); - emit ACLEvents.RevokedDelegation(sender, delegate, contractAddress, delegationCounter, oldExpiryDate); - acl.revokeDelegation(delegate, contractAddress); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); + userDecryptionDelegation = acl.getUserDecryptionDelegation(sender, delegate, contractAddress); + assertEq(userDecryptionDelegation.delegationCounter, ++userDecryptionDelegationCounter); + + /// @dev Increase block number to avoid "AlreadyDelegatedOrRevokedInSameBlock" error. + vm.roll(block.number + 1); + + /// @dev Revoke user decryption delegation for the second time. + vm.prank(sender); + acl.revokeDelegationForUserDecryption(delegate, contractAddress); + userDecryptionDelegation = acl.getUserDecryptionDelegation(sender, delegate, contractAddress); + assertEq(userDecryptionDelegation.delegationCounter, ++userDecryptionDelegationCounter); } /** @@ -402,7 +489,7 @@ contract ACLTest is Test { vm.prank(sender); vm.expectRevert(abi.encodeWithSelector(ACL.NotDelegatedYet.selector, sender, delegate, contractAddress)); - acl.revokeDelegation(delegate, contractAddress); + acl.revokeDelegationForUserDecryption(delegate, contractAddress); } /** @@ -560,47 +647,55 @@ contract ACLTest is Test { } /** - * @dev Tests that delegateAccount() cannot be called if the contract is paused. + * @dev Tests that user decryption delegation cannot be called if the contract is paused. */ - function test_CannotDelegateAccountIfPaused(address sender, address delegate, address contractAddress) public { + function test_CannotDelegateForUserDecryptionIfPaused( + address sender, + address delegate, + address contractAddress + ) public { _upgradeProxy(); vm.assume(sender != contractAddress); vm.assume(sender != delegate); vm.assume(delegate != contractAddress); - uint64 expiryDate = uint64(block.timestamp) + 7 hours; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; vm.prank(sender); - acl.delegateAccount(delegate, contractAddress, expiryDate); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); vm.prank(pauser); acl.pause(); vm.prank(sender); vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); - acl.delegateAccount(delegate, contractAddress, expiryDate); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); } /** - * @dev Tests that revokeDelegation() cannot be called if the contract is paused. + * @dev Tests that revoke delegation for user decryption cannot be called if the contract is paused. */ - function test_CannotRevokeDelegationIfPaused(address sender, address delegate, address contractAddress) public { + function test_CannotRevokeDelegationForUserDecryptionIfPaused( + address sender, + address delegate, + address contractAddress + ) public { _upgradeProxy(); vm.assume(sender != contractAddress); vm.assume(sender != delegate); vm.assume(delegate != contractAddress); - uint64 expiryDate = uint64(block.timestamp) + 7 hours; + uint64 expirationDate = uint64(block.timestamp) + 7 hours; vm.prank(sender); - acl.delegateAccount(delegate, contractAddress, expiryDate); + acl.delegateForUserDecryption(delegate, contractAddress, expirationDate); vm.prank(pauser); acl.pause(); vm.prank(sender); vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); - acl.revokeDelegation(delegate, contractAddress); + acl.revokeDelegationForUserDecryption(delegate, contractAddress); } /**