Skip to content

Commit 5f2377c

Browse files
authored
Merge pull request #884 from interlay/fix/no-rewards-when-not-accepting-issues
fix: set stake in reward pool to 0 when vault is not accepting new issues
2 parents babf97a + 4e54deb commit 5f2377c

File tree

5 files changed

+61
-17
lines changed

5 files changed

+61
-17
lines changed

crates/vault-registry/src/lib.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ pub mod pallet {
240240
let vault_id = VaultId::new(account_id, currency_pair.collateral, currency_pair.wrapped);
241241
let mut vault = Self::get_active_rich_vault_from_id(&vault_id)?;
242242
vault.set_accept_new_issues(accept_new_issues)?;
243+
PoolManager::<T>::on_vault_settings_change(&vault_id)?;
243244
Ok(().into())
244245
}
245246

@@ -262,7 +263,7 @@ pub mod pallet {
262263
let account_id = ensure_signed(origin)?;
263264
let vault_id = VaultId::new(account_id, currency_pair.collateral, currency_pair.wrapped);
264265
Self::try_set_vault_custom_secure_threshold(&vault_id, custom_threshold)?;
265-
PoolManager::<T>::on_set_secure_collateral_threshold(&vault_id)?;
266+
PoolManager::<T>::on_vault_settings_change(&vault_id)?;
266267
Ok(().into())
267268
}
268269

@@ -1932,11 +1933,15 @@ impl<T: Config> Pallet<T> {
19321933
assert!(reserved.ge(&backing_collateral).unwrap());
19331934

19341935
let rich_vault: RichVault<T> = vault.clone().into();
1935-
let expected_stake = rich_vault
1936-
.get_total_collateral()
1937-
.unwrap()
1938-
.checked_div(&rich_vault.get_secure_threshold().unwrap())
1939-
.unwrap();
1936+
let expected_stake = if !vault.accepts_new_issues() {
1937+
Amount::zero(vault_id.collateral_currency())
1938+
} else {
1939+
rich_vault
1940+
.get_total_collateral()
1941+
.unwrap()
1942+
.checked_div(&rich_vault.get_secure_threshold().unwrap())
1943+
.unwrap()
1944+
};
19401945

19411946
assert_eq!(ext::reward::get_stake::<T>(&vault_id).unwrap(), expected_stake.amount());
19421947
}

crates/vault-registry/src/pool_manager.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,26 @@ impl<T: Config> PoolManager<T> {
4747
Ok(ret)
4848
}
4949

