diff --git a/contracts/incentives/src/contract.rs b/contracts/incentives/src/contract.rs index a877040f5..37b97456a 100644 --- a/contracts/incentives/src/contract.rs +++ b/contracts/incentives/src/contract.rs @@ -1,10 +1,8 @@ -use std::collections::HashMap; - #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; use cosmwasm_std::{ - attr, coins, to_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env, - Event, MessageInfo, Order, Response, StdError, StdResult, Uint128, + attr, to_binary, Addr, BankMsg, Binary, Coin, Coins, Decimal, Deps, DepsMut, Env, Event, + MessageInfo, Order, Response, StdError, StdResult, Uint128, }; use cw_storage_plus::Bound; use mars_owner::{OwnerInit::SetInitialOwner, OwnerUpdate}; @@ -447,7 +445,7 @@ pub fn execute_claim_rewards( } else { base_event }; - let mut events = vec![base_event]; + response = response.add_event(base_event); let asset_incentives = state::paginate_incentive_states( deps.storage, @@ -456,7 +454,7 @@ pub fn execute_claim_rewards( limit, )?; - let mut total_unclaimed_rewards: HashMap = HashMap::new(); + let mut total_unclaimed_rewards = Coins::default(); for ((collateral_denom, incentive_denom), _) in asset_incentives { let querier = deps.querier; @@ -478,25 +476,25 @@ pub fn execute_claim_rewards( &Uint128::zero(), )?; - total_unclaimed_rewards - .entry(incentive_denom) - .and_modify(|amount| *amount += unclaimed_rewards) - .or_insert(unclaimed_rewards); + total_unclaimed_rewards.add(Coin { + denom: incentive_denom, + amount: unclaimed_rewards, + })?; } - for (denom, amount) in total_unclaimed_rewards.iter() { - response = response.add_message(CosmosMsg::Bank(BankMsg::Send { - to_address: user_addr.to_string(), - amount: coins(amount.u128(), denom), - })); - events.push( - Event::new("mars/incentives/claim_rewards/claimed_reward") - .add_attribute("denom", denom) - .add_attribute("amount", *amount), - ); + if !total_unclaimed_rewards.is_empty() { + response = response + .add_event( + Event::new("mars/incentives/claim_rewards/claimed_rewards") + .add_attribute("coins", total_unclaimed_rewards.to_string()), + ) + .add_message(BankMsg::Send { + to_address: user_addr.into(), + amount: total_unclaimed_rewards.into(), + }); } - Ok(response.add_events(events)) + Ok(response) } pub fn execute_update_config( @@ -675,7 +673,7 @@ pub fn query_user_unclaimed_rewards( limit, )?; - let mut total_unclaimed_rewards: HashMap = HashMap::new(); + let mut total_unclaimed_rewards = Coins::default(); for ((collateral_denom, incentive_denom), _) in incentive_states { let unclaimed_rewards = compute_user_unclaimed_rewards( @@ -688,19 +686,14 @@ pub fn query_user_unclaimed_rewards( &collateral_denom, &incentive_denom, )?; - total_unclaimed_rewards - .entry(incentive_denom) - .and_modify(|amount| *amount += unclaimed_rewards) - .or_insert(unclaimed_rewards); + + total_unclaimed_rewards.add(Coin { + denom: incentive_denom, + amount: unclaimed_rewards, + })?; } - Ok(total_unclaimed_rewards - .into_iter() - .map(|(denom, amount)| Coin { - denom, - amount, - }) - .collect()) + Ok(total_unclaimed_rewards.into()) } fn query_red_bank_address(deps: Deps) -> StdResult { diff --git a/contracts/incentives/tests/test_claim_rewards.rs b/contracts/incentives/tests/test_claim_rewards.rs index 8320d81ec..af545c28d 100644 --- a/contracts/incentives/tests/test_claim_rewards.rs +++ b/contracts/incentives/tests/test_claim_rewards.rs @@ -226,6 +226,10 @@ fn execute_claim_rewards() { let res = execute(deps.as_mut(), env.clone(), info, msg).unwrap(); // query after execution gives 0 rewards + // + // NOTE: the query should return an empty array, instead of a non-empty array + // with a zero-amount coin! the latter is considered an invalid coins array + // and will result in error. let rewards_query_after = query_user_unclaimed_rewards( deps.as_ref(), env, @@ -236,7 +240,7 @@ fn execute_claim_rewards() { None, ) .unwrap(); - assert_eq!(rewards_query_after[0].amount, Uint128::zero()); + assert!(rewards_query_after.is_empty()); // ASSERT @@ -254,7 +258,7 @@ fn execute_claim_rewards() { ); assert_eq!( res.events[1].attributes, - vec![attr("denom", "umars"), attr("amount", expected_accrued_rewards),] + vec![attr("coins", format!("{expected_accrued_rewards}umars"))] ); // asset and zero incentives get updated, no_user does not let asset_incentive =