diff --git a/Makefile b/Makefile index 9b99a985..7523cdbe 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ fmt: @cargo fmt -- --check check_contracts: - @cargo install cosmwasm-check --locked + @cargo install cosmwasm-check --version 2.0.4 --locked @cosmwasm-check --available-capabilities iterator,staking,stargate,neutron artifacts/*.wasm compile: diff --git a/contracts/dao/neutron-chain-manager/schema/neutron-chain-manager.json b/contracts/dao/neutron-chain-manager/schema/neutron-chain-manager.json index 9498e026..f681c60f 100644 --- a/contracts/dao/neutron-chain-manager/schema/neutron-chain-manager.json +++ b/contracts/dao/neutron-chain-manager/schema/neutron-chain-manager.json @@ -439,31 +439,8 @@ "additionalProperties": false }, { - "type": "object", - "required": [ - "staking" - ], - "properties": { - "staking": { - "$ref": "#/definitions/StakingMsg" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "distribution" - ], - "properties": { - "distribution": { - "$ref": "#/definitions/DistributionMsg" - } - }, - "additionalProperties": false - }, - { - "description": "A Stargate message encoded the same way as a protobuf [Any](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). This is the same structure as messages in `TxBody` from [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md)", + "description": "This is the same structure as messages in `TxBody` from [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md)", + "deprecated": true, "type": "object", "required": [ "stargate" @@ -909,57 +886,32 @@ } ] }, - "DistributionMsg": { - "description": "The message types of the distribution module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto", - "oneOf": [ - { - "description": "This is translated to a [MsgSetWithdrawAddress](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L29-L37). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "set_withdraw_address" - ], - "properties": { - "set_withdraw_address": { - "type": "object", - "required": [ - "address" - ], - "properties": { - "address": { - "description": "The `withdraw_address`", - "type": "string" - } - } - } - }, - "additionalProperties": false + "DexUpdateParamsPermission": { + "type": "object", + "required": [ + "fee_tiers", + "good_til_purge_allowance", + "max_jits_per_block", + "paused" + ], + "properties": { + "fee_tiers": { + "type": "boolean" }, - { - "description": "This is translated to a [[MsgWithdrawDelegatorReward](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L42-L50). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "withdraw_delegator_reward" - ], - "properties": { - "withdraw_delegator_reward": { - "type": "object", - "required": [ - "validator" - ], - "properties": { - "validator": { - "description": "The `validator_address`", - "type": "string" - } - } - } - }, - "additionalProperties": false + "good_til_purge_allowance": { + "type": "boolean" + }, + "max_jits_per_block": { + "type": "boolean" + }, + "paused": { + "type": "boolean" } - ] + }, + "additionalProperties": false }, "GovMsg": { - "description": "This message type allows the contract interact with the [x/gov] module in order to cast votes.\n\n[x/gov]: https://github.com/cosmos/cosmos-sdk/tree/v0.45.12/x/gov\n\n## Examples\n\nCast a simple vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); use cosmwasm_std::{GovMsg, VoteOption};\n\n#[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::Vote { proposal_id: 4, vote: VoteOption::Yes, })) } ```\n\nCast a weighted vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); # #[cfg(feature = \"cosmwasm_1_2\")] use cosmwasm_std::{Decimal, GovMsg, VoteOption, WeightedVoteOption};\n\n# #[cfg(feature = \"cosmwasm_1_2\")] #[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::VoteWeighted { proposal_id: 4, options: vec![ WeightedVoteOption { option: VoteOption::Yes, weight: Decimal::percent(65), }, WeightedVoteOption { option: VoteOption::Abstain, weight: Decimal::percent(35), }, ], })) } ```", + "description": "This message type allows the contract interact with the [x/gov] module in order to cast votes.\n\n[x/gov]: https://github.com/cosmos/cosmos-sdk/tree/v0.45.12/x/gov\n\n## Examples\n\nCast a simple vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); use cosmwasm_std::{GovMsg, VoteOption};\n\n#[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::Vote { proposal_id: 4, option: VoteOption::Yes, })) } ```\n\nCast a weighted vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); # #[cfg(feature = \"cosmwasm_1_2\")] use cosmwasm_std::{Decimal, GovMsg, VoteOption, WeightedVoteOption};\n\n# #[cfg(feature = \"cosmwasm_1_2\")] #[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::VoteWeighted { proposal_id: 4, options: vec![ WeightedVoteOption { option: VoteOption::Yes, weight: Decimal::percent(65), }, WeightedVoteOption { option: VoteOption::Abstain, weight: Decimal::percent(35), }, ], })) } ```", "oneOf": [ { "description": "This maps directly to [MsgVote](https://github.com/cosmos/cosmos-sdk/blob/v0.42.5/proto/cosmos/gov/v1beta1/tx.proto#L46-L56) in the Cosmos SDK with voter set to the contract address.", @@ -971,22 +923,22 @@ "vote": { "type": "object", "required": [ - "proposal_id", - "vote" + "option", + "proposal_id" ], "properties": { - "proposal_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "vote": { - "description": "The vote option.\n\nThis should be called \"option\" for consistency with Cosmos SDK. Sorry for that. See .", + "option": { + "description": "The vote option.\n\nThis used to be called \"vote\", but was changed for consistency with Cosmos SDK.", "allOf": [ { "$ref": "#/definitions/VoteOption" } ] + }, + "proposal_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 } } } @@ -1058,6 +1010,13 @@ "description": "existing channel to send the tokens over", "type": "string" }, + "memo": { + "description": "An optional memo. See the blog post [\"Moving Beyond Simple Token Transfers\"](https://medium.com/the-interchain-foundation/moving-beyond-simple-token-transfers-d42b2b1dc29b) for more information.\n\nThere is no difference between setting this to `None` or an empty string.\n\nThis field is only supported on chains with CosmWasm >= 2.0 and silently ignored on older chains. If you need support for both 1.x and 2.x chain with the same codebase, it is recommended to use `CosmosMsg::Stargate` with a custom MsgTransfer protobuf encoder instead.", + "type": [ + "string", + "null" + ] + }, "timeout": { "description": "when packet times out, measured on remote chain", "allOf": [ @@ -1982,11 +1941,11 @@ { "type": "object", "required": [ - "update_params_permission" + "update_cron_params_permission" ], "properties": { - "update_params_permission": { - "$ref": "#/definitions/UpdateParamsPermission" + "update_cron_params_permission": { + "$ref": "#/definitions/CronUpdateParamsPermission" } }, "additionalProperties": false @@ -1994,11 +1953,23 @@ { "type": "object", "required": [ - "cron_permission" + "update_tokenfactory_params_permission" ], "properties": { - "cron_permission": { - "$ref": "#/definitions/CronPermission" + "update_tokenfactory_params_permission": { + "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_dex_params_permission" + ], + "properties": { + "update_dex_params_permission": { + "$ref": "#/definitions/DexUpdateParamsPermission" } }, "additionalProperties": false @@ -2006,11 +1977,11 @@ { "type": "object", "required": [ - "tokenfactory_permission" + "cron_permission" ], "properties": { - "tokenfactory_permission": { - "$ref": "#/definitions/TokenfactoryPermission" + "cron_permission": { + "$ref": "#/definitions/CronPermission" } }, "additionalProperties": false @@ -2165,90 +2136,6 @@ } } }, - "StakingMsg": { - "description": "The message types of the staking module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto", - "oneOf": [ - { - "description": "This is translated to a [MsgDelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "delegate" - ], - "properties": { - "delegate": { - "type": "object", - "required": [ - "amount", - "validator" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Coin" - }, - "validator": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "description": "This is translated to a [MsgUndelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "undelegate" - ], - "properties": { - "undelegate": { - "type": "object", - "required": [ - "amount", - "validator" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Coin" - }, - "validator": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "description": "This is translated to a [MsgBeginRedelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "redelegate" - ], - "properties": { - "redelegate": { - "type": "object", - "required": [ - "amount", - "dst_validator", - "src_validator" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Coin" - }, - "dst_validator": { - "type": "string" - }, - "src_validator": { - "type": "string" - } - } - } - }, - "additionalProperties": false - } - ] - }, "StrategyMsg": { "oneOf": [ { @@ -2315,30 +2202,6 @@ } ] }, - "TokenfactoryPermission": { - "type": "object", - "required": [ - "denom_creation_fee", - "denom_creation_gas_consume", - "fee_collector_address", - "whitelisted_hooks" - ], - "properties": { - "denom_creation_fee": { - "type": "boolean" - }, - "denom_creation_gas_consume": { - "type": "boolean" - }, - "fee_collector_address": { - "type": "boolean" - }, - "whitelisted_hooks": { - "type": "boolean" - } - }, - "additionalProperties": false - }, "TokenfactoryUpdateParamsPermission": { "type": "object", "required": [ @@ -2429,34 +2292,6 @@ } } }, - "UpdateParamsPermission": { - "oneOf": [ - { - "type": "object", - "required": [ - "cron_update_params_permission" - ], - "properties": { - "cron_update_params_permission": { - "$ref": "#/definitions/CronUpdateParamsPermission" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "tokenfactory_update_params_permission" - ], - "properties": { - "tokenfactory_update_params_permission": { - "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" - } - }, - "additionalProperties": false - } - ] - }, "UpgradeProposal": { "description": "UpgradeProposal defines the struct for IBC upgrade proposal.", "deprecated": true, @@ -2747,6 +2582,30 @@ }, "additionalProperties": false }, + "DexUpdateParamsPermission": { + "type": "object", + "required": [ + "fee_tiers", + "good_til_purge_allowance", + "max_jits_per_block", + "paused" + ], + "properties": { + "fee_tiers": { + "type": "boolean" + }, + "good_til_purge_allowance": { + "type": "boolean" + }, + "max_jits_per_block": { + "type": "boolean" + }, + "paused": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "ParamChangePermission": { "type": "object", "required": [ @@ -2795,11 +2654,11 @@ { "type": "object", "required": [ - "update_params_permission" + "update_cron_params_permission" ], "properties": { - "update_params_permission": { - "$ref": "#/definitions/UpdateParamsPermission" + "update_cron_params_permission": { + "$ref": "#/definitions/CronUpdateParamsPermission" } }, "additionalProperties": false @@ -2807,11 +2666,23 @@ { "type": "object", "required": [ - "cron_permission" + "update_tokenfactory_params_permission" ], "properties": { - "cron_permission": { - "$ref": "#/definitions/CronPermission" + "update_tokenfactory_params_permission": { + "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_dex_params_permission" + ], + "properties": { + "update_dex_params_permission": { + "$ref": "#/definitions/DexUpdateParamsPermission" } }, "additionalProperties": false @@ -2819,11 +2690,11 @@ { "type": "object", "required": [ - "tokenfactory_permission" + "cron_permission" ], "properties": { - "tokenfactory_permission": { - "$ref": "#/definitions/TokenfactoryPermission" + "cron_permission": { + "$ref": "#/definitions/CronPermission" } }, "additionalProperties": false @@ -2855,30 +2726,6 @@ } ] }, - "TokenfactoryPermission": { - "type": "object", - "required": [ - "denom_creation_fee", - "denom_creation_gas_consume", - "fee_collector_address", - "whitelisted_hooks" - ], - "properties": { - "denom_creation_fee": { - "type": "boolean" - }, - "denom_creation_gas_consume": { - "type": "boolean" - }, - "fee_collector_address": { - "type": "boolean" - }, - "whitelisted_hooks": { - "type": "boolean" - } - }, - "additionalProperties": false - }, "TokenfactoryUpdateParamsPermission": { "type": "object", "required": [ @@ -2902,34 +2749,6 @@ } }, "additionalProperties": false - }, - "UpdateParamsPermission": { - "oneOf": [ - { - "type": "object", - "required": [ - "cron_update_params_permission" - ], - "properties": { - "cron_update_params_permission": { - "$ref": "#/definitions/CronUpdateParamsPermission" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "tokenfactory_update_params_permission" - ], - "properties": { - "tokenfactory_update_params_permission": { - "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" - } - }, - "additionalProperties": false - } - ] } } } diff --git a/contracts/dao/neutron-chain-manager/schema/raw/execute.json b/contracts/dao/neutron-chain-manager/schema/raw/execute.json index e84f3de6..d12f6cf5 100644 --- a/contracts/dao/neutron-chain-manager/schema/raw/execute.json +++ b/contracts/dao/neutron-chain-manager/schema/raw/execute.json @@ -410,31 +410,8 @@ "additionalProperties": false }, { - "type": "object", - "required": [ - "staking" - ], - "properties": { - "staking": { - "$ref": "#/definitions/StakingMsg" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "distribution" - ], - "properties": { - "distribution": { - "$ref": "#/definitions/DistributionMsg" - } - }, - "additionalProperties": false - }, - { - "description": "A Stargate message encoded the same way as a protobuf [Any](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto). This is the same structure as messages in `TxBody` from [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md)", + "description": "This is the same structure as messages in `TxBody` from [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md)", + "deprecated": true, "type": "object", "required": [ "stargate" @@ -880,57 +857,32 @@ } ] }, - "DistributionMsg": { - "description": "The message types of the distribution module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto", - "oneOf": [ - { - "description": "This is translated to a [MsgSetWithdrawAddress](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L29-L37). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "set_withdraw_address" - ], - "properties": { - "set_withdraw_address": { - "type": "object", - "required": [ - "address" - ], - "properties": { - "address": { - "description": "The `withdraw_address`", - "type": "string" - } - } - } - }, - "additionalProperties": false + "DexUpdateParamsPermission": { + "type": "object", + "required": [ + "fee_tiers", + "good_til_purge_allowance", + "max_jits_per_block", + "paused" + ], + "properties": { + "fee_tiers": { + "type": "boolean" }, - { - "description": "This is translated to a [[MsgWithdrawDelegatorReward](https://github.com/cosmos/cosmos-sdk/blob/v0.42.4/proto/cosmos/distribution/v1beta1/tx.proto#L42-L50). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "withdraw_delegator_reward" - ], - "properties": { - "withdraw_delegator_reward": { - "type": "object", - "required": [ - "validator" - ], - "properties": { - "validator": { - "description": "The `validator_address`", - "type": "string" - } - } - } - }, - "additionalProperties": false + "good_til_purge_allowance": { + "type": "boolean" + }, + "max_jits_per_block": { + "type": "boolean" + }, + "paused": { + "type": "boolean" } - ] + }, + "additionalProperties": false }, "GovMsg": { - "description": "This message type allows the contract interact with the [x/gov] module in order to cast votes.\n\n[x/gov]: https://github.com/cosmos/cosmos-sdk/tree/v0.45.12/x/gov\n\n## Examples\n\nCast a simple vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); use cosmwasm_std::{GovMsg, VoteOption};\n\n#[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::Vote { proposal_id: 4, vote: VoteOption::Yes, })) } ```\n\nCast a weighted vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); # #[cfg(feature = \"cosmwasm_1_2\")] use cosmwasm_std::{Decimal, GovMsg, VoteOption, WeightedVoteOption};\n\n# #[cfg(feature = \"cosmwasm_1_2\")] #[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::VoteWeighted { proposal_id: 4, options: vec![ WeightedVoteOption { option: VoteOption::Yes, weight: Decimal::percent(65), }, WeightedVoteOption { option: VoteOption::Abstain, weight: Decimal::percent(35), }, ], })) } ```", + "description": "This message type allows the contract interact with the [x/gov] module in order to cast votes.\n\n[x/gov]: https://github.com/cosmos/cosmos-sdk/tree/v0.45.12/x/gov\n\n## Examples\n\nCast a simple vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); use cosmwasm_std::{GovMsg, VoteOption};\n\n#[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::Vote { proposal_id: 4, option: VoteOption::Yes, })) } ```\n\nCast a weighted vote:\n\n``` # use cosmwasm_std::{ # HexBinary, # Storage, Api, Querier, DepsMut, Deps, entry_point, Env, StdError, MessageInfo, # Response, QueryResponse, # }; # type ExecuteMsg = (); # #[cfg(feature = \"cosmwasm_1_2\")] use cosmwasm_std::{Decimal, GovMsg, VoteOption, WeightedVoteOption};\n\n# #[cfg(feature = \"cosmwasm_1_2\")] #[entry_point] pub fn execute( deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg, ) -> Result { // ... Ok(Response::new().add_message(GovMsg::VoteWeighted { proposal_id: 4, options: vec![ WeightedVoteOption { option: VoteOption::Yes, weight: Decimal::percent(65), }, WeightedVoteOption { option: VoteOption::Abstain, weight: Decimal::percent(35), }, ], })) } ```", "oneOf": [ { "description": "This maps directly to [MsgVote](https://github.com/cosmos/cosmos-sdk/blob/v0.42.5/proto/cosmos/gov/v1beta1/tx.proto#L46-L56) in the Cosmos SDK with voter set to the contract address.", @@ -942,22 +894,22 @@ "vote": { "type": "object", "required": [ - "proposal_id", - "vote" + "option", + "proposal_id" ], "properties": { - "proposal_id": { - "type": "integer", - "format": "uint64", - "minimum": 0.0 - }, - "vote": { - "description": "The vote option.\n\nThis should be called \"option\" for consistency with Cosmos SDK. Sorry for that. See .", + "option": { + "description": "The vote option.\n\nThis used to be called \"vote\", but was changed for consistency with Cosmos SDK.", "allOf": [ { "$ref": "#/definitions/VoteOption" } ] + }, + "proposal_id": { + "type": "integer", + "format": "uint64", + "minimum": 0.0 } } } @@ -1029,6 +981,13 @@ "description": "existing channel to send the tokens over", "type": "string" }, + "memo": { + "description": "An optional memo. See the blog post [\"Moving Beyond Simple Token Transfers\"](https://medium.com/the-interchain-foundation/moving-beyond-simple-token-transfers-d42b2b1dc29b) for more information.\n\nThere is no difference between setting this to `None` or an empty string.\n\nThis field is only supported on chains with CosmWasm >= 2.0 and silently ignored on older chains. If you need support for both 1.x and 2.x chain with the same codebase, it is recommended to use `CosmosMsg::Stargate` with a custom MsgTransfer protobuf encoder instead.", + "type": [ + "string", + "null" + ] + }, "timeout": { "description": "when packet times out, measured on remote chain", "allOf": [ @@ -1953,11 +1912,11 @@ { "type": "object", "required": [ - "update_params_permission" + "update_cron_params_permission" ], "properties": { - "update_params_permission": { - "$ref": "#/definitions/UpdateParamsPermission" + "update_cron_params_permission": { + "$ref": "#/definitions/CronUpdateParamsPermission" } }, "additionalProperties": false @@ -1965,11 +1924,23 @@ { "type": "object", "required": [ - "cron_permission" + "update_tokenfactory_params_permission" ], "properties": { - "cron_permission": { - "$ref": "#/definitions/CronPermission" + "update_tokenfactory_params_permission": { + "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "update_dex_params_permission" + ], + "properties": { + "update_dex_params_permission": { + "$ref": "#/definitions/DexUpdateParamsPermission" } }, "additionalProperties": false @@ -1977,11 +1948,11 @@ { "type": "object", "required": [ - "tokenfactory_permission" + "cron_permission" ], "properties": { - "tokenfactory_permission": { - "$ref": "#/definitions/TokenfactoryPermission" + "cron_permission": { + "$ref": "#/definitions/CronPermission" } }, "additionalProperties": false @@ -2136,90 +2107,6 @@ } } }, - "StakingMsg": { - "description": "The message types of the staking module.\n\nSee https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto", - "oneOf": [ - { - "description": "This is translated to a [MsgDelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "delegate" - ], - "properties": { - "delegate": { - "type": "object", - "required": [ - "amount", - "validator" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Coin" - }, - "validator": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "description": "This is translated to a [MsgUndelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "undelegate" - ], - "properties": { - "undelegate": { - "type": "object", - "required": [ - "amount", - "validator" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Coin" - }, - "validator": { - "type": "string" - } - } - } - }, - "additionalProperties": false - }, - { - "description": "This is translated to a [MsgBeginRedelegate](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105). `delegator_address` is automatically filled with the current contract's address.", - "type": "object", - "required": [ - "redelegate" - ], - "properties": { - "redelegate": { - "type": "object", - "required": [ - "amount", - "dst_validator", - "src_validator" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Coin" - }, - "dst_validator": { - "type": "string" - }, - "src_validator": { - "type": "string" - } - } - } - }, - "additionalProperties": false - } - ] - }, "StrategyMsg": { "oneOf": [ { @@ -2286,30 +2173,6 @@ } ] }, - "TokenfactoryPermission": { - "type": "object", - "required": [ - "denom_creation_fee", - "denom_creation_gas_consume", - "fee_collector_address", - "whitelisted_hooks" - ], - "properties": { - "denom_creation_fee": { - "type": "boolean" - }, - "denom_creation_gas_consume": { - "type": "boolean" - }, - "fee_collector_address": { - "type": "boolean" - }, - "whitelisted_hooks": { - "type": "boolean" - } - }, - "additionalProperties": false - }, "TokenfactoryUpdateParamsPermission": { "type": "object", "required": [ @@ -2400,34 +2263,6 @@ } } }, - "UpdateParamsPermission": { - "oneOf": [ - { - "type": "object", - "required": [ - "cron_update_params_permission" - ], - "properties": { - "cron_update_params_permission": { - "$ref": "#/definitions/CronUpdateParamsPermission" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "tokenfactory_update_params_permission" - ], - "properties": { - "tokenfactory_update_params_permission": { - "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" - } - }, - "additionalProperties": false - } - ] - }, "UpgradeProposal": { "description": "UpgradeProposal defines the struct for IBC upgrade proposal.", "deprecated": true, diff --git a/contracts/dao/neutron-chain-manager/schema/raw/response_to_strategies.json b/contracts/dao/neutron-chain-manager/schema/raw/response_to_strategies.json index 36d64aa3..ebba6232 100644 --- a/contracts/dao/neutron-chain-manager/schema/raw/response_to_strategies.json +++ b/contracts/dao/neutron-chain-manager/schema/raw/response_to_strategies.json @@ -38,6 +38,30 @@ }, "additionalProperties": false }, + "DexUpdateParamsPermission": { + "type": "object", + "required": [ + "fee_tiers", + "good_til_purge_allowance", + "max_jits_per_block", + "paused" + ], + "properties": { + "fee_tiers": { + "type": "boolean" + }, + "good_til_purge_allowance": { + "type": "boolean" + }, + "max_jits_per_block": { + "type": "boolean" + }, + "paused": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "ParamChangePermission": { "type": "object", "required": [ @@ -86,11 +110,11 @@ { "type": "object", "required": [ - "update_params_permission" + "update_cron_params_permission" ], "properties": { - "update_params_permission": { - "$ref": "#/definitions/UpdateParamsPermission" + "update_cron_params_permission": { + "$ref": "#/definitions/CronUpdateParamsPermission" } }, "additionalProperties": false @@ -98,11 +122,11 @@ { "type": "object", "required": [ - "cron_permission" + "update_tokenfactory_params_permission" ], "properties": { - "cron_permission": { - "$ref": "#/definitions/CronPermission" + "update_tokenfactory_params_permission": { + "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" } }, "additionalProperties": false @@ -110,11 +134,23 @@ { "type": "object", "required": [ - "tokenfactory_permission" + "update_dex_params_permission" ], "properties": { - "tokenfactory_permission": { - "$ref": "#/definitions/TokenfactoryPermission" + "update_dex_params_permission": { + "$ref": "#/definitions/DexUpdateParamsPermission" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "cron_permission" + ], + "properties": { + "cron_permission": { + "$ref": "#/definitions/CronPermission" } }, "additionalProperties": false @@ -146,30 +182,6 @@ } ] }, - "TokenfactoryPermission": { - "type": "object", - "required": [ - "denom_creation_fee", - "denom_creation_gas_consume", - "fee_collector_address", - "whitelisted_hooks" - ], - "properties": { - "denom_creation_fee": { - "type": "boolean" - }, - "denom_creation_gas_consume": { - "type": "boolean" - }, - "fee_collector_address": { - "type": "boolean" - }, - "whitelisted_hooks": { - "type": "boolean" - } - }, - "additionalProperties": false - }, "TokenfactoryUpdateParamsPermission": { "type": "object", "required": [ @@ -193,34 +205,6 @@ } }, "additionalProperties": false - }, - "UpdateParamsPermission": { - "oneOf": [ - { - "type": "object", - "required": [ - "cron_update_params_permission" - ], - "properties": { - "cron_update_params_permission": { - "$ref": "#/definitions/CronUpdateParamsPermission" - } - }, - "additionalProperties": false - }, - { - "type": "object", - "required": [ - "tokenfactory_update_params_permission" - ], - "properties": { - "tokenfactory_update_params_permission": { - "$ref": "#/definitions/TokenfactoryUpdateParamsPermission" - } - }, - "additionalProperties": false - } - ] } } } diff --git a/contracts/dao/neutron-chain-manager/src/contract.rs b/contracts/dao/neutron-chain-manager/src/contract.rs index 31e08165..9dbfa86e 100644 --- a/contracts/dao/neutron-chain-manager/src/contract.rs +++ b/contracts/dao/neutron-chain-manager/src/contract.rs @@ -2,6 +2,10 @@ use crate::cron_module_param_types::{ MsgUpdateParamsCron, ParamsRequestCron, ParamsResponseCron, MSG_TYPE_UPDATE_PARAMS_CRON, PARAMS_QUERY_PATH_CRON, }; +use crate::dex_module_param_types::{ + MsgUpdateParamsDex, ParamsRequestDex, ParamsResponseDex, MSG_TYPE_UPDATE_PARAMS_DEX, + PARAMS_QUERY_PATH_DEX, +}; use crate::tokenfactory_module_param_types::{ MsgUpdateParamsTokenfactory, ParamsRequestTokenfactory, ParamsResponseTokenfactory, MSG_TYPE_UPDATE_PARAMS_TOKENFACTORY, PARAMS_QUERY_PATH_TOKENFACTORY, @@ -14,6 +18,7 @@ use cosmwasm_std::{ use cw2::set_contract_version; use neutron_sdk::bindings::msg::{AdminProposal, NeutronMsg, ProposalExecuteMessage}; use neutron_sdk::proto_types::neutron::cron::QueryParamsRequest as QueryParamsRequestCron; +use neutron_sdk::proto_types::neutron::dex::QueryParamsRequest as QueryParamsRequestDex; use neutron_sdk::proto_types::osmosis::tokenfactory::v1beta1::QueryParamsRequest as QueryParamsRequestTokenfactory; use neutron_sdk::stargate::aux::make_stargate_query; @@ -237,6 +242,9 @@ fn check_proposal_execute_message( } else if typed_proposal.type_field.as_str() == MSG_TYPE_UPDATE_PARAMS_TOKENFACTORY { check_tokenfactory_update_msg_params(deps, strategy, proposal)?; Ok(()) + } else if typed_proposal.type_field.as_str() == MSG_TYPE_UPDATE_PARAMS_DEX { + check_dex_update_msg_params(deps, strategy, proposal)?; + Ok(()) } else { Err(ContractError::Unauthorized {}) } @@ -338,6 +346,57 @@ pub fn get_tokenfactory_params( ) } +/// Checks that the strategy owner is authorised to change the parameters of the +/// dex module. We query the current values for each parameter & compare them to +/// the values in the proposal; all modifications must be allowed by the strategy. +fn check_dex_update_msg_params( + deps: Deps, + strategy: Strategy, + proposal: ProposalExecuteMessage, +) -> Result<(), ContractError> { + let msg_update_params: MsgUpdateParamsDex = + serde_json_wasm::from_str(proposal.message.as_str())?; + + let dex_update_param_permission = strategy + .get_dex_update_param_permission() + .ok_or(ContractError::Unauthorized {})?; + + let dex_params = get_dex_params(deps, ParamsRequestDex {})?; + + if dex_params.params.fee_tiers != msg_update_params.params.fee_tiers + && !dex_update_param_permission.fee_tiers + { + return Err(ContractError::Unauthorized {}); + } + if dex_params.params.paused != msg_update_params.params.paused + && !dex_update_param_permission.paused + { + return Err(ContractError::Unauthorized {}); + } + if dex_params.params.max_jits_per_block != msg_update_params.params.max_jits_per_block + && !dex_update_param_permission.max_jits_per_block + { + return Err(ContractError::Unauthorized {}); + } + if dex_params.params.good_til_purge_allowance + != msg_update_params.params.good_til_purge_allowance + && !dex_update_param_permission.good_til_purge_allowance + { + return Err(ContractError::Unauthorized {}); + } + + Ok(()) +} + +/// Queries the parameters of the dex module. +pub fn get_dex_params(deps: Deps, req: ParamsRequestDex) -> StdResult { + make_stargate_query( + deps, + PARAMS_QUERY_PATH_DEX, + QueryParamsRequestDex::from(req), + ) +} + #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { diff --git a/contracts/dao/neutron-chain-manager/src/cron_module_param_types.rs b/contracts/dao/neutron-chain-manager/src/cron_module_param_types.rs index eb5889b7..a79fb104 100644 --- a/contracts/dao/neutron-chain-manager/src/cron_module_param_types.rs +++ b/contracts/dao/neutron-chain-manager/src/cron_module_param_types.rs @@ -16,6 +16,9 @@ pub struct MsgUpdateParamsCron { #[serde(rename_all = "snake_case")] pub struct ParamsCron { pub security_address: String, + /// Unfortunately, stargate returns a string instead of a number for the + /// limit parameter, so we need to have a custom deserializer for this + /// field. #[serde(deserialize_with = "deserialize_u64")] pub limit: u64, } diff --git a/contracts/dao/neutron-chain-manager/src/dex_module_param_types.rs b/contracts/dao/neutron-chain-manager/src/dex_module_param_types.rs new file mode 100644 index 00000000..322f0ba8 --- /dev/null +++ b/contracts/dao/neutron-chain-manager/src/dex_module_param_types.rs @@ -0,0 +1,42 @@ +use crate::utils::{deserialize_u64, deserialize_u64_vec}; +use neutron_sdk::proto_types::neutron::dex::QueryParamsRequest; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +pub const PARAMS_QUERY_PATH_DEX: &str = "/neutron.dex.Query/Params"; +pub const MSG_TYPE_UPDATE_PARAMS_DEX: &str = "/neutron.dex.MsgUpdateParams"; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct MsgUpdateParamsDex { + pub params: ParamsDex, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +/// Unfortunately, stargate returns a string instead of a number for the +/// u64 fields, so we need to have a custom deserializer. +pub struct ParamsDex { + #[serde(deserialize_with = "deserialize_u64_vec")] + pub fee_tiers: Vec, + pub paused: bool, + #[serde(deserialize_with = "deserialize_u64")] + pub max_jits_per_block: u64, + #[serde(deserialize_with = "deserialize_u64")] + pub good_til_purge_allowance: u64, +} + +/// The types below are used for querying dex module parameters via stargate. +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, JsonSchema, ::prost::Message)] +pub struct ParamsRequestDex {} + +impl From for QueryParamsRequest { + fn from(_: ParamsRequestDex) -> QueryParamsRequest { + QueryParamsRequest {} + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct ParamsResponseDex { + pub params: ParamsDex, +} diff --git a/contracts/dao/neutron-chain-manager/src/lib.rs b/contracts/dao/neutron-chain-manager/src/lib.rs index a647a8a4..adb8b9e5 100644 --- a/contracts/dao/neutron-chain-manager/src/lib.rs +++ b/contracts/dao/neutron-chain-manager/src/lib.rs @@ -1,10 +1,10 @@ pub mod contract; +mod cron_module_param_types; +mod dex_module_param_types; mod error; pub mod msg; pub mod state; -pub mod utils; - -mod cron_module_param_types; #[cfg(test)] mod testing; mod tokenfactory_module_param_types; +pub mod utils; diff --git a/contracts/dao/neutron-chain-manager/src/msg.rs b/contracts/dao/neutron-chain-manager/src/msg.rs index 0a1ccc86..478bf15f 100644 --- a/contracts/dao/neutron-chain-manager/src/msg.rs +++ b/contracts/dao/neutron-chain-manager/src/msg.rs @@ -152,6 +152,25 @@ impl Strategy { } } } + + pub fn get_dex_update_param_permission(&self) -> Option { + match self { + Strategy::AllowAll => Some(DexUpdateParamsPermission { + fee_tiers: true, + paused: true, + max_jits_per_block: true, + good_til_purge_allowance: true, + }), + Strategy::AllowOnly(permissions) => { + match permissions.get(&PermissionType::UpdateDexParamsPermission) { + Some(Permission::UpdateDexParamsPermission(dex_update_params)) => { + Some(dex_update_params.clone()) + } + _ => None, + } + } + } + } } #[cw_serde] @@ -162,6 +181,7 @@ pub enum Permission { // For new-style parameter updates. UpdateCronParamsPermission(CronUpdateParamsPermission), UpdateTokenfactoryParamsPermission(TokenfactoryUpdateParamsPermission), + UpdateDexParamsPermission(DexUpdateParamsPermission), CronPermission(CronPermission), } @@ -173,6 +193,7 @@ impl From for PermissionType { Permission::UpdateTokenfactoryParamsPermission(_) => { PermissionType::UpdateTokenfactoryParamsPermission } + Permission::UpdateDexParamsPermission(_) => PermissionType::UpdateDexParamsPermission, Permission::CronPermission(_) => PermissionType::CronPermission, } } @@ -184,6 +205,7 @@ pub enum PermissionType { ParamChangePermission, UpdateCronParamsPermission, UpdateTokenfactoryParamsPermission, + UpdateDexParamsPermission, CronPermission, } @@ -228,6 +250,16 @@ pub struct TokenfactoryUpdateParamsPermission { pub whitelisted_hooks: bool, } +#[cw_serde] +#[derive(Eq)] +#[serde(rename_all = "snake_case")] +pub struct DexUpdateParamsPermission { + pub fee_tiers: bool, + pub paused: bool, + pub max_jits_per_block: bool, + pub good_til_purge_allowance: bool, +} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct ProposalExecuteMessageJSON { diff --git a/contracts/dao/neutron-chain-manager/src/testing/mock_querier.rs b/contracts/dao/neutron-chain-manager/src/testing/mock_querier.rs index a5a7e095..f790a63f 100644 --- a/contracts/dao/neutron-chain-manager/src/testing/mock_querier.rs +++ b/contracts/dao/neutron-chain-manager/src/testing/mock_querier.rs @@ -1,4 +1,5 @@ use crate::cron_module_param_types::{ParamsCron, ParamsResponseCron}; +use crate::dex_module_param_types::{ParamsDex, ParamsResponseDex}; use crate::tokenfactory_module_param_types::{ParamsResponseTokenfactory, ParamsTokenfactory}; use cosmwasm_std::testing::{MockApi, MockQuerier, MockStorage}; use cosmwasm_std::{ @@ -63,6 +64,17 @@ impl WasmMockQuerier { }); SystemResult::Ok(ContractResult::from(resp)) } + "/neutron.dex.Query/Params" => { + let resp = to_json_binary(&ParamsResponseDex { + params: ParamsDex { + fee_tiers: [1, 2, 99].to_vec(), + paused: false, + max_jits_per_block: 20, + good_til_purge_allowance: 25000, + }, + }); + SystemResult::Ok(ContractResult::from(resp)) + } _ => todo!(), }, _ => self.base.handle_query(request), diff --git a/contracts/dao/neutron-chain-manager/src/testing/tests.rs b/contracts/dao/neutron-chain-manager/src/testing/tests.rs index 5f47d3c7..f79c65e3 100644 --- a/contracts/dao/neutron-chain-manager/src/testing/tests.rs +++ b/contracts/dao/neutron-chain-manager/src/testing/tests.rs @@ -2,16 +2,15 @@ use crate::contract::{ execute_add_strategy, execute_execute_messages, execute_remove_strategy, instantiate, }; use crate::error::ContractError::{InvalidDemotion, Unauthorized}; -use crate::msg::InstantiateMsg; use crate::msg::Permission::{ - CronPermission, ParamChangePermission, UpdateCronParamsPermission, + CronPermission, ParamChangePermission, UpdateCronParamsPermission, UpdateDexParamsPermission, UpdateTokenfactoryParamsPermission, }; use crate::msg::{ - CronPermission as CronPermissionType, CronUpdateParamsPermission, StrategyMsg, - TokenfactoryUpdateParamsPermission, + CronPermission as CronPermissionType, CronUpdateParamsPermission, DexUpdateParamsPermission, + InstantiateMsg, ParamChangePermission as ParamChangePermissionType, ParamPermission, + StrategyMsg, TokenfactoryUpdateParamsPermission, }; -use crate::msg::{ParamChangePermission as ParamChangePermissionType, ParamPermission}; use crate::testing::mock_querier::mock_dependencies; use cosmwasm_std::testing::{message_info, mock_env}; use cosmwasm_std::{Addr, BankMsg, Coin, CosmosMsg, Uint128}; @@ -694,6 +693,236 @@ pub fn test_execute_execute_message_update_params_tokenfactory_unauthorized_whit assert_eq!(err, Unauthorized {}); } +/// Checks that if you have permissions, you can change all parameters of the dex +/// module (new style parameter changes). NOTE: this does not check that the +/// parameters have actually been changed. +#[test] +pub fn test_execute_execute_message_update_params_dex_authorized() { + let msg = CosmosMsg::Custom(NeutronMsg::SubmitAdminProposal { + admin_proposal: AdminProposal::ProposalExecuteMessage(ProposalExecuteMessage { + message: r#"{"@type":"/neutron.dex.MsgUpdateParams", + "authority":"neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", + "params": {"fee_tiers":["1","2"],"paused":true,"max_jits_per_block":"25","good_til_purge_allowance":"540000"}}"# + .to_string(), + }), + }); + + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + + instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + initial_strategy_address: Addr::unchecked("neutron_dao_address".to_string()), + }, + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + execute_add_strategy( + deps.as_mut(), + info.clone(), + Addr::unchecked("addr1".to_string()), + StrategyMsg::AllowOnly(vec![UpdateDexParamsPermission(DexUpdateParamsPermission { + fee_tiers: true, + paused: true, + max_jits_per_block: true, + good_til_purge_allowance: true, + })]), + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("addr1"), &[]); + execute_execute_messages(deps.as_mut(), info.clone(), vec![msg]).unwrap(); +} + +/// Checks that you can't change the `fee_tiers` if you don't have the permission to do so +/// (new style parameter changes). +#[test] +pub fn test_execute_execute_message_update_params_dex_unauthorized_fee_tiers() { + let msg = CosmosMsg::Custom(NeutronMsg::SubmitAdminProposal { + admin_proposal: AdminProposal::ProposalExecuteMessage(ProposalExecuteMessage { + message: r#"{"@type":"/neutron.dex.MsgUpdateParams", + "authority":"neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", + "params": {"fee_tiers":["1","2"],"paused":true,"max_jits_per_block":"25","good_til_purge_allowance":"540000"}}"# + .to_string(), + }), + }); + + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + + instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + initial_strategy_address: Addr::unchecked("neutron_dao_address".to_string()), + }, + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + execute_add_strategy( + deps.as_mut(), + info.clone(), + Addr::unchecked("addr1".to_string()), + StrategyMsg::AllowOnly(vec![UpdateDexParamsPermission(DexUpdateParamsPermission { + fee_tiers: false, + paused: true, + max_jits_per_block: true, + good_til_purge_allowance: true, + })]), + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("addr1"), &[]); + let err = execute_execute_messages(deps.as_mut(), info.clone(), vec![msg]).unwrap_err(); + assert_eq!(err, Unauthorized {}) +} + +/// Checks that you can't change `paused` if you don't have the permission to do so +/// (new style parameter changes). + +#[test] +pub fn test_execute_execute_message_update_params_dex_unauthorized_paused() { + let msg = CosmosMsg::Custom(NeutronMsg::SubmitAdminProposal { + admin_proposal: AdminProposal::ProposalExecuteMessage(ProposalExecuteMessage { + message: r#"{"@type":"/neutron.dex.MsgUpdateParams", + "authority":"neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", + "params": {"fee_tiers":["1","2"],"paused":true,"max_jits_per_block":"25","good_til_purge_allowance":"540000"}}"# + .to_string(), + }), + }); + + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + + instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + initial_strategy_address: Addr::unchecked("neutron_dao_address".to_string()), + }, + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + execute_add_strategy( + deps.as_mut(), + info.clone(), + Addr::unchecked("addr1".to_string()), + StrategyMsg::AllowOnly(vec![UpdateDexParamsPermission(DexUpdateParamsPermission { + fee_tiers: true, + paused: false, + max_jits_per_block: true, + good_til_purge_allowance: true, + })]), + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("addr1"), &[]); + let err = execute_execute_messages(deps.as_mut(), info.clone(), vec![msg]).unwrap_err(); + assert_eq!(err, Unauthorized {}); +} + +/// Checks that you can't change `max_jits_per_block` if you don't have the permission to do so +/// (new style parameter changes). +#[test] +pub fn test_execute_execute_message_update_params_dex_unauthorized_max_jits_per_block() { + let msg = CosmosMsg::Custom(NeutronMsg::SubmitAdminProposal { + admin_proposal: AdminProposal::ProposalExecuteMessage(ProposalExecuteMessage { + message: r#"{"@type":"/neutron.dex.MsgUpdateParams", + "authority":"neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", + "params": {"fee_tiers":["1","2"],"paused":true,"max_jits_per_block":"25","good_til_purge_allowance":"540000"}}"# + .to_string(), + }), + }); + + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + + instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + initial_strategy_address: Addr::unchecked("neutron_dao_address".to_string()), + }, + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + execute_add_strategy( + deps.as_mut(), + info.clone(), + Addr::unchecked("addr1".to_string()), + StrategyMsg::AllowOnly(vec![UpdateDexParamsPermission(DexUpdateParamsPermission { + fee_tiers: true, + paused: true, + max_jits_per_block: false, + good_til_purge_allowance: true, + })]), + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("addr1"), &[]); + let err = execute_execute_messages(deps.as_mut(), info.clone(), vec![msg]).unwrap_err(); + assert_eq!(err, Unauthorized {}); +} +/// Checks that you can't change `good_til_purge_allowance` if you don't have the permission to do so +/// (new style parameter changes). +#[test] +pub fn test_execute_execute_message_update_params_dex_unauthorized_good_til_purge_allowance() { + let msg = CosmosMsg::Custom(NeutronMsg::SubmitAdminProposal { + admin_proposal: AdminProposal::ProposalExecuteMessage(ProposalExecuteMessage { + message: r#"{"@type":"/neutron.dex.MsgUpdateParams", + "authority":"neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z", + "params": {"fee_tiers":["1","2"],"paused":true,"max_jits_per_block":"25","good_til_purge_allowance":"540000"}}"# + .to_string(), + }), + }); + + let mut deps = mock_dependencies(); + let env = mock_env(); + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + + instantiate( + deps.as_mut(), + env.clone(), + info.clone(), + InstantiateMsg { + initial_strategy_address: Addr::unchecked("neutron_dao_address".to_string()), + }, + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("neutron_dao_address"), &[]); + execute_add_strategy( + deps.as_mut(), + info.clone(), + Addr::unchecked("addr1".to_string()), + StrategyMsg::AllowOnly(vec![UpdateDexParamsPermission(DexUpdateParamsPermission { + fee_tiers: true, + paused: true, + max_jits_per_block: true, + good_til_purge_allowance: false, + })]), + ) + .unwrap(); + + let info = message_info(&Addr::unchecked("addr1"), &[]); + let err = execute_execute_messages(deps.as_mut(), info.clone(), vec![msg]).unwrap_err(); + assert_eq!(err, Unauthorized {}); +} + /// Checks that you can update a legacy param if you have the necessary ALLOW_ONLY permission. #[test] pub fn test_execute_execute_message_param_change_success() { diff --git a/contracts/dao/neutron-chain-manager/src/utils.rs b/contracts/dao/neutron-chain-manager/src/utils.rs index 7de6cda3..5eea30ab 100644 --- a/contracts/dao/neutron-chain-manager/src/utils.rs +++ b/contracts/dao/neutron-chain-manager/src/utils.rs @@ -1,5 +1,5 @@ -use serde::de::{self, Visitor}; -use serde::Deserializer; +use serde::de::{self, SeqAccess, Visitor}; +use serde::{Deserialize, Deserializer}; use std::fmt; /// Unfortunately, stargate returns a string instead of a number for @@ -35,3 +35,46 @@ where deserializer.deserialize_any(StringOrNumberVisitor) } + +pub fn deserialize_u64_vec<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct StringOrNumberVecVisitor; + + impl<'de> Visitor<'de> for StringOrNumberVecVisitor { + type Value = Vec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a vector of u64s or strings representing u64s") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut vec = Vec::new(); + + while let Some(value) = seq.next_element::()? { + match value { + U64OrString::U64(num) => vec.push(num), + U64OrString::String(s) => { + let num: u64 = s.parse().map_err(de::Error::custom)?; + vec.push(num); + } + } + } + + Ok(vec) + } + } + + deserializer.deserialize_seq(StringOrNumberVecVisitor) +} + +#[derive(Deserialize)] +#[serde(untagged)] +enum U64OrString { + U64(u64), + String(String), +} diff --git a/contracts/tokenomics/reserve/schema/neutron-reserve.json b/contracts/tokenomics/reserve/schema/neutron-reserve.json index 1b1917e3..e7367431 100644 --- a/contracts/tokenomics/reserve/schema/neutron-reserve.json +++ b/contracts/tokenomics/reserve/schema/neutron-reserve.json @@ -1,6 +1,6 @@ { "contract_name": "neutron-reserve", - "contract_version": "0.1.2", + "contract_version": "0.2.0", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#",