From a4cfd53c105bfbd7e52d63b93337932431023a0b Mon Sep 17 00:00:00 2001 From: Supanat Potiwarakorn Date: Tue, 26 Sep 2023 10:44:26 +0700 Subject: [PATCH] validate the denom of each new limiter to be part of the pool assets --- contracts/transmuter/src/contract.rs | 30 ++++++++++++++++++ .../src/transmuter_pool/has_denom.rs | 31 +++++++++++++++++++ .../transmuter/src/transmuter_pool/mod.rs | 1 + 3 files changed, 62 insertions(+) create mode 100644 contracts/transmuter/src/transmuter_pool/has_denom.rs diff --git a/contracts/transmuter/src/contract.rs b/contracts/transmuter/src/contract.rs index 59f5312..093a6e5 100644 --- a/contracts/transmuter/src/contract.rs +++ b/contracts/transmuter/src/contract.rs @@ -144,6 +144,13 @@ impl Transmuter<'_> { // only admin can register limiter ensure_admin_authority!(info.sender, self.role.admin, deps.as_ref()); + // ensure pool has the specified denom + let pool = self.pool.load(deps.storage)?; + ensure!( + pool.has_denom(&denom), + ContractError::InvalidPoolAssetDenom { denom } + ); + let base_attrs = vec![ ("method", "register_limiter"), ("denom", &denom), @@ -1550,6 +1557,29 @@ mod tests { assert_eq!(res.attributes, attrs); + // denom that is not in the pool can't be registered + let err = execute( + deps.as_mut(), + mock_env(), + mock_info(admin, &[]), + ContractExecMsg::Transmuter(ExecMsg::RegisterLimiter { + denom: "invalid_denom".to_string(), + label: "1h".to_string(), + limiter_params: LimiterParams::ChangeLimiter { + window_config: window_config_1h.clone(), + boundary_offset: Decimal::percent(1), + }, + }), + ) + .unwrap_err(); + + assert_eq!( + err, + ContractError::InvalidPoolAssetDenom { + denom: "invalid_denom".to_string(), + } + ); + // Query the list of limiters let query_msg = ContractQueryMsg::Transmuter(QueryMsg::ListLimiters {}); let res = query(deps.as_ref(), mock_env(), query_msg).unwrap(); diff --git a/contracts/transmuter/src/transmuter_pool/has_denom.rs b/contracts/transmuter/src/transmuter_pool/has_denom.rs new file mode 100644 index 0000000..42e861f --- /dev/null +++ b/contracts/transmuter/src/transmuter_pool/has_denom.rs @@ -0,0 +1,31 @@ +use super::TransmuterPool; + +impl TransmuterPool { + /// Check if the pool has the specified denom + pub fn has_denom(&self, denom: &str) -> bool { + self.pool_assets + .iter() + .any(|pool_asset| pool_asset.denom == denom) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::denom::Denom; + + #[test] + fn test_has_denom() { + let pool_assets = vec![ + Denom::unchecked("asset1"), + Denom::unchecked("asset2"), + Denom::unchecked("asset3"), + ]; + let pool = TransmuterPool::new(&pool_assets).unwrap(); + + assert!(pool.has_denom("asset1")); + assert!(pool.has_denom("asset2")); + assert!(pool.has_denom("asset3")); + assert!(!pool.has_denom("asset4")); + } +} diff --git a/contracts/transmuter/src/transmuter_pool/mod.rs b/contracts/transmuter/src/transmuter_pool/mod.rs index 17b4db2..aa9e110 100644 --- a/contracts/transmuter/src/transmuter_pool/mod.rs +++ b/contracts/transmuter/src/transmuter_pool/mod.rs @@ -2,6 +2,7 @@ mod exit_pool; mod join_pool; mod transmute; mod weight; +mod has_denom; use cosmwasm_schema::cw_serde; use cosmwasm_std::{ensure, Coin, Uint64};