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

feat: privileged subdaos #NTRN-211 #99

Merged
merged 19 commits into from
May 13, 2024
Merged

Conversation

zavgorodnii
Copy link
Contributor

@zavgorodnii zavgorodnii commented Jan 22, 2024

Overview

This PR implements the privileged SubDAOs design (look up the Privileged SubDAOs RFC in Notion for full details).

Important note: this PR implements an example strategy for new style parameter updates (only Cron module). However, changing the parameters of this module is not going to work until the PR to the core repo is merged and we upgrade the mainnet, because, unfortunately, we forgot to allow querying cron module parameters with stargate, and chain manager really needs to query those params. All other functionality will work without upgrading the chain.

Integration tests

neutron-org/neutron-integration-tests#266

Successful test run: https://github.com/neutron-org/neutron-tests/actions/runs/7919615589
Successful test run (post-review 1): https://github.com/neutron-org/neutron-tests/actions/runs/8055334942

  1. All existing tests are updated to know about the new layout of the chain administration (which also tests that ALLOW_ALL strategy works properly, since the Neutron DAO core contract is the only address with this type of strategy),
  2. Added a test for changing parameters of the cron module by a subdao (new style parameter updates),
  3. Added a test for changing parameters of the globalfee module by a subdao (old style style parameter updates).

Rehearsal scenario

  1. Fork the mainnet,
  2. Upload & instantiate the neutron-chain-manager contract with the ALLOW_ALL initial_strategy for the Neutron DAO core contract,
  3. Instantiate the Global Fee SubDAO (timelocked, multisig) with a single member,
  4. Create a proposal in the Neutron DAO to add an ALLOW_ONLY strategy for the Global Fee subdao's core contract (only allows to change the MinimumGasPricesParam),
  5. Create a proposal in the Neutron DAO to add the neutron-chain-manager contract to the list of chain admins and to remove the Neutron DAO contract from the list of chain admins,
  6. Create & execute a proposal in the Global Fee SubDAO to change the MinimumGasPricesParam, then check that the parameter was actually changed.

@zavgorodnii zavgorodnii changed the base branch from main to sdk-47 January 22, 2024 16:36
@zavgorodnii zavgorodnii changed the title feat: privileged subdaos [#NTRN-211] feat: privileged subdaos #NTRN-211 Feb 7, 2024
@zavgorodnii zavgorodnii marked this pull request as ready for review February 15, 2024 22:17
) -> Result<(), ContractError> {
match neutron_msg {
NeutronMsg::AddSchedule {
name: _,
Copy link
Contributor

Choose a reason for hiding this comment

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

you can ignore all the variables with ..

}
}

fn get_allow_all_count(deps: Deps) -> Result<u64, ContractError> {
Copy link
Contributor

@swelf19 swelf19 Feb 27, 2024

Choose a reason for hiding this comment

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

Do you ever need to count all allow_all? Simple find seems enough, instead of iterating over all the strategies.

) -> Result<Response, ContractError> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

if let Strategy::AllowOnly(_) = msg.initial_strategy {
Copy link
Contributor

Choose a reason for hiding this comment

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

If the only AllowAll allowed as initial strategy, why do you ever need the message param at all? Just set AllowAll for initial address.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i see your point, but I don't think that it's worth the effort.

pub struct ProposalExecuteMessageJSON {
#[serde(rename = "@type")]
pub type_field: String,
pub authority: String,
Copy link
Contributor

@swelf19 swelf19 Feb 27, 2024

Choose a reason for hiding this comment

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

You never use authority field, i think it's unnecessary field

let typed_proposal: ProposalExecuteMessageJSON =
serde_json_wasm::from_str(proposal.message.as_str())?;

if typed_proposal.type_field.as_str() == "/neutron.cron.MsgUpdateParams" {
Copy link
Contributor

Choose a reason for hiding this comment

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

You could use a const for the message type value.

Comment on lines 134 to 141
Ok(strategy) => {
if let Strategy::AllowOnly(_) = strategy {
return Err(ContractError::Unauthorized {});
}

Ok(())
}
Err(_) => Err(ContractError::Unauthorized {}),
Copy link
Contributor

Choose a reason for hiding this comment

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

it's a bit easier to read, from my point of view

Suggested change
Ok(strategy) => {
if let Strategy::AllowOnly(_) = strategy {
return Err(ContractError::Unauthorized {});
}
Ok(())
}
Err(_) => Err(ContractError::Unauthorized {}),
Ok(Strategy::AllowAll) => Ok(()),
_ => Err(ContractError::Unauthorized {})

Copy link
Contributor Author

Choose a reason for hiding this comment

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

didn't even know you could do this. thanks

Comment on lines 126 to 127
ParamChangePermission(ParamChangePermission),
UpdateParamsPermission(UpdateParamsPermission),
Copy link
Contributor

Choose a reason for hiding this comment

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

Pls add a comment which describes the difference between two sets of permissions.

Copy link
Contributor

@NeverHappened NeverHappened left a comment

Choose a reason for hiding this comment

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

lgtm, awaiting rehearsal

Copy link
Contributor

@sotnikov-s sotnikov-s left a comment

Choose a reason for hiding this comment

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

just in case we'll be making small improvements:

Comment on lines 50 to 60
Strategy::AllowOnly(permissions) => {
let mut has_permission = false;
for permission in permissions {
if let Permission::CronPermission(cron_permission) = permission {
has_permission = cron_permission.add_schedule
}
}

has_permission
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

we could just return cron_permission.add_schedule in the if let Permission::CronPermission(cron_permission) = permission closure similar to has_param_change_permission. this would

  1. shorten the code
  2. make an instant return on matched value (now we continue iterating over permissions even if we've already matched the respective one)

same in has_cron_remove_schedule_permission

@pr0n00gler pr0n00gler changed the base branch from sdk-47 to main March 26, 2024 12:44
@pr0n00gler
Copy link
Collaborator

@pr0n00gler pr0n00gler merged commit af56c72 into main May 13, 2024
9 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.

6 participants