profit margin range validation

This commit is contained in:
Jędrzej Stuczyński
2024-07-18 11:45:59 +01:00
committed by fmtabbara
parent 8704c21621
commit c2ab47a102
4 changed files with 42 additions and 2 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;
@@ -240,6 +241,12 @@ pub enum MixnetContractError {
#[error("this delegation has not been performed with the vesting tokens or has already been migrated")]
NotAVestingDelegation,
#[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.
@@ -24,7 +24,7 @@ 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, validate_pledge,
ensure_no_pending_pledge_changes, ensure_profit_margin_within_range, validate_pledge,
};
use super::storage;
@@ -69,6 +69,9 @@ pub(crate) fn try_add_mixnode(
cost_params: MixNodeCostParams,
owner_signature: MessageSignature,
) -> 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(info.funds, minimum_pledge)?;
@@ -295,6 +298,9 @@ pub(crate) fn try_update_mixnode_cost_params(
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,
&info.sender,
+16
View File
@@ -7,6 +7,7 @@ use cosmwasm_std::{Addr, BankMsg, Coin, CosmosMsg, Response, Storage};
use mixnet_contract_common::error::MixnetContractError;
use mixnet_contract_common::mixnode::PendingMixNodeChanges;
use mixnet_contract_common::{EpochState, EpochStatus, IdentityKeyRef, MixNodeBond};
use nym_contracts_common::Percent;
// helper trait to attach `Msg` to a response if it's provided
#[allow(dead_code)]
@@ -267,3 +268,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(())
}