use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{Addr, Env, StdResult, Uint128};
use litium_refer::contract::{execute, query};
use litium_refer::error::ContractError;
use litium_refer::msg::{
CommunityPoolBalanceResponse, ExecuteMsg, QueryMsg, ReferralInfoResponse, ReferrerOfResponse,
TestingOverrides, TotalPendingRewardsResponse,
};
use litium_refer::state::{
ReferConfig, COMMUNITY_POOL_BALANCE, CONFIG, TOTAL_ACCRUED_REWARDS, TOTAL_CLAIMED_REWARDS,
};
fn setup() -> (
cosmwasm_std::OwnedDeps<
cosmwasm_std::MemoryStorage,
cosmwasm_std::testing::MockApi,
cosmwasm_std::testing::MockQuerier,
>,
Env,
) {
let mut deps = mock_dependencies();
let env = mock_env();
let config = ReferConfig {
core_contract: Addr::unchecked("core_contract"),
mine_contract: Addr::unchecked("mine_contract"),
community_pool_addr: None,
admin: Addr::unchecked("admin"),
paused: false,
};
CONFIG.save(deps.as_mut().storage, &config).unwrap();
COMMUNITY_POOL_BALANCE
.save(deps.as_mut().storage, &Uint128::zero())
.unwrap();
TOTAL_ACCRUED_REWARDS
.save(deps.as_mut().storage, &Uint128::zero())
.unwrap();
TOTAL_CLAIMED_REWARDS
.save(deps.as_mut().storage, &Uint128::zero())
.unwrap();
(deps, env)
}
#[test]
fn only_mine_can_bind_referrer() {
let (mut deps, env) = setup();
let info = mock_info("random", &[]);
let err = execute(
deps.as_mut(),
env,
info,
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "referrer1".to_string(),
},
)
.unwrap_err();
assert_eq!(err, ContractError::NotMineContract {});
}
#[test]
fn bind_referrer_works() {
let (mut deps, env) = setup();
let info = mock_info("mine_contract", &[]);
execute(
deps.as_mut(),
env.clone(),
info,
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "referrer1".to_string(),
},
)
.unwrap();
let resp: ReferrerOfResponse = cosmwasm_std::from_json(
query(
deps.as_ref(),
env,
QueryMsg::ReferrerOf {
miner: "miner1".to_string(),
},
)
.unwrap(),
)
.unwrap();
assert_eq!(resp.referrer, Some("referrer1".to_string()));
}
#[test]
fn self_referral_rejected() {
let (mut deps, env) = setup();
let info = mock_info("mine_contract", &[]);
let err = execute(
deps.as_mut(),
env,
info,
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "miner1".to_string(),
},
)
.unwrap_err();
assert_eq!(err, ContractError::SelfReferral {});
}
#[test]
fn referrer_mismatch_rejected() {
let (mut deps, env) = setup();
let info = mock_info("mine_contract", &[]);
execute(
deps.as_mut(),
env.clone(),
info.clone(),
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "referrer1".to_string(),
},
)
.unwrap();
let err = execute(
deps.as_mut(),
env,
info,
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "referrer2".to_string(),
},
)
.unwrap_err();
assert_eq!(err, ContractError::ReferrerMismatch {});
}
#[test]
fn accrue_to_referrer() {
let (mut deps, env) = setup();
let info = mock_info("mine_contract", &[]);
// Bind first
execute(
deps.as_mut(),
env.clone(),
info.clone(),
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "referrer1".to_string(),
},
)
.unwrap();
// Accrue
execute(
deps.as_mut(),
env.clone(),
info,
ExecuteMsg::AccrueReward {
miner: "miner1".to_string(),
amount: Uint128::from(100u128),
},
)
.unwrap();
let resp: ReferralInfoResponse = cosmwasm_std::from_json(
query(
deps.as_ref(),
env,
QueryMsg::ReferralInfo {
address: "referrer1".to_string(),
},
)
.unwrap(),
)
.unwrap();
assert_eq!(resp.referral_rewards, Uint128::from(100u128));
assert_eq!(resp.referrals_count, 1);
}
#[test]
fn accrue_to_community_pool_when_no_referrer() {
let (mut deps, env) = setup();
let info = mock_info("mine_contract", &[]);
// Accrue without binding referrer
execute(
deps.as_mut(),
env.clone(),
info,
ExecuteMsg::AccrueReward {
miner: "miner1".to_string(),
amount: Uint128::from(100u128),
},
)
.unwrap();
let resp: CommunityPoolBalanceResponse = cosmwasm_std::from_json(
query(deps.as_ref(), env, QueryMsg::CommunityPoolBalance {}).unwrap(),
)
.unwrap();
assert_eq!(resp.balance, Uint128::from(100u128));
}
#[test]
fn claim_rewards() {
let (mut deps, env) = setup();
let info = mock_info("mine_contract", &[]);
// Bind + accrue
execute(
deps.as_mut(),
env.clone(),
info.clone(),
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "referrer1".to_string(),
},
)
.unwrap();
execute(
deps.as_mut(),
env.clone(),
info,
ExecuteMsg::AccrueReward {
miner: "miner1".to_string(),
amount: Uint128::from(100u128),
},
)
.unwrap();
// Claim as referrer
let info = mock_info("referrer1", &[]);
let res = execute(
deps.as_mut(),
env.clone(),
info,
ExecuteMsg::ClaimRewards {},
)
.unwrap();
assert_eq!(res.messages.len(), 1); // Mint msg to core
// Should be zero after claim
let resp: ReferralInfoResponse = cosmwasm_std::from_json(
query(
deps.as_ref(),
env,
QueryMsg::ReferralInfo {
address: "referrer1".to_string(),
},
)
.unwrap(),
)
.unwrap();
assert_eq!(resp.referral_rewards, Uint128::zero());
}
#[test]
fn claim_rewards_rejected_when_paused() {
let (mut deps, env) = setup();
CONFIG
.update(deps.as_mut().storage, |mut c| -> StdResult<_> {
c.paused = true;
Ok(c)
})
.unwrap();
let err = execute(
deps.as_mut(),
env,
mock_info("referrer1", &[]),
ExecuteMsg::ClaimRewards {},
)
.unwrap_err();
assert_eq!(err, ContractError::Paused {});
}
#[test]
fn claim_community_pool_rejected_when_paused() {
let (mut deps, env) = setup();
CONFIG
.update(deps.as_mut().storage, |mut c| -> StdResult<_> {
c.paused = true;
Ok(c)
})
.unwrap();
let err = execute(
deps.as_mut(),
env,
mock_info("admin", &[]),
ExecuteMsg::ClaimCommunityPool {
to: "recipient".to_string(),
},
)
.unwrap_err();
assert_eq!(err, ContractError::Paused {});
}
#[test]
fn claim_community_pool_requires_admin() {
let (mut deps, env) = setup();
COMMUNITY_POOL_BALANCE
.save(deps.as_mut().storage, &Uint128::from(10u128))
.unwrap();
let err = execute(
deps.as_mut(),
env,
mock_info("not_admin", &[]),
ExecuteMsg::ClaimCommunityPool {
to: "recipient".to_string(),
},
)
.unwrap_err();
assert_eq!(err, ContractError::Unauthorized {});
}
#[test]
fn apply_testing_overrides_admin_updates_state() {
let (mut deps, env) = setup();
let info = mock_info("admin", &[]);
execute(
deps.as_mut(),
env,
info,
ExecuteMsg::ApplyTestingOverrides {
overrides: TestingOverrides {
paused: Some(true),
community_pool_addr: Some("pool".to_string()),
community_pool_balance: Some(Uint128::from(123u128)),
total_accrued_rewards: Some(Uint128::from(321u128)),
total_claimed_rewards: Some(Uint128::from(21u128)),
},
},
)
.unwrap();
let cfg = CONFIG.load(deps.as_ref().storage).unwrap();
assert!(cfg.paused);
assert_eq!(cfg.community_pool_addr.unwrap().as_str(), "pool");
assert_eq!(
COMMUNITY_POOL_BALANCE.load(deps.as_ref().storage).unwrap(),
Uint128::from(123u128)
);
assert_eq!(
TOTAL_ACCRUED_REWARDS.load(deps.as_ref().storage).unwrap(),
Uint128::from(321u128)
);
assert_eq!(
TOTAL_CLAIMED_REWARDS.load(deps.as_ref().storage).unwrap(),
Uint128::from(21u128)
);
}
#[test]
fn apply_testing_overrides_unauthorized() {
let (mut deps, env) = setup();
let info = mock_info("hacker", &[]);
let err = execute(
deps.as_mut(),
env,
info,
ExecuteMsg::ApplyTestingOverrides {
overrides: TestingOverrides {
paused: Some(true),
community_pool_addr: None,
community_pool_balance: None,
total_accrued_rewards: None,
total_claimed_rewards: None,
},
},
)
.unwrap_err();
assert_eq!(err, ContractError::Unauthorized {});
}
/// Regression: when claimed exceeds accrued (should never happen but defensive),
/// TotalPendingRewards query must return 0 (not panic from overflow).
#[test]
fn total_pending_rewards_saturates_on_overshoot() {
let (mut deps, env) = setup();
TOTAL_ACCRUED_REWARDS
.save(deps.as_mut().storage, &Uint128::from(50u128))
.unwrap();
TOTAL_CLAIMED_REWARDS
.save(deps.as_mut().storage, &Uint128::from(55u128))
.unwrap();
let resp: TotalPendingRewardsResponse = cosmwasm_std::from_json(
query(deps.as_ref(), env, QueryMsg::TotalPendingRewards {}).unwrap(),
)
.unwrap();
assert_eq!(resp.total_pending_rewards, Uint128::zero());
}
/// Verify claim increments TOTAL_CLAIMED_REWARDS instead of decrementing a single counter.
#[test]
fn claim_rewards_increments_claimed_counter() {
let (mut deps, env) = setup();
// Bind referrer and accrue reward
let mine_info = mock_info("mine_contract", &[]);
execute(
deps.as_mut(),
env.clone(),
mine_info.clone(),
ExecuteMsg::BindReferrer {
miner: "miner1".to_string(),
referrer: "referrer1".to_string(),
},
)
.unwrap();
execute(
deps.as_mut(),
env.clone(),
mine_info,
ExecuteMsg::AccrueReward {
miner: "miner1".to_string(),
amount: Uint128::from(200u128),
},
)
.unwrap();
let accrued = TOTAL_ACCRUED_REWARDS.load(deps.as_ref().storage).unwrap();
assert_eq!(accrued, Uint128::from(200u128));
assert_eq!(
TOTAL_CLAIMED_REWARDS.load(deps.as_ref().storage).unwrap(),
Uint128::zero()
);
// Claim as referrer
execute(
deps.as_mut(),
env.clone(),
mock_info("referrer1", &[]),
ExecuteMsg::ClaimRewards {},
)
.unwrap();
// Accrued unchanged, claimed increased
assert_eq!(
TOTAL_ACCRUED_REWARDS.load(deps.as_ref().storage).unwrap(),
Uint128::from(200u128)
);
assert_eq!(
TOTAL_CLAIMED_REWARDS.load(deps.as_ref().storage).unwrap(),
Uint128::from(200u128)
);
// Query returns zero pending
let resp: TotalPendingRewardsResponse = cosmwasm_std::from_json(
query(deps.as_ref(), env, QueryMsg::TotalPendingRewards {}).unwrap(),
)
.unwrap();
assert_eq!(resp.total_pending_rewards, Uint128::zero());
}
cw-cyber/tests/litium-tests/tests/unit_refer.rs
ฯ 0.0%
use ;
use ;
use ;
use ContractError;
use ;
use ;
/// Regression: when claimed exceeds accrued (should never happen but defensive),
/// TotalPendingRewards query must return 0 (not panic from overflow).
/// Verify claim increments TOTAL_CLAIMED_REWARDS instead of decrementing a single counter.