Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ManagedAllowList #255

Merged
merged 22 commits into from
May 17, 2024

Conversation

piotr-roslaniec
Copy link
Contributor

@piotr-roslaniec piotr-roslaniec commented Apr 15, 2024

Type of PR:

  • Feature

Required reviews:

  • 3

What this does:

High-level idea of the changes introduced in this PR.
List relevant API changes (if any), as well as related PRs and issues.

Issues fixed/closed:

  • Fixes #...

Why it's needed:

Explain how this PR fits in the greater context of the NuCypher Network.
E.g., if this PR address a nucypher/productdev issue, let reviewers know!

Notes for reviewers:

@piotr-roslaniec piotr-roslaniec force-pushed the managed-allow-list branch 4 times, most recently from 75a4eb9 to 639e38a Compare April 15, 2024 18:55
@piotr-roslaniec
Copy link
Contributor Author

Hi @cygnusv, @vzotova - I asked for a review of this draft to make sure I'm on the right path with everything. Please let me know what you think.

Copy link
Member

@vzotova vzotova left a comment

Choose a reason for hiding this comment

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

couple high level and style questions:

contracts/contracts/coordination/GlobalAllowList.sol Outdated Show resolved Hide resolved
contracts/contracts/coordination/GlobalAllowList.sol Outdated Show resolved Hide resolved
contracts/contracts/coordination/ManagedAllowList.sol Outdated Show resolved Hide resolved
contracts/contracts/coordination/ManagedAllowList.sol Outdated Show resolved Hide resolved
// If we want to authorize an address, we need to check if the authorization cap has been exceeded
// If we want to deauthorize an address, we don't need to check the authorization cap
require(
!value ||
Copy link
Member

Choose a reason for hiding this comment

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

can we extract check of value before loop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. But I'm not sure about the business logic here. Should deauthorizations count towards billable authActions? I'm going to assume yes for the time being and remove the require on value. CC: @cygnusv

contracts/contracts/coordination/Subscription.sol Outdated Show resolved Hide resolved
contracts/contracts/coordination/Subscription.sol Outdated Show resolved Hide resolved
@piotr-roslaniec
Copy link
Contributor Author

Requesting review from @arjunhassard and @cygnusv to make sure this matches business logic as outlined in #257

Copy link
Member

@cygnusv cygnusv left a comment

Choose a reason for hiding this comment

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

Thanks for this @piotr-roslaniec! I think this is a great starting point also for the Subscription stuff laid out in #264

}

