Skip to content

Commit 81eb087

Browse files
committed
test: more precise fee pool testing
1 parent 5f2377c commit 81eb087

File tree

4 files changed

+582
-181
lines changed

4 files changed

+582
-181
lines changed

standalone/runtime/tests/mock/redeem_testing_utils.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ pub const VAULT: [u8; 32] = BOB;
88
pub const VAULT2: [u8; 32] = CAROL;
99
pub const USER_BTC_ADDRESS: BtcAddress = BtcAddress::P2PKH(H160([2u8; 20]));
1010

11+
pub trait RedeemRequestTestExt {
12+
fn amount_without_fee_as_collateral(&self, currency_id: CurrencyId) -> Amount<Runtime>;
13+
}
14+
impl RedeemRequestTestExt for RedeemRequest<AccountId, BlockNumber, Balance, CurrencyId> {
15+
fn amount_without_fee_as_collateral(&self, currency_id: CurrencyId) -> Amount<Runtime> {
16+
let amount_without_fee = self.amount_btc() + self.transfer_fee_btc();
17+
amount_without_fee.convert_to(currency_id).unwrap()
18+
}
19+
}
20+
1121
pub struct ExecuteRedeemBuilder {
1222
redeem_id: H256,
1323
redeem: RedeemRequest<AccountId32, BlockNumber, Balance, CurrencyId>,
@@ -80,11 +90,20 @@ pub fn setup_cancelable_redeem(user: [u8; 32], vault: &VaultId, issued_tokens: A
8090

8191
// expire request without transferring btc
8292
mine_blocks((RedeemPallet::redeem_period() + 99) / 100 + 1);
83-
SecurityPallet::set_active_block_number(RedeemPallet::redeem_period() + 1 + 1);
93+
SecurityPallet::set_active_block_number(
94+
SecurityPallet::active_block_number() + RedeemPallet::redeem_period() + 1 + 1,
95+
);
8496

8597
redeem_id
8698
}
8799

100+
pub fn expire_bans() {
101+
mine_blocks((RedeemPallet::redeem_period() + 99) / 100 + 1);
102+
SecurityPallet::set_active_block_number(
103+
SecurityPallet::active_block_number() + VaultRegistryPallet::punishment_delay() + 1 + 1,
104+
);
105+
}
106+
88107
pub fn set_redeem_state(
89108
vault_to_be_redeemed: Amount<Runtime>,
90109
user_to_redeem: Amount<Runtime>,

standalone/runtime/tests/mock/reward_testing_utils.rs

Lines changed: 99 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::*;
22
use primitives::TruncateFixedPointToInt;
3-
use std::collections::BTreeMap;
3+
use std::collections::{BTreeMap, HashMap};
44

55
pub type StakeId = (VaultId, AccountId);
66

@@ -10,7 +10,7 @@ pub struct IdealRewardPool {
1010
secure_threshold: BTreeMap<VaultId, FixedU128>,
1111
accept_new_issues: BTreeMap<VaultId, bool>,
1212
commission: BTreeMap<VaultId, FixedU128>,
13-
collateral: BTreeMap<StakeId, u128>,
13+
collateral: BTreeMap<StakeId, FixedU128>,
1414
rewards: BTreeMap<AccountId, (FixedU128, FixedU128)>,
1515
}
1616

@@ -36,27 +36,33 @@ impl IdealRewardPool {
3636
pub fn deposit_nominator_collateral(&mut self, account: &StakeId, amount: u128) -> &mut Self {
3737
log::debug!("deposit_nominator_collateral {amount}");
3838
let current_collateral = self.collateral.get(account).map(|x| *x).unwrap_or_default();
39-
self.collateral.insert(account.clone(), current_collateral + amount);
39+
self.collateral
40+
.insert(account.clone(), current_collateral + FixedU128::from(amount));
4041
self
4142
}
4243

4344
pub fn withdraw_nominator_collateral(&mut self, account: &StakeId, amount: u128) -> &mut Self {
4445
log::debug!("withdraw_nominator_collateral {amount}");
4546
let current_collateral = self.collateral.get(account).map(|x| *x).unwrap_or_default();
46-
self.collateral.insert(account.clone(), current_collateral - amount);
47+
self.collateral
48+
.insert(account.clone(), current_collateral - FixedU128::from(amount));
4749
self
4850
}
4951

5052
pub fn slash_collateral(&mut self, account: &VaultId, amount: u128) -> &mut Self {
5153
log::error!("slash_collateral {amount}");
54+
let amount = FixedU128::from(amount);
5255
let nominators: Vec<_> = {
5356
self.collateral
5457
.iter()
5558
.filter(|((vault, _nominator), _stake)| vault == account)
5659
.map(|(key, value)| (key.clone(), value.clone()))
5760
.collect()
5861
};
59-
let total_stake: u128 = nominators.iter().map(|(_key, value)| *value).sum();
62+
let total_stake: FixedU128 = nominators
63+
.iter()
64+
.map(|(_key, value)| *value)
65+
.fold(Zero::zero(), |x: FixedU128, y: FixedU128| x + y);
6066
for (key, stake) in nominators {
6167
let new_stake = stake - (stake * amount) / total_stake;
6268
self.collateral.insert(key, new_stake);
@@ -77,26 +83,91 @@ impl IdealRewardPool {
7783
return self;
7884
}
7985

80-
for (stake_id, _) in self.collateral.iter() {
81-
let stake = self.stake(stake_id);
82-
let reward = (stake * reward) / total_stake;
83-
84-
let (vault_id, nominator_id) = stake_id;
85-
86-
let commission = self.commission.get(vault_id).cloned().unwrap_or_default();
87-
88-
let (vault_commission, vault_reward) = self.rewards.get(&vault_id.account_id).cloned().unwrap_or_default();
89-
self.rewards.insert(
90-
vault_id.account_id.clone(),
91-
(vault_commission + reward * commission, vault_reward),
92-
);
93-
94-
let (nominator_commission, nominator_reward) = self.rewards.get(&nominator_id).cloned().unwrap_or_default();
95-
self.rewards.insert(
96-
nominator_id.clone(),
97-
(nominator_commission, nominator_reward + (reward - reward * commission)),
98-
);
86+
let vault_stakes: HashMap<_, _> = self
87+
.collateral
88+
.iter()
89+
.map(|((vault, _nominator), collateral)| (vault, collateral))
90+
.filter(|(vault, _)| *self.accept_new_issues.get(vault).unwrap_or(&true))
91+
.into_group_map()
92+
.into_iter()
93+
.map(|(vault, nominator_collaterals)| {
94+
let vault_collateral = nominator_collaterals
95+
.into_iter()
96+
.cloned()
97+
.fold(Zero::zero(), |x: FixedU128, y: FixedU128| x + y);
98+
let threshold = self.secure_threshold[vault];
99+
let reward_stake = (vault_collateral / threshold).truncate_to_inner().unwrap();
100+
(vault, reward_stake)
101+
})
102+
.collect();
103+
104+
let capacity_stakes: Vec<_> = vault_stakes
105+
.iter()
106+
.map(|(vault, stake)| (vault.collateral_currency(), stake))
107+
.into_group_map()
108+
.into_iter()
109+
.map(|(currency, vault_stakes)| {
110+
let currency_capacity: u128 = vault_stakes.into_iter().sum();
111+
let exchange_rate = self.exchange_rate[&currency];
112+
let capacity_stake = (FixedU128::from(currency_capacity) / exchange_rate)
113+
.truncate_to_inner()
114+
.unwrap();
115+
(currency, capacity_stake)
116+
})
117+
.collect();
118+
119+
log::error!("Capacity_stakes: {capacity_stakes:?}");
120+
121+
let total_capacity: u128 = capacity_stakes.iter().map(|(_, capacity)| capacity).sum();
122+
for (currency, capacity_stake) in capacity_stakes {
123+
let currency_reward = (reward * FixedU128::from(capacity_stake)) / FixedU128::from(total_capacity);
124+
let currency_reward = currency_reward.trunc();
125+
// reward for this currency = reward * (capacity_stake / total_capacity)
126+
let vaults: Vec<_> = vault_stakes
127+
.iter()
128+
.filter(|(vault, _)| vault.collateral_currency() == currency)
129+
.collect();
130+
let total_vault_stake: u128 = vaults.iter().map(|(_, stake)| **stake).sum();
131+
for vault_stake in vaults.iter() {
132+
let nominators: Vec<_> = self
133+
.nominations()
134+
.iter()
135+
.cloned()
136+
.filter(|((vault, _nominator), _stake)| &vault == vault_stake.0)
137+
.map(|((_vault, nominator), stake)| (nominator, stake))
138+
.collect();
139+
let total_nomination = nominators
140+
.iter()
141+
.map(|(_, nomination)| *nomination)
142+
.fold(Zero::zero(), |x: FixedU128, y: FixedU128| x + y);
143+
let vault_reward =
144+
(currency_reward * FixedU128::from(*vault_stake.1)) / FixedU128::from(total_vault_stake);
145+
let vault_reward = vault_reward.trunc();
146+
log::error!("vault_reward: {}", vault_reward.truncate_to_inner().unwrap());
147+
148+
let commission = self.commission.get(vault_stake.0).cloned().unwrap_or_default();
149+
150+
let vault = vault_stake.0.clone();
151+
let (vault_commission, old_vault_reward) =
152+
self.rewards.get(&vault.account_id).cloned().unwrap_or_default();
153+
self.rewards.insert(
154+
vault.account_id.clone(),
155+
(vault_commission + vault_reward * commission, old_vault_reward),
156+
);
157+
158+
for (nominator_id, nomination) in nominators {
159+
let nominator_reward = (vault_reward - vault_reward * commission) * nomination / total_nomination;
160+
161+
let (nominator_commission, old_nominator_reward) =
162+
self.rewards.get(&nominator_id).cloned().unwrap_or_default();
163+
self.rewards.insert(
164+
nominator_id.clone(),
165+
(nominator_commission, old_nominator_reward + nominator_reward),
166+
);
167+
}
168+
}
99169
}
170+
100171
self
101172
}
102173

@@ -120,10 +191,12 @@ impl IdealRewardPool {
120191
.iter()
121192
.filter(|((vault, nominator), _stake)| nominator == account && vault.collateral_currency() == currency_id)
122193
.map(|(_key, value)| *value)
123-
.sum()
194+
.fold(Zero::zero(), |x: FixedU128, y: FixedU128| x + y)
195+
.truncate_to_inner()
196+
.unwrap()
124197
}
125198

126-
pub fn nominations(&self) -> Vec<(StakeId, u128)> {
199+
pub fn nominations(&self) -> Vec<(StakeId, FixedU128)> {
127200
self.collateral
128201
.iter()
129202
.map(|(key, value)| (key.clone(), value.clone()))

0 commit comments

Comments
 (0)