Merge pull request #4822 from nymtech/feature/mixnet-contract-update-admin
added explicit updateable admin to the mixnet contract
This commit is contained in:
Generated
+1
@@ -5273,6 +5273,7 @@ dependencies = [
|
||||
"bs58 0.4.0",
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
"cw-controllers",
|
||||
"cw2",
|
||||
"humantime-serde",
|
||||
"log",
|
||||
|
||||
@@ -42,6 +42,10 @@ pub trait MixnetQueryClient {
|
||||
|
||||
// state/sys-params-related
|
||||
|
||||
async fn admin(&self) -> Result<cw_controllers::AdminResponse, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::Admin {}).await
|
||||
}
|
||||
|
||||
async fn get_mixnet_contract_version(&self) -> Result<ContractBuildInformation, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetContractVersion {})
|
||||
.await
|
||||
@@ -580,6 +584,7 @@ mod tests {
|
||||
msg: MixnetQueryMsg,
|
||||
) -> u32 {
|
||||
match msg {
|
||||
MixnetQueryMsg::Admin {} => client.admin().ignore(),
|
||||
MixnetQueryMsg::GetAllFamiliesPaged { limit, start_after } => client
|
||||
.get_all_family_members_paged(start_after, limit)
|
||||
.ignore(),
|
||||
|
||||
@@ -31,6 +31,15 @@ pub trait MixnetSigningClient {
|
||||
|
||||
// state/sys-params-related
|
||||
|
||||
async fn update_admin(
|
||||
&self,
|
||||
admin: String,
|
||||
fee: Option<Fee>,
|
||||
) -> Result<ExecuteResult, NyxdError> {
|
||||
self.execute_mixnet_contract(fee, MixnetExecuteMsg::UpdateAdmin { admin }, vec![])
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_rewarding_validator_address(
|
||||
&self,
|
||||
address: AccountId,
|
||||
@@ -760,6 +769,7 @@ mod tests {
|
||||
msg: MixnetExecuteMsg,
|
||||
) {
|
||||
match msg {
|
||||
MixnetExecuteMsg::UpdateAdmin { admin } => client.update_admin(admin, None).ignore(),
|
||||
MixnetExecuteMsg::AssignNodeLayer { mix_id, layer } => {
|
||||
client.assign_node_layer(mix_id, layer, None).ignore()
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ repository = { workspace = true }
|
||||
bs58 = "0.4.0"
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmwasm-schema = { workspace = true }
|
||||
cw-controllers = { workspace = true }
|
||||
cw2 = { workspace = true, optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_repr = { workspace = true }
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::{EpochEventId, EpochState, IdentityKey, MixId, OperatingCostRange, Pr
|
||||
use contracts_common::signing::verifier::ApiVerifierError;
|
||||
use contracts_common::Percent;
|
||||
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
|
||||
use cw_controllers::AdminError;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
@@ -12,6 +13,9 @@ pub enum MixnetContractError {
|
||||
#[error("could not perform contract migration: {comment}")]
|
||||
FailedMigration { comment: String },
|
||||
|
||||
#[error(transparent)]
|
||||
Admin(#[from] AdminError),
|
||||
|
||||
#[error("{source}")]
|
||||
StdErr {
|
||||
#[from]
|
||||
|
||||
@@ -110,6 +110,11 @@ impl InitialRewardingParams {
|
||||
|
||||
#[cw_serde]
|
||||
pub enum ExecuteMsg {
|
||||
/// Change the admin
|
||||
UpdateAdmin {
|
||||
admin: String,
|
||||
},
|
||||
|
||||
AssignNodeLayer {
|
||||
mix_id: MixId,
|
||||
layer: Layer,
|
||||
@@ -292,6 +297,7 @@ pub enum ExecuteMsg {
|
||||
impl ExecuteMsg {
|
||||
pub fn default_memo(&self) -> String {
|
||||
match self {
|
||||
ExecuteMsg::UpdateAdmin { admin } => format!("updating contract admin to {admin}"),
|
||||
ExecuteMsg::AssignNodeLayer { mix_id, layer } => {
|
||||
format!("assigning mix {mix_id} for layer {layer:?}")
|
||||
}
|
||||
@@ -408,6 +414,9 @@ impl ExecuteMsg {
|
||||
#[cw_serde]
|
||||
#[cfg_attr(feature = "schema", derive(QueryResponses))]
|
||||
pub enum QueryMsg {
|
||||
#[cfg_attr(feature = "schema", returns(cw_controllers::AdminResponse))]
|
||||
Admin {},
|
||||
|
||||
// families
|
||||
/// Gets the list of families registered in this contract.
|
||||
#[cfg_attr(feature = "schema", returns(PagedFamiliesResponse))]
|
||||
|
||||
@@ -187,7 +187,11 @@ impl Index<Layer> for LayerDistribution {
|
||||
#[cw_serde]
|
||||
pub struct ContractState {
|
||||
/// Address of the contract owner.
|
||||
pub owner: Addr,
|
||||
#[deprecated(
|
||||
note = "use explicit ADMIN instead. this field will be removed in future release"
|
||||
)]
|
||||
#[serde(default)]
|
||||
pub owner: Option<Addr>,
|
||||
|
||||
/// Address of "rewarding validator" (nym-api) that's allowed to send any rewarding-related transactions.
|
||||
pub rewarding_validator_address: Addr,
|
||||
|
||||
Generated
+2
@@ -1276,6 +1276,7 @@ dependencies = [
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
"cosmwasm-storage",
|
||||
"cw-controllers",
|
||||
"cw-storage-plus",
|
||||
"cw2",
|
||||
"nym-contracts-common",
|
||||
@@ -1295,6 +1296,7 @@ dependencies = [
|
||||
"bs58 0.4.0",
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
"cw-controllers",
|
||||
"cw2",
|
||||
"humantime-serde",
|
||||
"log",
|
||||
|
||||
@@ -34,6 +34,7 @@ cosmwasm-schema = { workspace = true, optional = true }
|
||||
cosmwasm-std = { workspace = true }
|
||||
cosmwasm-storage = { workspace = true }
|
||||
cosmwasm-derive = { workspace = true }
|
||||
cw-controllers = { workspace = true }
|
||||
cw2 = { workspace = true }
|
||||
cw-storage-plus = { workspace = true }
|
||||
|
||||
|
||||
@@ -177,6 +177,28 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "ExecuteMsg",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Change the admin",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"update_admin"
|
||||
],
|
||||
"properties": {
|
||||
"update_admin": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"admin"
|
||||
],
|
||||
"properties": {
|
||||
"admin": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -1692,6 +1714,19 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "QueryMsg",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"admin"
|
||||
],
|
||||
"properties": {
|
||||
"admin": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"description": "Gets the list of families registered in this contract.",
|
||||
"type": "object",
|
||||
@@ -2937,6 +2972,21 @@
|
||||
},
|
||||
"sudo": null,
|
||||
"responses": {
|
||||
"admin": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "AdminResponse",
|
||||
"description": "Returned from Admin.query_admin()",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"get_all_delegations": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "PagedAllDelegationsResponse",
|
||||
@@ -8140,7 +8190,6 @@
|
||||
"description": "The current state of the mixnet contract.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"owner",
|
||||
"params",
|
||||
"rewarding_denom",
|
||||
"rewarding_validator_address",
|
||||
@@ -8149,9 +8198,14 @@
|
||||
"properties": {
|
||||
"owner": {
|
||||
"description": "Address of the contract owner.",
|
||||
"allOf": [
|
||||
"default": null,
|
||||
"deprecated": true,
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -2,6 +2,28 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "ExecuteMsg",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Change the admin",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"update_admin"
|
||||
],
|
||||
"properties": {
|
||||
"update_admin": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"admin"
|
||||
],
|
||||
"properties": {
|
||||
"admin": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -2,6 +2,19 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "QueryMsg",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"admin"
|
||||
],
|
||||
"properties": {
|
||||
"admin": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"description": "Gets the list of families registered in this contract.",
|
||||
"type": "object",
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "AdminResponse",
|
||||
"description": "Returned from Admin.query_admin()",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"admin": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
"description": "The current state of the mixnet contract.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"owner",
|
||||
"params",
|
||||
"rewarding_denom",
|
||||
"rewarding_validator_address",
|
||||
@@ -13,9 +12,14 @@
|
||||
"properties": {
|
||||
"owner": {
|
||||
"description": "Address of the contract owner.",
|
||||
"allOf": [
|
||||
"default": null,
|
||||
"deprecated": true,
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Addr"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -57,6 +57,7 @@ pub const PENDING_INTERVAL_EVENTS_NAMESPACE: &str = "pie";
|
||||
pub const LAST_EPOCH_EVENT_ID_KEY: &str = "lee";
|
||||
pub const LAST_INTERVAL_EVENT_ID_KEY: &str = "lie";
|
||||
|
||||
pub const ADMIN_STORAGE_KEY: &str = "admin";
|
||||
pub const CONTRACT_STATE_KEY: &str = "state";
|
||||
|
||||
pub const LAYER_DISTRIBUTION_KEY: &str = "layers";
|
||||
|
||||
@@ -28,8 +28,10 @@ fn default_initial_state(
|
||||
profit_margin: ProfitMarginRange,
|
||||
interval_operating_cost: OperatingCostRange,
|
||||
) -> ContractState {
|
||||
// we have to temporarily preserve this functionalities until it can be removed
|
||||
#[allow(deprecated)]
|
||||
ContractState {
|
||||
owner,
|
||||
owner: Some(owner),
|
||||
rewarding_validator_address,
|
||||
vesting_contract_address,
|
||||
rewarding_denom: rewarding_denom.clone(),
|
||||
@@ -56,7 +58,7 @@ fn default_initial_state(
|
||||
/// `msg` is the contract initialization message, sort of like a constructor call.
|
||||
#[entry_point]
|
||||
pub fn instantiate(
|
||||
deps: DepsMut<'_>,
|
||||
mut deps: DepsMut<'_>,
|
||||
env: Env,
|
||||
info: MessageInfo,
|
||||
msg: InstantiateMsg,
|
||||
@@ -72,7 +74,7 @@ pub fn instantiate(
|
||||
let rewarding_validator_address = deps.api.addr_validate(&msg.rewarding_validator_address)?;
|
||||
let vesting_contract_address = deps.api.addr_validate(&msg.vesting_contract_address)?;
|
||||
let state = default_initial_state(
|
||||
info.sender,
|
||||
info.sender.clone(),
|
||||
rewarding_validator_address.clone(),
|
||||
msg.rewarding_denom,
|
||||
vesting_contract_address,
|
||||
@@ -90,7 +92,7 @@ pub fn instantiate(
|
||||
starting_interval,
|
||||
rewarding_validator_address,
|
||||
)?;
|
||||
mixnet_params_storage::initialise_storage(deps.storage, state)?;
|
||||
mixnet_params_storage::initialise_storage(deps.branch(), state, info.sender)?;
|
||||
mixnode_storage::initialise_storage(deps.storage)?;
|
||||
rewards_storage::initialise_storage(deps.storage, reward_params)?;
|
||||
cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
|
||||
@@ -108,6 +110,11 @@ pub fn execute(
|
||||
msg: ExecuteMsg,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
match msg {
|
||||
ExecuteMsg::UpdateAdmin { admin } => {
|
||||
crate::mixnet_contract_settings::transactions::try_update_contract_admin(
|
||||
deps, info, admin,
|
||||
)
|
||||
}
|
||||
ExecuteMsg::AssignNodeLayer { mix_id, layer } => {
|
||||
crate::mixnodes::transactions::assign_mixnode_layer(deps, info, mix_id, layer)
|
||||
}
|
||||
@@ -335,6 +342,9 @@ pub fn query(
|
||||
QueryMsg::GetState {} => {
|
||||
to_binary(&crate::mixnet_contract_settings::queries::query_contract_state(deps)?)
|
||||
}
|
||||
QueryMsg::Admin {} => to_binary(&crate::mixnet_contract_settings::queries::query_admin(
|
||||
deps,
|
||||
)?),
|
||||
QueryMsg::GetRewardingParams {} => {
|
||||
to_binary(&crate::rewards::queries::query_rewarding_params(deps)?)
|
||||
}
|
||||
@@ -536,6 +546,7 @@ pub fn migrate(
|
||||
cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
|
||||
|
||||
crate::queued_migrations::vesting_purge(deps.branch())?;
|
||||
crate::queued_migrations::explicit_contract_admin(deps.branch())?;
|
||||
|
||||
// due to circular dependency on contract addresses (i.e. mixnet contract requiring vesting contract address
|
||||
// and vesting contract requiring the mixnet contract address), if we ever want to deploy any new fresh
|
||||
@@ -594,8 +605,9 @@ mod tests {
|
||||
let res = instantiate(deps.as_mut(), env, sender, init_msg);
|
||||
assert!(res.is_ok());
|
||||
|
||||
#[allow(deprecated)]
|
||||
let expected_state = ContractState {
|
||||
owner: Addr::unchecked("sender"),
|
||||
owner: Some(Addr::unchecked("sender")),
|
||||
rewarding_validator_address: Addr::unchecked("foomp123"),
|
||||
vesting_contract_address: Addr::unchecked("bar456"),
|
||||
rewarding_denom: "uatom".into(),
|
||||
|
||||
@@ -5,11 +5,12 @@ use super::storage;
|
||||
use crate::interval::helpers::change_interval_config;
|
||||
use crate::interval::pending_events::ContractExecutableEvent;
|
||||
use crate::interval::storage::push_new_interval_event;
|
||||
use crate::mixnet_contract_settings::storage::ADMIN;
|
||||
use crate::mixnodes::transactions::update_mixnode_layer;
|
||||
use crate::rewards;
|
||||
use crate::rewards::storage as rewards_storage;
|
||||
use crate::support::helpers::{
|
||||
ensure_can_advance_epoch, ensure_epoch_in_progress_state, ensure_is_authorized, ensure_is_owner,
|
||||
ensure_can_advance_epoch, ensure_epoch_in_progress_state, ensure_is_authorized,
|
||||
};
|
||||
use cosmwasm_std::{DepsMut, Env, MessageInfo, Order, Response, Storage};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
@@ -325,7 +326,7 @@ pub(crate) fn try_update_interval_config(
|
||||
epoch_duration_secs: u64,
|
||||
force_immediately: bool,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
ensure_is_owner(info.sender, deps.storage)?;
|
||||
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;
|
||||
|
||||
if epochs_in_interval == 0 {
|
||||
return Err(MixnetContractError::EpochsInIntervalZero);
|
||||
@@ -1766,6 +1767,7 @@ mod tests {
|
||||
use super::*;
|
||||
use cosmwasm_std::testing::mock_info;
|
||||
use cosmwasm_std::Decimal;
|
||||
use cw_controllers::AdminError::NotAdmin;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
@@ -1831,11 +1833,11 @@ mod tests {
|
||||
1000,
|
||||
false,
|
||||
);
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
let res =
|
||||
try_update_interval_config(test.deps_mut(), env.clone(), random, 100, 1000, false);
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
let res = try_update_interval_config(test.deps_mut(), env, owner, 100, 1000, false);
|
||||
assert!(res.is_ok())
|
||||
|
||||
@@ -2,10 +2,16 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::storage;
|
||||
use crate::mixnet_contract_settings::storage::ADMIN;
|
||||
use cosmwasm_std::{Deps, StdResult};
|
||||
use cw_controllers::AdminResponse;
|
||||
use mixnet_contract_common::{ContractBuildInformation, ContractState, ContractStateParams};
|
||||
use nym_contracts_common::get_build_information;
|
||||
|
||||
pub(crate) fn query_admin(deps: Deps<'_>) -> StdResult<AdminResponse> {
|
||||
ADMIN.query_admin(deps)
|
||||
}
|
||||
|
||||
pub(crate) fn query_contract_state(deps: Deps<'_>) -> StdResult<ContractState> {
|
||||
storage::CONTRACT_STATE.load(deps.storage)
|
||||
}
|
||||
@@ -36,8 +42,9 @@ pub(crate) mod tests {
|
||||
fn query_for_contract_settings_works() {
|
||||
let mut deps = test_helpers::init_contract();
|
||||
|
||||
#[allow(deprecated)]
|
||||
let dummy_state = ContractState {
|
||||
owner: Addr::unchecked("someowner"),
|
||||
owner: Some(Addr::unchecked("foomp")),
|
||||
rewarding_validator_address: Addr::unchecked("monitor"),
|
||||
vesting_contract_address: Addr::unchecked("foomp"),
|
||||
rewarding_denom: "unym".to_string(),
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::constants::CONTRACT_STATE_KEY;
|
||||
use cosmwasm_std::{Addr, Storage};
|
||||
use crate::constants::{ADMIN_STORAGE_KEY, CONTRACT_STATE_KEY};
|
||||
use cosmwasm_std::{Addr, DepsMut, Storage};
|
||||
use cosmwasm_std::{Coin, StdResult};
|
||||
use cw_controllers::Admin;
|
||||
use cw_storage_plus::Item;
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::{ContractState, OperatingCostRange, ProfitMarginRange};
|
||||
|
||||
pub(crate) const CONTRACT_STATE: Item<'_, ContractState> = Item::new(CONTRACT_STATE_KEY);
|
||||
pub(crate) const ADMIN: Admin = Admin::new(ADMIN_STORAGE_KEY);
|
||||
|
||||
pub fn rewarding_validator_address(storage: &dyn Storage) -> Result<Addr, MixnetContractError> {
|
||||
Ok(CONTRACT_STATE
|
||||
@@ -66,8 +68,10 @@ pub(crate) fn vesting_contract_address(storage: &dyn Storage) -> Result<Addr, Mi
|
||||
}
|
||||
|
||||
pub(crate) fn initialise_storage(
|
||||
storage: &mut dyn Storage,
|
||||
deps: DepsMut<'_>,
|
||||
initial_state: ContractState,
|
||||
initial_admin: Addr,
|
||||
) -> StdResult<()> {
|
||||
CONTRACT_STATE.save(storage, &initial_state)
|
||||
CONTRACT_STATE.save(deps.storage, &initial_state)?;
|
||||
ADMIN.set(deps, Some(initial_admin))
|
||||
}
|
||||
|
||||
@@ -2,15 +2,36 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use super::storage;
|
||||
use cosmwasm_std::DepsMut;
|
||||
use crate::mixnet_contract_settings::storage::ADMIN;
|
||||
use cosmwasm_std::MessageInfo;
|
||||
use cosmwasm_std::Response;
|
||||
use cosmwasm_std::{DepsMut, StdResult};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::events::{
|
||||
new_rewarding_validator_address_update_event, new_settings_update_event,
|
||||
};
|
||||
use mixnet_contract_common::ContractStateParams;
|
||||
|
||||
pub fn try_update_contract_admin(
|
||||
mut deps: DepsMut<'_>,
|
||||
info: MessageInfo,
|
||||
new_admin: String,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let new_admin = deps.api.addr_validate(&new_admin)?;
|
||||
|
||||
let res = ADMIN.execute_update_admin(deps.branch(), info, Some(new_admin.clone()))?;
|
||||
|
||||
// SAFETY: we don't need to perform any authentication checks on the sender as it was performed
|
||||
// during 'execute_update_admin' call
|
||||
#[allow(deprecated)]
|
||||
storage::CONTRACT_STATE.update(deps.storage, |mut state| -> StdResult<_> {
|
||||
state.owner = Some(new_admin);
|
||||
Ok(state)
|
||||
})?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn try_update_rewarding_validator_address(
|
||||
deps: DepsMut<'_>,
|
||||
info: MessageInfo,
|
||||
@@ -18,9 +39,7 @@ pub fn try_update_rewarding_validator_address(
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let mut state = storage::CONTRACT_STATE.load(deps.storage)?;
|
||||
|
||||
if info.sender != state.owner {
|
||||
return Err(MixnetContractError::Unauthorized);
|
||||
}
|
||||
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;
|
||||
|
||||
let new_address = deps.api.addr_validate(&address)?;
|
||||
let old_address = state.rewarding_validator_address;
|
||||
@@ -43,10 +62,7 @@ pub(crate) fn try_update_contract_settings(
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
let mut state = storage::CONTRACT_STATE.load(deps.storage)?;
|
||||
|
||||
// check if this is executed by the owner, if not reject the transaction
|
||||
if info.sender != state.owner {
|
||||
return Err(MixnetContractError::Unauthorized);
|
||||
}
|
||||
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;
|
||||
|
||||
let response = Response::new().add_event(new_settings_update_event(&state.params, ¶ms));
|
||||
|
||||
@@ -65,6 +81,7 @@ pub mod tests {
|
||||
use crate::support::tests::test_helpers;
|
||||
use cosmwasm_std::testing::mock_info;
|
||||
use cosmwasm_std::{Addr, Coin, Uint128};
|
||||
use cw_controllers::AdminError::NotAdmin;
|
||||
|
||||
#[test]
|
||||
fn update_contract_rewarding_validtor_address() {
|
||||
@@ -76,7 +93,7 @@ pub mod tests {
|
||||
info,
|
||||
"not-the-creator".to_string(),
|
||||
);
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
let info = mock_info("creator", &[]);
|
||||
let res = try_update_rewarding_validator_address(
|
||||
@@ -136,7 +153,7 @@ pub mod tests {
|
||||
// cannot be updated from non-owner account
|
||||
let info = mock_info("not-the-creator", &[]);
|
||||
let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone());
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
// but works fine from the creator account
|
||||
let info = mock_info("creator", &[]);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::interval::storage as interval_storage;
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use cosmwasm_std::{DepsMut, Order, Storage};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
use mixnet_contract_common::PendingEpochEventKind;
|
||||
@@ -49,3 +50,17 @@ pub(crate) fn vesting_purge(deps: DepsMut) -> Result<(), MixnetContractError> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn explicit_contract_admin(deps: DepsMut) -> Result<(), MixnetContractError> {
|
||||
// we need to read the deprecated field to migrate it over
|
||||
#[allow(deprecated)]
|
||||
// SAFETY: this value should ALWAYS exist on the first execution of this migration;
|
||||
// as a matter of fact, it should ALWAYS continue existing until another migration
|
||||
#[allow(clippy::expect_used)]
|
||||
let existing_admin = mixnet_params_storage::CONTRACT_STATE
|
||||
.load(deps.storage)?
|
||||
.owner
|
||||
.expect("the contract state is corrupt - there's no admin set");
|
||||
mixnet_params_storage::ADMIN.set(deps, Some(existing_admin))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ use crate::delegations::storage as delegations_storage;
|
||||
use crate::interval::storage as interval_storage;
|
||||
use crate::interval::storage::{push_new_epoch_event, push_new_interval_event};
|
||||
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
|
||||
use crate::mixnet_contract_settings::storage::ADMIN;
|
||||
use crate::mixnodes::helpers::get_mixnode_details_by_owner;
|
||||
use crate::mixnodes::storage as mixnodes_storage;
|
||||
use crate::rewards::helpers;
|
||||
use crate::rewards::helpers::update_and_save_last_rewarded;
|
||||
use crate::support::helpers::{
|
||||
ensure_bonded, ensure_can_advance_epoch, ensure_epoch_in_progress_state, ensure_is_owner,
|
||||
AttachSendTokens,
|
||||
ensure_bonded, ensure_can_advance_epoch, ensure_epoch_in_progress_state, AttachSendTokens,
|
||||
};
|
||||
use cosmwasm_std::{DepsMut, Env, MessageInfo, Response};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
@@ -227,7 +227,7 @@ pub(crate) fn try_update_active_set_size(
|
||||
active_set_size: u32,
|
||||
force_immediately: bool,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
ensure_is_owner(info.sender, deps.storage)?;
|
||||
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;
|
||||
|
||||
let mut rewarding_params = storage::REWARDING_PARAMS.load(deps.storage)?;
|
||||
if active_set_size == 0 {
|
||||
@@ -273,7 +273,7 @@ pub(crate) fn try_update_rewarding_params(
|
||||
updated_params: IntervalRewardingParamsUpdate,
|
||||
force_immediately: bool,
|
||||
) -> Result<Response, MixnetContractError> {
|
||||
ensure_is_owner(info.sender, deps.storage)?;
|
||||
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;
|
||||
|
||||
if !updated_params.contains_updates() {
|
||||
return Err(MixnetContractError::EmptyParamsChangeMsg);
|
||||
@@ -1796,6 +1796,7 @@ pub mod tests {
|
||||
|
||||
#[cfg(test)]
|
||||
mod updating_active_set {
|
||||
use cw_controllers::AdminError::NotAdmin;
|
||||
use mixnet_contract_common::EpochStatus;
|
||||
|
||||
use crate::support::tests::test_helpers::TestSetup;
|
||||
@@ -1858,10 +1859,10 @@ pub mod tests {
|
||||
42,
|
||||
false,
|
||||
);
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
let res = try_update_active_set_size(test.deps_mut(), env.clone(), random, 42, false);
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
let res = try_update_active_set_size(test.deps_mut(), env, owner, 42, false);
|
||||
assert!(res.is_ok())
|
||||
@@ -2002,6 +2003,7 @@ pub mod tests {
|
||||
#[cfg(test)]
|
||||
mod updating_rewarding_params {
|
||||
use cosmwasm_std::Decimal;
|
||||
use cw_controllers::AdminError::NotAdmin;
|
||||
|
||||
use mixnet_contract_common::EpochStatus;
|
||||
|
||||
@@ -2085,11 +2087,11 @@ pub mod tests {
|
||||
update,
|
||||
false,
|
||||
);
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
let res =
|
||||
try_update_rewarding_params(test.deps_mut(), env.clone(), random, update, false);
|
||||
assert_eq!(res, Err(MixnetContractError::Unauthorized));
|
||||
assert_eq!(res, Err(MixnetContractError::Admin(NotAdmin {})));
|
||||
|
||||
let res = try_update_rewarding_params(test.deps_mut(), env, owner, update, false);
|
||||
assert!(res.is_ok())
|
||||
|
||||
@@ -194,20 +194,6 @@ pub(crate) fn ensure_can_advance_epoch(
|
||||
Ok(epoch_status)
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_is_owner(
|
||||
sender: Addr,
|
||||
storage: &dyn Storage,
|
||||
) -> Result<(), MixnetContractError> {
|
||||
if sender
|
||||
!= crate::mixnet_contract_settings::storage::CONTRACT_STATE
|
||||
.load(storage)?
|
||||
.owner
|
||||
{
|
||||
return Err(MixnetContractError::Unauthorized);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_bonded(bond: &MixNodeBond) -> Result<(), MixnetContractError> {
|
||||
if bond.is_unbonding {
|
||||
return Err(MixnetContractError::MixnodeIsUnbonding {
|
||||
|
||||
@@ -105,10 +105,11 @@ pub mod test_helpers {
|
||||
let deps = init_contract();
|
||||
let rewarding_validator_address =
|
||||
rewarding_validator_address(deps.as_ref().storage).unwrap();
|
||||
let owner = mixnet_params_storage::CONTRACT_STATE
|
||||
.load(deps.as_ref().storage)
|
||||
let owner = mixnet_params_storage::ADMIN
|
||||
.query_admin(deps.as_ref())
|
||||
.unwrap()
|
||||
.owner;
|
||||
.admin
|
||||
.unwrap();
|
||||
|
||||
TestSetup {
|
||||
deps,
|
||||
|
||||
Generated
+1
@@ -3281,6 +3281,7 @@ dependencies = [
|
||||
"bs58 0.4.0",
|
||||
"cosmwasm-schema",
|
||||
"cosmwasm-std",
|
||||
"cw-controllers",
|
||||
"humantime-serde",
|
||||
"log",
|
||||
"nym-contracts-common",
|
||||
|
||||
Reference in New Issue
Block a user