/**
* @notice Calculates the available amount of fees that can be withdrawn be the beneficiary
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* @notice Calculates the available amount of fees that can be withdrawn be the beneficiary
* @notice Calculates the available amount of fees that can be withdrawn by the beneficiary

* @param encryptor The address of the encryptor
* @return The key used to lookup authorizations
*/
function lookupKey(uint32 ritualId, address encryptor) internal pure returns (bytes32) {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think encryptor applies here anymore since this method is also used for administrator addresses, spender addresses etc. Should we use a more generic name eg. anAddress or associatedAddress or ...

Copy link
Member

Choose a reason for hiding this comment

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

It's true it's not strictly accurate here, but the hierarchy of roles/names is getting quite unwieldy. Maybe we can rename encryptor --> encryptAdmin and then rename this admin or anAdmin.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this is a library code and is re-used in a couple of places, perhaps we should rename it to just _address. encryptor and admin are terms from specific contexts.

Comment on lines +17 to +18
mnaged_allow_list = deployer.deploy(project.ManagedAllowList)
deployments = [mnaged_allow_list]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
mnaged_allow_list = deployer.deploy(project.ManagedAllowList)
deployments = [mnaged_allow_list]
managed_allow_list = deployer.deploy(project.ManagedAllowList)
deployments = [managed_allow_list]

Comment on lines +94 to +98
for (uint256 i = 0; i < addresses.length; i++) {
require(
authActions[ritualId] <
subscription.authorizationActionsCap(ritualId, addresses[i]),
"Authorization cap exceeded"
Copy link
Member

@derekpierre derekpierre May 15, 2024

Choose a reason for hiding this comment

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

I may be misunderstanding, but this logic is a little unclear to me:

  • Should we only be checking caps if value is True i.e. we are authorizing? If deauthorizing (i.e. value is False), there are no caps.
  • I'm unclear what we are checking in the require statement. canSetAuthorizations already checks whether the sender is a valid admin for the ritual - great, but I assumed here you need to check 2 things (not in a loop):
    1. the remaining allowance for the admin making the authorization request (i.e. sender) allows for the set of encryptor addresses to be authorized, so:
    require(getAllowance(ritualId, msg.sender) >= addresses.length, "Administrator cap exceeded")
    1. That the total cap across all administrators for a specific ritual is not being exceeded, so:
    require(authActions[ritualId] >= addresses.length, "Ritual-wide cap exceeded")

Copy link
Member

@derekpierre derekpierre May 15, 2024

Choose a reason for hiding this comment

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

My calls may be wrong above ^, but the pseudocode I'm looking for is:
i. remaining allowance for administrator for ritual >= the number of encryptor addresses to authorize
ii. remaining allowed actions for ritual (based on cap) >= the number of encryptor addresses to authorize

Copy link
Member

Choose a reason for hiding this comment

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

the remaining allowance for the admin making the authorization request (i.e. sender) allows for the set of encryptor addresses to be authorized, so:

This maybe needs to call a partner-defined contract, so they can write their own logic for limits placed on authAdmins?

Copy link
Contributor Author

@piotr-roslaniec piotr-roslaniec May 16, 2024

Choose a reason for hiding this comment

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

Just to give more context, I wasn't sure how to use value here: Should setting authorization to false (so, removing authorization) count towards billable actions?

We may treat adding and removing authorization differently, but I think it's application-specific (the frequency of actions, but also the application-specific meaning of authorizing/deauthorizing)

emit AddressAuthorizationSet(ritualId, addresses[i], value);
}

authActions[ritualId] += addresses.length;
Copy link
Member

Choose a reason for hiding this comment

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

Is incrementing only applicable if value is True? If value is False should this be decrementing instead?

Copy link
Member

Choose a reason for hiding this comment

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

For this version, the goal was to charge per action, regardless if it's authorizing or deauthorizing. But more recent variations proposed to some adopters will use something different (e.g. charging for authorized slots). I think we can leave it as is because it's only a starting point anyway, and the more recent design of subscription contracts will refactor everything

Copy link
Member

Choose a reason for hiding this comment

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

👍 I see, so every action (authorize or deauthorize) is a charge.

Copy link
Member

Choose a reason for hiding this comment

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

I'm confused about the relationship between value and charging for authorizations/deauthorizations.

Doesn't * @param value The authorization status imply that this is just a boolean check as to whether the ritualID is active? (Separately, what is the evidence that confirms this?)

As @cygnusv mentions, we're not charging for authorizations/deauthorizations, these are unlimited and can be executed at will – and the cohortAdmin/sponsor pays the gas, possibly passing that cost to an authAdmin (btw, do we have an estimate for how much this will be per action? how much is saved by batching?)

I guess #253 will cover the rules of adding/removing encryptor credits (or 'slots') and we can leave the option of charging for authorizations/deauthorizations in some later version.

Copy link
Member

@arjunhassard arjunhassard left a comment

Choose a reason for hiding this comment

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

Excellent work, think you can claim to be at least somewhat-versed in Solidity now.

Still quite a few things to clarify and decide, particularly with respect to #253-driven refactoring. I suggest we do a PR walkthrough, maybe on Friday?

require(coordinator.isRitualActive(ritualId), "Only active rituals can add authorizations");
require(coordinator.isRitualActive(ritualId), "Only active rituals can set authorizations");

require(addresses.length <= MAX_AUTH_ACTIONS, "Too many addresses");
Copy link
Member

Choose a reason for hiding this comment

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

Is this a maximum per batch of authorizations?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, per one setAuthorizations call

emit AddressAuthorizationSet(ritualId, addresses[i], value);
}

authActions[ritualId] += addresses.length;
Copy link
Member

Choose a reason for hiding this comment

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

I'm confused about the relationship between value and charging for authorizations/deauthorizations.

Doesn't * @param value The authorization status imply that this is just a boolean check as to whether the ritualID is active? (Separately, what is the evidence that confirms this?)

As @cygnusv mentions, we're not charging for authorizations/deauthorizations, these are unlimited and can be executed at will – and the cohortAdmin/sponsor pays the gas, possibly passing that cost to an authAdmin (btw, do we have an estimate for how much this will be per action? how much is saved by batching?)

I guess #253 will cover the rules of adding/removing encryptor credits (or 'slots') and we can leave the option of charging for authorizations/deauthorizations in some later version.

Comment on lines +94 to +98
for (uint256 i = 0; i < addresses.length; i++) {
require(
authActions[ritualId] <
subscription.authorizationActionsCap(ritualId, addresses[i]),
"Authorization cap exceeded"
Copy link
Member

Choose a reason for hiding this comment

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

the remaining allowance for the admin making the authorization request (i.e. sender) allows for the set of encryptor addresses to be authorized, so:

This maybe needs to call a partner-defined contract, so they can write their own logic for limits placed on authAdmins?

* @param encryptor The address of the encryptor
* @return The key used to lookup authorizations
*/
function lookupKey(uint32 ritualId, address encryptor) internal pure returns (bytes32) {
Copy link
Member

Choose a reason for hiding this comment

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

It's true it's not strictly accurate here, but the hierarchy of roles/names is getting quite unwieldy. Maybe we can rename encryptor --> encryptAdmin and then rename this admin or anAdmin.

@cygnusv
Copy link
Member

cygnusv commented May 16, 2024

@arjunhassard @derekpierre The work @vzotova is doing on #264 will be based directly on this (as you can see in #265, Vicky is already working on top of this PR). The plan we laid out is that this is good foundational work, but that will require a lot of changes in light of the recent design for Subscriptions and the newer requirements for the AllowList contract. I propose we merge this now, either as-is or with minor changes (like renames).

@vzotova vzotova changed the base branch from main to epic-subscription May 17, 2024 15:19
@vzotova vzotova mentioned this pull request May 17, 2024
7 tasks
@vzotova vzotova merged commit df671df into nucypher:epic-subscription May 17, 2024
2 checks passed
@cygnusv cygnusv mentioned this pull request May 24, 2024
7 tasks
@derekpierre derekpierre mentioned this pull request Aug 12, 2024
23 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants