Skip to content

Commit

Permalink
sketched parsing of raw json payloads for ProposalExecuteMessage
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Zavgorodnii committed Feb 2, 2024
1 parent f008ebd commit 90100ef
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 42 deletions.
1 change: 1 addition & 0 deletions contracts/dao/neutron-chain-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ schemars = "0.8.8"
serde = {version = "1.0.175", default-features = false, features = ["derive"]}
thiserror = {version = "1.0"}
neutron-sdk = "0.8.0"
serde-json-wasm = "1.0.1"

[dev-dependencies]
anyhow = "1.0.57"
Expand Down
55 changes: 30 additions & 25 deletions contracts/dao/neutron-chain-manager/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use cw2::set_contract_version;
use neutron_sdk::bindings::msg::{AdminProposal, NeutronMsg};

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, Strategy};
use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, MsgUpdateParamsCron, ProposalExecuteMessageJSON, QueryMsg, Strategy};
use crate::state::{STRATEGIES_ALLOW_ALL, STRATEGIES_ALLOW_ONLY};

pub(crate) const CONTRACT_NAME: &str = "crates.io:neutron-chain-manager";
Expand Down Expand Up @@ -44,7 +44,7 @@ pub fn execute(
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
) -> Result<Response<NeutronMsg>, ContractError> {
match msg {
ExecuteMsg::AddStrategy { strategy } => execute_add_strategy(deps, info, strategy),
ExecuteMsg::RemoveStrategy { address } => execute_remove_strategy(deps, info, address),
Expand All @@ -58,7 +58,7 @@ pub fn execute_add_strategy(
deps: DepsMut,
info: MessageInfo,
strategy: Strategy,
) -> Result<Response, ContractError> {
) -> Result<Response<NeutronMsg>, ContractError> {
if !STRATEGIES_ALLOW_ALL.has(deps.storage, info.sender) {
return Err(ContractError::Unauthorized {});
}
Expand Down Expand Up @@ -92,7 +92,7 @@ pub fn execute_remove_strategy(
deps: DepsMut,
info: MessageInfo,
address: Addr,
) -> Result<Response, ContractError> {
) -> Result<Response<NeutronMsg>, ContractError> {
if !STRATEGIES_ALLOW_ALL.has(deps.storage, info.sender) {
return Err(ContractError::Unauthorized {});
}
Expand Down Expand Up @@ -121,53 +121,58 @@ pub fn execute_execute_messages(
.add_attribute("action", "execute_execute_messages")
.add_attribute("strategy", "allow_all")
.add_attribute("address", info.sender.clone())
.add_messages(messages))
.add_messages(messages));
}

if !STRATEGIES_ALLOW_ONLY.has(deps.storage, info.sender.clone()) {
return Err(ContractError::Unauthorized {})
return Err(ContractError::Unauthorized {});
}

let strategy = STRATEGIES_ALLOW_ONLY.load(deps.storage, info.sender)?;
let strategy = STRATEGIES_ALLOW_ONLY.load(deps.storage, info.sender.clone())?;
// For every message, check whether we have the permission to execute it.
// Any missing permission aborts the execution.
for msg in messages {
for msg in messages.clone() {
match msg {
CosmosMsg::Custom(neutron_msg) => {
match neutron_msg {
NeutronMsg::AddSchedule => {
NeutronMsg::AddSchedule {name: _, period: _, msgs: _} => {
if !strategy.has_cron_add_schedule_permission() {
return Err(ContractError::Unauthorized {})
return Err(ContractError::Unauthorized {});
}
}
NeutronMsg::RemoveSchedule => {
NeutronMsg::RemoveSchedule {name: _} => {
if !strategy.has_cron_remove_schedule_permission() {
return Err(ContractError::Unauthorized {})
return Err(ContractError::Unauthorized {});
}
}
NeutronMsg::SubmitAdminProposal{admin_proposal} => {
match admin_proposal {
AdminProposal::ParamChangeProposal(proposal) => {
for param_change in proposal.param_changes {
if !strategy.has_param_change_permission(param_change) {
return Err(ContractError::Unauthorized {})
}
NeutronMsg::SubmitAdminProposal { admin_proposal } => match admin_proposal {
AdminProposal::ParamChangeProposal(proposal) => {
for param_change in proposal.param_changes {
if !strategy.has_param_change_permission(param_change) {
return Err(ContractError::Unauthorized {});
}
},
AdminProposal::ProposalExecuteMessage(proposal) => {
}
}
AdminProposal::ProposalExecuteMessage(proposal) => {
let typed_proposal: ProposalExecuteMessageJSON = serde_json_wasm::from_str(proposal.message.as_str())?;

match typed_proposal.type_field.as_str() {
"/neutron.cron.MsgUpdateParams" => {
let msg_update_params: MsgUpdateParamsCron = serde_json_wasm::from_str(proposal.message.as_str())?;
println!("{} -------- {}", msg_update_params.params.limit, msg_update_params.params.security_address)
}
_ => {}
}
_ => {}
}
}
_ => {}
},
_ => {}
}
}
},
_ => {}
}
}


Ok(Response::new()
.add_attribute("action", "execute_execute_messages")
.add_attribute("strategy", "allow_only")
Expand Down
10 changes: 10 additions & 0 deletions contracts/dao/neutron-chain-manager/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,14 @@ pub enum ContractError {

#[error("InvalidDemotion")]
InvalidDemotion {},

// A variant for serde_json_wasm deserialization errors.
#[error("Deserialization error: {0}")]
DeserializationError(String),
}

impl From<serde_json_wasm::de::Error> for ContractError {
fn from(err: serde_json_wasm::de::Error) -> ContractError {
ContractError::DeserializationError(err.to_string())
}
}
50 changes: 35 additions & 15 deletions contracts/dao/neutron-chain-manager/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use cosmwasm_std::{Addr, CosmosMsg};
use neutron_sdk::bindings::msg::{NeutronMsg, ParamChange};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::error::ContractError;

#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
pub struct InstantiateMsg {
Expand Down Expand Up @@ -43,37 +42,36 @@ pub struct Strategy {

impl Strategy {
pub fn has_cron_add_schedule_permission(&self) -> bool {
for permission in self.permissions {
let mut has_permission = false;
for permission in &self.permissions {
match permission {
Permission::CronPermission(cron_permission) => {
cron_permission.add_schedule
}
Permission::CronPermission(cron_permission) => {has_permission = cron_permission.add_schedule},
_ => {}
}
}

false
has_permission
}
pub fn has_cron_remove_schedule_permission(&self) -> bool {
for permission in self.permissions {
let mut has_permission = false;
for permission in self.permissions.clone() {
match permission {
Permission::CronPermission(cron_permission) => {
cron_permission.remove_schedule
}
Permission::CronPermission(cron_permission) => {has_permission = cron_permission.remove_schedule},
_ => {}
}
}

false
has_permission
}
pub fn has_param_change_permission(&self, param_change: ParamChange) -> bool {
for permission in self.permissions {
for permission in self.permissions.clone() {
match permission {
Permission::ParamChangePermission(param_change_permissions) => {
for param_change_permission in param_change_permissions.params {
if param_change.subspace == param_change_permission.subspace &&
param_change.key == param_change_permission.key {
return true
if param_change.subspace == param_change_permission.subspace
&& param_change.key == param_change_permission.key
{
return true;
}
}
}
Expand Down Expand Up @@ -120,3 +118,25 @@ pub struct CronPermission {
pub add_schedule: bool,
pub remove_schedule: bool,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ProposalExecuteMessageJSON {
#[serde(rename = "@type")]
pub type_field: String,
pub authority: String,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct MsgUpdateParamsCron {
pub params: ParamsCron
}


#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ParamsCron {
pub security_address: String,
pub limit: u64,
}
26 changes: 24 additions & 2 deletions contracts/dao/neutron-chain-manager/src/testing/tests.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::contract::{execute_add_strategy, execute_remove_strategy, instantiate};
use crate::error::ContractError::{InvalidDemotion, InvalidInitialStrategy, Unauthorized};
use crate::msg::CronPermission as CronPermissionType;
use crate::msg::{CronPermission as CronPermissionType, MsgUpdateParamsCron, ProposalExecuteMessageJSON};
use crate::msg::Permission::CronPermission;
use crate::msg::{InstantiateMsg, Strategy};
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::Addr;
use cosmwasm_std::{Addr, CosmosMsg};
use neutron_sdk::bindings::msg::{AdminProposal, NeutronMsg, ProposalExecuteMessage};

#[test]
fn test_instantiate() {
Expand Down Expand Up @@ -313,3 +314,24 @@ fn test_remove_strategy_invalid_demotion() {
.unwrap_err();
assert_eq!(err, InvalidDemotion {});
}

#[test]
pub fn test_execute_execute_message() {
let _msg = CosmosMsg::Custom(NeutronMsg::SubmitAdminProposal {
admin_proposal: AdminProposal::ProposalExecuteMessage(ProposalExecuteMessage {
message: r#"{"@type":"/neutron.cron.MsgUpdateParams", "authority":"neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", "params": {"security_address": "neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", "limit": 16}}"#.to_string(),
}),
});

// let json_message = r#"{"@type":"/neutron.cron.MsgUpdateParams", "authority":"neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", "params": {"security_address": "neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", "limit": 16}}"#;
// let typed_proposal_payload: ProposalExecuteMessageJSON = serde_json::from_str(json_message).unwrap();
// println!("{:?}", typed_proposal_payload);
//
// match typed_proposal_payload.type_field.as_str() {
// "/neutron.cron.MsgUpdateParams" => {
// let msg_update_params: MsgUpdateParamsCron = serde_json::from_str(json_message).unwrap();
// println!("{} -------- {}", msg_update_params.params.limit, msg_update_params.params.security_address)
// }
// _ => {}
// }
}

0 comments on commit 90100ef

Please sign in to comment.