Skip to content

Commit 75e509c

Browse files
committed
additional tests for transactions and fixes
1 parent 77f38e0 commit 75e509c

File tree

8 files changed

+1235
-45
lines changed

8 files changed

+1235
-45
lines changed

common/cosmwasm-smart-contracts/nym-pool-contract/src/error.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,8 @@ pub enum NymPoolContractError {
4444
current_block_timestamp: u64,
4545
},
4646

47-
#[error("there are not enough tokens to process this grant. {available} are available, but {requested_grant} was requested.")]
48-
InsufficientTokens {
49-
available: Coin,
50-
requested_grant: Coin,
51-
},
47+
#[error("there are not enough tokens to process this request. {available} are available, but {required} is needed.")]
48+
InsufficientTokens { available: Coin, required: Coin },
5249

5350
#[error("the period length can't be zero")]
5451
ZeroAllowancePeriod,
@@ -95,4 +92,7 @@ pub enum NymPoolContractError {
9592

9693
#[error("the associated grant hasn't expired yet")]
9794
GrantNotExpired,
95+
96+
#[error("this grant is not available yet. it will become usable at {available_at_timestamp}")]
97+
GrantNotYetAvailable { available_at_timestamp: u64 },
9898
}

common/cosmwasm-smart-contracts/nym-pool-contract/src/types.rs

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,16 @@ pub mod grants {
159159

160160
// check whether given the current allowance state, the provided amount could be spent
161161
// note: it's responsibility of the caller to call `try_update_state` before the call.
162-
pub fn can_spend(&self, env: &Env, amount: &Coin) -> bool {
162+
pub fn ensure_can_spend(
163+
&self,
164+
env: &Env,
165+
amount: &Coin,
166+
) -> Result<(), NymPoolContractError> {
163167
match self {
164-
Allowance::Basic(allowance) => allowance.can_spend(env, amount),
165-
Allowance::ClassicPeriodic(allowance) => allowance.can_spend(env, amount),
166-
Allowance::CumulativePeriodic(allowance) => allowance.can_spend(env, amount),
167-
Allowance::Delayed(allowance) => allowance.can_spend(env, amount),
168+
Allowance::Basic(allowance) => allowance.ensure_can_spend(env, amount),
169+
Allowance::ClassicPeriodic(allowance) => allowance.ensure_can_spend(env, amount),
170+
Allowance::CumulativePeriodic(allowance) => allowance.ensure_can_spend(env, amount),
171+
Allowance::Delayed(allowance) => allowance.ensure_can_spend(env, amount),
168172
}
169173
}
170174

@@ -255,14 +259,18 @@ pub mod grants {
255259
spend_limit.amount >= amount.amount
256260
}
257261

258-
fn can_spend(&self, env: &Env, amount: &Coin) -> bool {
259-
!self.expired(env) && self.within_spendable_limits(amount)
262+
fn ensure_can_spend(&self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
263+
if self.expired(env) {
264+
return Err(NymPoolContractError::GrantExpired);
265+
}
266+
if !self.within_spendable_limits(amount) {
267+
return Err(NymPoolContractError::SpendingAboveAllowance);
268+
}
269+
Ok(())
260270
}
261271

262272
fn try_spend(&mut self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
263-
if !self.can_spend(env, amount) {
264-
return Err(NymPoolContractError::SpendingAboveAllowance);
265-
}
273+
self.ensure_can_spend(env, amount)?;
266274

267275
if let Some(ref mut spend_limit) = self.spend_limit {
268276
spend_limit.amount -= amount.amount;
@@ -391,14 +399,18 @@ pub mod grants {
391399
available.amount >= amount.amount
392400
}
393401

394-
fn can_spend(&self, env: &Env, amount: &Coin) -> bool {
395-
!self.basic.expired(env) && self.within_spendable_limits(amount)
402+
fn ensure_can_spend(&self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
403+
if self.basic.expired(env) {
404+
return Err(NymPoolContractError::GrantExpired);
405+
}
406+
if !self.within_spendable_limits(amount) {
407+
return Err(NymPoolContractError::SpendingAboveAllowance);
408+
}
409+
Ok(())
396410
}
397411

398412
fn try_spend(&mut self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
399-
if !self.can_spend(env, amount) {
400-
return Err(NymPoolContractError::SpendingAboveAllowance);
401-
}
413+
self.ensure_can_spend(env, amount)?;
402414

403415
// deduct from both the current period and the max amount
404416
if let Some(ref mut spend_limit) = self.basic.spend_limit {
@@ -567,14 +579,18 @@ pub mod grants {
567579
available.amount >= amount.amount
568580
}
569581

570-
fn can_spend(&self, env: &Env, amount: &Coin) -> bool {
571-
!self.basic.expired(env) && self.within_spendable_limits(amount)
582+
fn ensure_can_spend(&self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
583+
if self.basic.expired(env) {
584+
return Err(NymPoolContractError::GrantExpired);
585+
}
586+
if !self.within_spendable_limits(amount) {
587+
return Err(NymPoolContractError::SpendingAboveAllowance);
588+
}
589+
Ok(())
572590
}
573591

574592
fn try_spend(&mut self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
575-
if !self.can_spend(env, amount) {
576-
return Err(NymPoolContractError::SpendingAboveAllowance);
577-
}
593+
self.ensure_can_spend(env, amount)?;
578594

579595
// deduct from both the current period and the max amount
580596
if let Some(ref mut spend_limit) = self.basic.spend_limit {
@@ -625,16 +641,24 @@ pub mod grants {
625641
self.basic.within_spendable_limits(amount)
626642
}
627643

628-
fn can_spend(&self, env: &Env, amount: &Coin) -> bool {
629-
!self.basic.expired(env)
630-
&& self.within_spendable_limits(amount)
631-
&& self.available_at_unix_timestamp >= env.block.time.seconds()
644+
fn ensure_can_spend(&self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
645+
if self.basic.expired(env) {
646+
return Err(NymPoolContractError::GrantExpired);
647+
}
648+
if !self.within_spendable_limits(amount) {
649+
return Err(NymPoolContractError::SpendingAboveAllowance);
650+
}
651+
if self.available_at_unix_timestamp < env.block.time.seconds() {
652+
return Err(NymPoolContractError::GrantNotYetAvailable {
653+
available_at_timestamp: self.available_at_unix_timestamp,
654+
});
655+
}
656+
657+
Ok(())
632658
}
633659

634660
fn try_spend(&mut self, env: &Env, amount: &Coin) -> Result<(), NymPoolContractError> {
635-
if !self.can_spend(env, amount) {
636-
return Err(NymPoolContractError::SpendingAboveAllowance);
637-
}
661+
self.ensure_can_spend(env, amount)?;
638662

639663
if let Some(ref mut spend_limit) = self.basic.spend_limit {
640664
spend_limit.amount -= amount.amount;

contracts/nym-pool/src/contract.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,7 @@ mod tests {
194194
mod setting_initial_grants {
195195
use super::*;
196196
use crate::testing::deps_with_balance;
197-
use cosmwasm_std::testing::{MockApi, MockQuerier, MockStorage};
198-
use cosmwasm_std::{coin, coins, Empty, MemoryStorage, Order, OwnedDeps, Storage};
197+
use cosmwasm_std::{coin, Order, Storage};
199198
use nym_pool_contract_common::{Allowance, BasicAllowance, Grant, GranteeAddress};
200199
use std::collections::HashMap;
201200

contracts/nym-pool/src/queries.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ mod tests {
183183
use super::*;
184184
use crate::contract::instantiate;
185185
use crate::testing::{TestSetup, TEST_DENOM};
186-
use cosmwasm_std::testing::{
187-
message_info, mock_dependencies, mock_dependencies_with_balance, mock_env,
188-
};
186+
use cosmwasm_std::testing::{message_info, mock_dependencies_with_balance, mock_env};
189187
use cosmwasm_std::{coin, Uint128};
190188
use nym_pool_contract_common::{Allowance, BasicAllowance, GranterInformation, InstantiateMsg};
191189

@@ -564,7 +562,6 @@ mod tests {
564562
#[cfg(test)]
565563
mod grants_paged_query {
566564
use super::*;
567-
use nym_pool_contract_common::GranteeAddress;
568565

569566
fn grants_sorted(test: &mut TestSetup, count: usize) -> Vec<GrantInformation> {
570567
let mut grantees = Vec::new();

contracts/nym-pool/src/storage.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl NymPoolStorage {
7878
let balance = self.contract_balance(deps.as_ref(), &env)?;
7979
if required_amount > balance.amount || balance.amount.is_zero() {
8080
return Err(NymPoolContractError::InsufficientTokens {
81-
requested_grant: coin(max(required_amount.u128(), 1), &balance.denom),
81+
required: coin(max(required_amount.u128(), 1), &balance.denom),
8282
available: balance,
8383
});
8484
}
@@ -243,7 +243,7 @@ impl NymPoolStorage {
243243
if spend_limit.amount > available.amount {
244244
return Err(NymPoolContractError::InsufficientTokens {
245245
available,
246-
requested_grant: spend_limit.clone(),
246+
required: spend_limit.clone(),
247247
});
248248
}
249249
}
@@ -501,7 +501,7 @@ mod tests {
501501
use super::*;
502502
use crate::testing::{deps_with_balance, TEST_DENOM};
503503
use cosmwasm_std::testing::{mock_dependencies, mock_env};
504-
use cosmwasm_std::{coin, MemoryStorage, Order};
504+
use cosmwasm_std::{coin, Order};
505505
use nym_pool_contract_common::BasicAllowance;
506506

507507
fn all_grants(storage: &dyn Storage) -> HashMap<GranteeAddress, Grant> {
@@ -1922,9 +1922,10 @@ mod tests {
19221922
let storage = NymPoolStorage::new();
19231923
let env = test.env();
19241924
let grantee = test.add_dummy_grant().grantee;
1925-
let amount = test.coin(100);
1925+
let amount1 = test.coin(100);
1926+
let amount2 = test.coin(200);
19261927

1927-
storage.lock_part_of_allowance(test.deps_mut(), &env, &grantee, amount)?;
1928+
storage.lock_part_of_allowance(test.deps_mut(), &env, &grantee, amount1)?;
19281929
assert_eq!(
19291930
storage.locked.grantee_locked(test.storage(), &grantee)?,
19301931
Uint128::new(100)
@@ -1934,6 +1935,17 @@ mod tests {
19341935
Uint128::new(100)
19351936
);
19361937

1938+
// more locked by same grantee
1939+
storage.lock_part_of_allowance(test.deps_mut(), &env, &grantee, amount2)?;
1940+
assert_eq!(
1941+
storage.locked.grantee_locked(test.storage(), &grantee)?,
1942+
Uint128::new(300)
1943+
);
1944+
assert_eq!(
1945+
storage.locked.total_locked.load(test.storage())?,
1946+
Uint128::new(300)
1947+
);
1948+
19371949
Ok(())
19381950
}
19391951
}

contracts/nym-pool/src/testing/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ impl TestSetup {
107107
}
108108
}
109109

110+
pub fn set_contract_balance(&mut self, balance: Coin) {
111+
let contract_address = &self.contract_address;
112+
self.app
113+
.router()
114+
.bank
115+
.init_balance(
116+
&mut self.storage.inner_storage(),
117+
contract_address,
118+
vec![balance],
119+
)
120+
.unwrap();
121+
}
122+
110123
pub fn deps(&self) -> Deps<'_> {
111124
Deps {
112125
storage: &self.storage,

contracts/nym-pool/src/testing/storage.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ pub(crate) struct ContractStorageWrapper {
2929
inner: StorageWrapper,
3030
}
3131

32+
impl ContractStorageWrapper {
33+
pub fn inner_storage(&self) -> StorageWrapper {
34+
self.inner.clone()
35+
}
36+
}
37+
3238
impl Storage for StorageWrapper {
3339
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
3440
self.0.borrow().get(key)

0 commit comments

Comments
 (0)