Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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) => {
Expand Down Expand Up @@ -779,10 +781,10 @@ pub fn acl_result_handles(event: &Log<AclContractEvents>) -> Vec<Handle> {
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![],
Expand Down
164 changes: 90 additions & 74 deletions host-contracts/contracts/ACL.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,25 @@ 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 requested expiration date for user decryption delegation is after the next year.
error ExpirationDateAfterOneYear();

/// @notice Returned if the handlesList array is empty.
error HandlesListIsEmpty();
Expand Down Expand Up @@ -97,13 +97,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.
Expand All @@ -114,7 +114,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.
Expand Down Expand Up @@ -224,34 +227,36 @@ 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 (expirationDate < block.timestamp + 1 hours) {
revert ExpirationDateBeforeOneHour();
}
if (expiryDate > block.timestamp + 365 days) {
revert ExpiryDateAfterOneYear();
if (expirationDate > block.timestamp + 365 days) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this check needed to be deleted, after the OZ requirement...
Correct me if i'm wrong cc: @immortal-tofu @0xalexbel

revert ExpirationDateAfterOneYear();
}

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);
Expand All @@ -263,51 +268,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
);
}

/**
Expand All @@ -332,43 +345,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;
}

/**
Expand Down Expand Up @@ -424,6 +416,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.
Expand Down
8 changes: 4 additions & 4 deletions host-contracts/contracts/ACLEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
Loading
Loading