50-
// hook to be called _after_ the value has been written
51-
pub fn on_set_secure_collateral_threshold(vault_id: &DefaultVaultId<T>) -> Result<(), DispatchError> {
50+
// hook to be called _after_ one of the vault parameters that influences
51+
// capacity has been written. This is called when the custom secure threshold or
52+
// the accept_new_issues setting changes.
53+
pub fn on_vault_settings_change(vault_id: &DefaultVaultId<T>) -> Result<(), DispatchError> {
5254
ext::fee::distribute_all_vault_rewards::<T>(vault_id)?;
5355
Self::update_reward_stake(vault_id)
5456
}
5557

5658
// NOTE: temporarily public for reward migration
5759
pub(crate) fn update_reward_stake(vault_id: &DefaultVaultId<T>) -> Result<(), DispatchError> {
58-
let total_collateral = ext::staking::total_current_stake::<T>(vault_id)?;
59-
let secure_threshold = Pallet::<T>::get_vault_secure_threshold(vault_id)?;
60-
61-
let new_reward_stake = total_collateral.checked_div(&secure_threshold)?;
60+
let vault = Pallet::<T>::get_vault_from_id(vault_id)?;
61+
let new_reward_stake = if !vault.accepts_new_issues() {
62+
// if the vault is not accepting new issues it's not getting rewards
63+
Amount::zero(vault_id.collateral_currency())
64+
} else {
65+
let total_collateral = ext::staking::total_current_stake::<T>(vault_id)?;
66+
let secure_threshold = Pallet::<T>::get_vault_secure_threshold(vault_id)?;
67+
68+
total_collateral.checked_div(&secure_threshold)?
69+
};
6270

6371
ext::reward::set_stake(vault_id, &new_reward_stake)?;
6472

crates/vault-registry/src/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ impl<
217217
pub fn is_liquidated(&self) -> bool {
218218
matches!(self.status, VaultStatus::Liquidated)
219219
}
220+
221+
pub fn accepts_new_issues(&self) -> bool {
222+
matches!(self.status, VaultStatus::Active(true))
223+
}
220224
}
221225

222226
pub type DefaultVault<T> = Vault<

standalone/runtime/tests/mock/reward_testing_utils.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub type StakeId = (VaultId, AccountId);
88
pub struct IdealRewardPool {
99
exchange_rate: BTreeMap<CurrencyId, FixedU128>,
1010
secure_threshold: BTreeMap<VaultId, FixedU128>,
11+
accept_new_issues: BTreeMap<VaultId, bool>,
1112
commission: BTreeMap<VaultId, FixedU128>,
1213
collateral: BTreeMap<StakeId, u128>,
1314
rewards: BTreeMap<AccountId, (FixedU128, FixedU128)>,
@@ -72,6 +73,10 @@ impl IdealRewardPool {
7273
.map(|(stake_id, _)| self.stake(stake_id))
7374
.fold(Zero::zero(), |x: FixedU128, y: FixedU128| x + y);
7475

76+
if total_stake.is_zero() {
77+
return self;
78+
}
79+
7580
for (stake_id, _) in self.collateral.iter() {
7681
let stake = self.stake(stake_id);
7782
let reward = (stake * reward) / total_stake;
@@ -95,6 +100,12 @@ impl IdealRewardPool {
95100
self
96101
}
97102

103+
pub fn accept_new_issues(&mut self, vault: &VaultId, accept_new_issues: bool) -> &mut Self {
104+
log::debug!("accept_new_issues {:?}", accept_new_issues);
105+
self.accept_new_issues.insert(vault.clone(), accept_new_issues);
106+
self
107+
}
108+
98109
pub fn get_total_reward_for(&self, account: &crate::AccountId) -> u128 {
99110
self.rewards
100111
.get(account)
@@ -132,9 +143,13 @@ impl IdealRewardPool {
132143

133144
pub fn stake(&self, (vault_id, nominator_id): &StakeId) -> FixedU128 {
134145
let currency_id = vault_id.collateral_currency();
135-
let threshold = self.secure_threshold[vault_id];
136-
let exchange_rate = self.exchange_rate[&currency_id];
137-
let collateral = self.collateral[&(vault_id.clone(), nominator_id.clone())];
138-
FixedU128::from(collateral) / threshold / exchange_rate
146+
if !self.accept_new_issues.get(vault_id).unwrap_or(&true) {
147+
Zero::zero()
148+
} else {
149+
let threshold = self.secure_threshold[vault_id];
150+
let exchange_rate = self.exchange_rate[&currency_id];
151+
let collateral = self.collateral[&(vault_id.clone(), nominator_id.clone())];
152+
FixedU128::from(collateral) / threshold / exchange_rate
153+
}
139154
}
140155
}

standalone/runtime/tests/test_fee_pool.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,18 +413,20 @@ enum Action {
413413
SetSecureThreshold,
414414
DistributeRewards,
415415
SetExchangeRate,
416+
SetAcceptIssues,
416417
}
417418

418419
impl Action {
419420
fn random<R: Rng + ?Sized>(rng: &mut R) -> Action {
420-
match rng.gen_range(0..7) {
421+
match rng.gen_range(0..8) {
421422
0 => Self::DepositNominationCollateral,
422423
1 => Self::WithdrawNominationCollateral,
423424
2 => Self::DepositVaultCollateral,
424425
3 => Self::WithdrawVaultCollateral,
425426
4 => Self::SetSecureThreshold,
426427
5 => Self::DistributeRewards,
427428
6 => Self::SetExchangeRate,
429+
7 => Self::SetAcceptIssues,
428430
_ => unreachable!(),
429431
}
430432
}
@@ -645,6 +647,16 @@ fn do_random_nomination_sequence() {
645647
distribute_rewards(Amount::new(amount, REWARD_CURRENCY));
646648
reference_pool.distribute_reward(amount);
647649
}
650+
Action::SetAcceptIssues => {
651+
let vault_id = vaults[rng.gen_range(0..vaults.len())].clone();
652+
let accept_new_issues = rng.gen_bool(0.5);
653+
assert_ok!(RuntimeCall::VaultRegistry(VaultRegistryCall::accept_new_issues {
654+
currency_pair: vault_id.currencies.clone(),
655+
accept_new_issues,
656+
})
657+
.dispatch(origin_of(vault_id.account_id.clone())));
658+
reference_pool.accept_new_issues(&vault_id, accept_new_issues);
659+
}
648660
};
649661
}
650662
for ((vault_id, nominator_id), _) in reference_pool.nominations() {

0 commit comments

Comments
 (0)