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

Allow admin to pause/unpause subdao #744

Merged
merged 13 commits into from
Mar 25, 2024

Conversation

ismellike
Copy link
Contributor

Also fixed some typos and removed unused msg.rs from dao-dao-core

#737

Also fixed some typos and removed unused msg.rs from dao-dao-core
The only way the DAO can unpause is through an admin that is not itself
Copy link
Member

@JakeHartnell JakeHartnell left a comment

Choose a reason for hiding this comment

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

Only one small comments on tests and then we can get this in!

Also, ignore the lints, have a fix for those.

Sometimes new rust versions break CI.

Copy link
Member

@NoahSaso NoahSaso left a comment

Choose a reason for hiding this comment

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

sick! i think i found one line that needs fixing, and it seems like you need to format (cargo fmt --all -- --check)

also, it wouldn't hurt to add a test that random person cannot unpause as well, not just the DAO itself

update: i was wrong, no fix needed other than the format

contracts/dao-dao-core/src/contract.rs Show resolved Hide resolved
Copy link
Collaborator

@bekauz bekauz left a comment

Choose a reason for hiding this comment

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

overall lgtm!

that being said, it would be great to add some extended testing for this. as mentioned in comment, imho adding some tests that would combine the pausing/unpausing logic with a veto committee would be a good way to make sure we aren't introducing some potential chaos here.

contracts/dao-dao-core/src/contract.rs Outdated Show resolved Hide resolved
contracts/dao-dao-core/src/contract.rs Outdated Show resolved Hide resolved
contracts/dao-dao-core/src/contract.rs Outdated Show resolved Hide resolved
@bekauz
Copy link
Collaborator

bekauz commented Feb 2, 2024

also now that i think of it, i'm not sure how i feel about the fact that pausing / unpausing can be done by different parties. don't have a solution off the top of my head right now, but something to think about.

@JakeHartnell
Copy link
Member

also now that i think of it, i'm not sure how i feel about the fact that pausing / unpausing can be done by different parties. don't have a solution off the top of my head right now, but something to think about.

Had similar thoughts initially, but eventually warmed up to it as a nice change that Neutron introduced. This feature is most relevant in the context of SubDAOs. For DAOs without an admin, nothing changes. As a parent DAO is in full control of its SubDAOs, it makes sense that that control should also extend to pausing and unpausing a SubDAO.

For example, the Juno Charter has departments that may become inactive due to lack of members or activity. Rather than having to do all the work of moving around treasuries, vesting, etc., the SubDAO can simply enter a paused state until the parent DAO decides what to do with it.

The Parent DAO (admin) can already pause a SubDAO, I think it is useful and safest to allow them to unpause it. To be clear there is only one party that can unpause it, and that is the Parent DAO. Otherwise, nothing changes.

@bekauz
Copy link
Collaborator

bekauz commented Feb 3, 2024

that makes sense!

@NoahSaso
Copy link
Member

this is really interesting; i have some thoughts! sorry for the long ass brain dump but i want to make sure we know exactly what we're doing, and this is me working it out out loud 😁

both allowing the parent DAO and DAO itself to bypass the pause, AND moving the paused check to execute_proposal_hook, effectively change the behavior of what pause is

before: "lock contract, frozen until expiration or forever if no expiration set"
after: "prevent proposals from being able to execute anything"

interestingly, proposals can still be created and voted on. they just won't be executable until the DAO is unpaused. i think this is fine, and we can disable proposal creation in the UI while paused to enforce the expected behavior that you shouldn't be creating proposals in a paused DAO.

our goals (what we want from pause):

  • ensure DAO or parent DAO can pause the DAO in case of emergency
  • ensure DAO or parent DAO can indefinitely lock the DAO, likely upon DAO death
  • ensure parent DAO can unpause a paused DAO
  • ensure parent DAO can operate on the DAO while paused (in order to rescue assets, update membership, etc.)

all of these are achieved by both allowing the parent and DAO itself to call execute while paused (and no one else), AND moving the pause logic to the proposal execution hook.

something else to consider though: authz allows an account to execute on behalf of another account. if the DAO has authorized (authz granted) a wallet the authority to do something as the DAO, there is no way for us to prevent action being taken while paused, since the wallet authz executes as the DAO itself. we cannot prevent the wallet from updating membership, for example, since the voting module would allow that if it comes from the DAO when authz executed by the wallet. we also couldn't prevent the wallet from calling messages on the DAO itself, IFF we allow the DAO to execute messages on itself (which we have to allow if we want to let the parent tell the DAO to execute messages while paused, like to add/remove a voting or proposal module). now, it'd be very silly for a DAO to give generic authz power on or as the DAO to a wallet—that effectively sets them as admin, so maybe it's not a case we really need to design for, but we should definitely know how it will interact with this pause logic. most likely, DAO-given authz will be for very specific actions, like trading on a DEX or managing staking. in these instances, we can't do anything about them anyways, and the DAO/parent needs to know to revoke any outstanding authz grants when they go to pause. that is something the UI can help solve, and there's nothing the contracts can do about it either way. additionally, a DAO may want to give a trusted wallet or DAO (maybe a security SubDAO) the ability to pause/unpause using authz, so in all cases we must allow both the parent DAO and DAO itself to bypass the pause and execute things, as long as the proposal hook is blocked.

so the question really is: should pausing simply mean halting the governance process (by disallowing proposal module execution)? i think that sounds right, but now i'm curious what @0xekez had in mind at the beginning when putting the auth logic at the top level like this. since there was no ability to unpause early and no ability for the parent to execute while paused, it acts as a complete emergency freeze until the expiration (or indefinitely if no expiration). if we want to give the parent DAO the power to execute as the DAO and on the DAO, which it seems like we do, we are changing what paused means—and we need to allow the parent DAO to execute at least execute_admin_msgs as well as the DAO itself to execute anything (so the parent DAO can use execute_admin_msgs to update config, voting modules, etc.).

it seems that both keeping the paused logic in the top-level execute function (with the addition that the parent and DAO itself can still execute anything) and simply moving the paused logic to the execute_proposal_hook function have the same security guarantees.

wdyt @ismellike @JakeHartnell @bekauz ?

@bekauz
Copy link
Collaborator

bekauz commented Mar 1, 2024

it'd be very silly for a DAO to give generic authz power on or as the DAO to a wallet—that effectively sets them as admin, so maybe it's not a case we really need to design for

really great point about authz. completely flew over my head.

my immediate thought after reading through this again would be to design this flow with the assumption that DAO gave generic (or some more restrictive but still critical) authz power to some wallet. while it's unlikely and unwise, i totally echo this:

we should definitely know how it will interact with this pause logic

@NoahSaso could we revoke all authorizations on pause? should we? just pondering here.

@bekauz
Copy link
Collaborator

bekauz commented Mar 1, 2024

one more doomer thought regarding the authz revoking above:

the number of things that we need to consider when adding features like this makes me somewhat paranoid of getting to the point where adding something new will require us explicitly addressing numerous other features previously added without considering something like this. not sure if this constitutes feature creep, internal dependency hell (is that a thing?), or something else, but i think you get what i mean. veto feature was giving me similar feelings at the start, but ended up being quite encapsulated.

@NoahSaso
Copy link
Member

NoahSaso commented Mar 2, 2024

@NoahSaso could we revoke all authorizations on pause? should we? just pondering here.

nope 🤩

i don't think we can force the DAO to revoke all authorizations on pause without adding some way to register all of the authorizations that already exist. even if we did that, i suspect we'd run into gas limit issues if too many authorizations had been granted, thereby preventing pausing.

instead, this is something we should surface in the UI when attempting to pause. we can display all outstanding authorizations to make it clear that certain executions will still be possible, and even prompt to add actions to revoke them all in the same proposal.

one more doomer thought regarding the authz revoking above:

the number of things that we need to consider when adding features like this makes me somewhat paranoid of getting to the point where adding something new will require us explicitly addressing numerous other features previously added without considering something like this. not sure if this constitutes feature creep, internal dependency hell (is that a thing?), or something else, but i think you get what i mean. veto feature was giving me similar feelings at the start, but ended up being quite encapsulated.

yeah... i think we are choosing to play the game on hard mode here. we can't avoid this problem if we want to add features. we should strongly seek to solve problems without modifying the core contract when possible, but pause has to be done directly like this. i mean, pause should really be the only feature that has to be implemented so bluntly like this. most other features have to do with proposal and voting modules.

we should be paranoid. we're building smart contracts that give the users full power to change anything about the contract and its relationship to other accounts. most other contracts aren't susceptible to this because they don't allow generic message executions, but we're basically creating a passthrough contract with some wrapper logic. i think this is the best we can do 🤷🏻‍♂️

@NoahSaso
Copy link
Member

NoahSaso commented Mar 8, 2024

alright @ismellike, i think we're good to go on moving the paused check back to the beginning of the execution function, and skipping it if the sender is the admin or the DAO itself :D

@ismellike ismellike requested a review from NoahSaso March 18, 2024 17:00
Copy link
Member

@NoahSaso NoahSaso left a comment

Choose a reason for hiding this comment

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

nice! one more thing

contracts/dao-dao-core/src/contract.rs Outdated Show resolved Hide resolved
@NoahSaso
Copy link
Member

seems like you need to recreate the schema and then the linter will pass

Copy link
Member

@NoahSaso NoahSaso left a comment

Choose a reason for hiding this comment

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

SICK GREAT WORK GREAT DISCUSSIONS EVERYONE

@NoahSaso NoahSaso merged commit 8f37dc8 into DA0-DA0:development Mar 25, 2024
3 of 4 checks passed
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.

4 participants