profit margin range validation

This commit is contained in:
Jędrzej Stuczyński
2024-07-18 11:45:59 +01:00
parent 60f9f33f3a
commit ef540edb16
4 changed files with 43 additions and 3 deletions
@@ -1,8 +1,9 @@
// Copyright 2022-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::{EpochEventId, EpochState, IdentityKey, MixId};
use crate::{EpochEventId, EpochState, IdentityKey, MixId, ProfitMarginRange};
use contracts_common::signing::verifier::ApiVerifierError;
use contracts_common::Percent;
use cosmwasm_std::{Addr, Coin, Decimal, Uint128};
use thiserror::Error;
@@ -239,6 +240,12 @@ pub enum MixnetContractError {
#[from]
source: ApiVerifierError,
},
#[error("the provided profit margin ({provided}) is outside the allowed range: {range}")]
ProfitMarginOutsideRange {
provided: Percent,
range: ProfitMarginRange,
},
}
impl MixnetContractError {
@@ -7,6 +7,7 @@ use contracts_common::Percent;
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use cosmwasm_std::Coin;
use std::fmt::{Display, Formatter};
use std::ops::Index;
// type aliases for better reasoning about available data
@@ -23,6 +24,12 @@ pub struct ProfitMarginRange {
pub maximum: Percent,
}
impl Display for ProfitMarginRange {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} - {}", self.minimum, self.maximum)
}
}
impl Default for ProfitMarginRange {
fn default() -> Self {
ProfitMarginRange {
@@ -42,6 +49,10 @@ impl ProfitMarginRange {
profit_margin
}
}
pub fn within_range(&self, profit_margin: Percent) -> bool {
profit_margin >= self.minimum && profit_margin <= self.maximum
}
}
/// Specifies layer assignment for the given mixnode.
@@ -25,8 +25,8 @@ use crate::mixnodes::signature_helpers::verify_mixnode_bonding_signature;
use crate::signing::storage as signing_storage;
use crate::support::helpers::{
ensure_bonded, ensure_epoch_in_progress_state, ensure_is_authorized, ensure_no_existing_bond,
ensure_no_pending_pledge_changes, ensure_proxy_match, ensure_sent_by_vesting_contract,
validate_pledge,
ensure_no_pending_pledge_changes, ensure_profit_margin_within_range, ensure_proxy_match,
ensure_sent_by_vesting_contract, validate_pledge,
};
use super::storage;
@@ -121,6 +121,9 @@ fn _try_add_mixnode(
owner_signature: MessageSignature,
proxy: Option<Addr>,
) -> Result<Response, MixnetContractError> {
// ensure the profit margin is within the defined range
ensure_profit_margin_within_range(deps.storage, cost_params.profit_margin_percent)?;
// check if the pledge contains any funds of the appropriate denomination
let minimum_pledge = mixnet_params_storage::minimum_mixnode_pledge(deps.storage)?;
let pledge = validate_pledge(pledge, minimum_pledge)?;
@@ -477,6 +480,9 @@ pub(crate) fn _try_update_mixnode_cost_params(
ensure_proxy_match(&proxy, &existing_bond.proxy)?;
ensure_bonded(&existing_bond)?;
// ensure the profit margin is within the defined range
ensure_profit_margin_within_range(deps.storage, new_costs.profit_margin_percent)?;
let cosmos_event = new_mixnode_pending_cost_params_update_event(
existing_bond.mix_id,
&owner,
+16
View File
@@ -8,6 +8,7 @@ use cosmwasm_std::{wasm_execute, Addr, BankMsg, Coin, CosmosMsg, MessageInfo, Re
use mixnet_contract_common::error::MixnetContractError;
use mixnet_contract_common::mixnode::PendingMixNodeChanges;
use mixnet_contract_common::{EpochState, EpochStatus, IdentityKeyRef, MixId, MixNodeBond};
use nym_contracts_common::Percent;
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
// helper trait to attach `Msg` to a response if it's provided
@@ -431,3 +432,18 @@ pub(crate) fn decode_ed25519_identity_key(
Ok(public_key)
}
pub(crate) fn ensure_profit_margin_within_range(
storage: &dyn Storage,
profit_margin: Percent,
) -> Result<(), MixnetContractError> {
let range = mixnet_params_storage::profit_margin_range(storage)?;
if !range.within_range(profit_margin) {
return Err(MixnetContractError::ProfitMarginOutsideRange {
provided: profit_margin,
range,
});
}
Ok(())
}