Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: update rewards payout formula #896

Merged
merged 29 commits into from
Jan 27, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cleanup math
1xstj committed Jan 20, 2025
commit 5cab5f3df27708427d574c1160b6234d74802270
4 changes: 4 additions & 0 deletions pallets/rewards/src/functions.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ use crate::{
RewardConfigForAssetVault, RewardConfigStorage, RewardVaults, TotalRewardVaultDeposit,
TotalRewardVaultScore, UserClaimedReward,
};
use log::debug;
use frame_support::{ensure, traits::Currency};
use frame_system::pallet_prelude::BlockNumberFor;
use sp_runtime::{
@@ -281,10 +282,13 @@ impl<T: Config> Pallet<T> {
// Calculate per block reward pool first to minimize precision loss
let total_reward_per_block = Self::calculate_reward_per_block(total_annual_rewards)
.ok_or(Error::<T>::ArithmeticError)?;
debug!("total reward per block: {:?}", total_reward_per_block);

// Calculate user's proportion of rewards based on their score
let user_proportion = Percent::from_rational(user_score, total_asset_score);
println!("user proportion: {:?}", user_proportion);
let user_reward_per_block = user_proportion.mul_floor(total_reward_per_block);
println!("user reward per block: {:?}", user_reward_per_block);

// Calculate total rewards for the period
let blocks_to_be_paid = current_block.saturating_sub(last_claim_block);
33 changes: 17 additions & 16 deletions pallets/rewards/src/tests/reward_calc.rs
Original file line number Diff line number Diff line change
@@ -6,19 +6,20 @@ use pallet_balances::TotalIssuance;
use sp_runtime::Percent;
use tangle_primitives::types::rewards::{LockInfo, LockMultiplier, UserDepositWithLocks};

// Helper function to setup test environment with consistent values
fn setup_test_env() {
ApyBlocks::<Runtime>::put(BLOCKS_PER_YEAR); // ~6 second blocks = ~1 year
System::set_block_number(1000); // Set current block to 1000
}

// Mock values for consistent testing
const MOCK_DEPOSIT_CAP: u128 = 1_000_000_000_000_000_000_000_000; // 1M tokens with 18 decimals
const MOCK_TOTAL_ISSUANCE: u128 = 100_000_000_000_000_000_000_000_000; // 100M tokens with 18 decimals
const MOCK_INCENTIVE_CAP: u128 = 10_000_000_000_000_000_000_000; // 10k tokens with 18 decimals
const MOCK_APY: u8 = 10; // 10% APY
const MOCK_DEPOSIT: u128 = 100_000_000_000_000_000_000_000; // 100k tokens with 18 decimals
const BLOCKS_PER_YEAR: u32 = 5_256_000; // ~6 second blocks = ~1 year
const BLOCKS_PER_YEAR: u64 = 5_256_000; // ~6 second blocks = ~1 year

// Helper function to setup test environment with consistent values
fn setup_test_env() {
ApyBlocks::<Runtime>::put(BLOCKS_PER_YEAR); // ~6 second blocks = ~1 year
System::set_block_number(1000); // Set current block to 1000
TotalIssuance::<Runtime>::set(MOCK_TOTAL_ISSUANCE);
}

#[test]
fn test_calculate_rewards_zero_deposit() {
@@ -56,11 +57,10 @@ fn test_calculate_rewards_only_unlocked() {

let total_deposit = MOCK_DEPOSIT;
let total_asset_score = MOCK_DEPOSIT;
let user_deposit = 10_000_000_000_000_000_000; // 10k tokens with 18 decimals
let user_deposit = 10_000_000_000_000_000_000_000; // 10k tokens with 18 decimals
let deposit =
UserDepositWithLocks { unlocked_amount: user_deposit, amount_with_locks: None };
let total_issuance = TotalIssuance::<Runtime>::set(MOCK_TOTAL_ISSUANCE);


let reward = RewardConfigForAssetVault {
apy: Percent::from_percent(MOCK_APY),
deposit_cap: MOCK_DEPOSIT_CAP,
@@ -100,7 +100,7 @@ fn test_calculate_rewards_with_expired_lock() {

let total_deposit = MOCK_DEPOSIT;
let total_asset_score = MOCK_DEPOSIT * 2; // Due to lock multipliers
let user_deposit = 10_000_000_000_000_000_000; // 10k tokens with 18 decimals
let user_deposit = 10_000_000_000_000_000_000_000; // 10k tokens with 18 decimals
let deposit = UserDepositWithLocks {
unlocked_amount: user_deposit,
amount_with_locks: Some(vec![LockInfo {
@@ -141,7 +141,7 @@ fn test_calculate_rewards_with_active_locks() {

let total_deposit = MOCK_DEPOSIT;
let total_asset_score = MOCK_DEPOSIT * 3; // Average multiplier effect
let user_deposit = 10_000_000_000_000_000_000; // 10k tokens with 18 decimals
let user_deposit = 10_000_000_000_000_000_000_000; // 10k tokens with 18 decimals
let deposit = UserDepositWithLocks {
unlocked_amount: user_deposit,
amount_with_locks: Some(vec![
@@ -195,7 +195,7 @@ fn test_calculate_rewards_with_previous_claim() {

let total_deposit = MOCK_DEPOSIT;
let total_asset_score = MOCK_DEPOSIT;
let user_deposit = 10_000_000_000_000_000_000; // 10k tokens with 18 decimals
let user_deposit = 10_000_000_000_000_000_000_000; // 10k tokens with 18 decimals
let deposit =
UserDepositWithLocks { unlocked_amount: user_deposit, amount_with_locks: None };
let reward = RewardConfigForAssetVault {
@@ -235,9 +235,10 @@ fn test_calculate_rewards_zero_cap() {
let total_deposit = MOCK_DEPOSIT;
let total_asset_score = MOCK_DEPOSIT;
let deposit = UserDepositWithLocks {
unlocked_amount: 10_000_000_000_000_000_000,
unlocked_amount: 10_000_000_000_000_000_000_000,
amount_with_locks: None,
};

let reward = RewardConfigForAssetVault {
apy: Percent::from_percent(MOCK_APY),
deposit_cap: 0,
@@ -255,7 +256,7 @@ fn test_calculate_rewards_zero_cap() {
last_claim,
);

assert_ok!(result, 0);
assert_err!(result, Error::<Runtime>::ArithmeticError);
});
}

@@ -266,7 +267,7 @@ fn test_calculate_rewards_same_block_claim() {

let total_deposit = MOCK_DEPOSIT;
let total_asset_score = MOCK_DEPOSIT;
let user_deposit = 10_000_000_000_000_000_000; // 10k tokens with 18 decimals
let user_deposit = 10_000_000_000_000_000_000_000; // 10k tokens with 18 decimals
let deposit =
UserDepositWithLocks { unlocked_amount: user_deposit, amount_with_locks: None };
let reward = RewardConfigForAssetVault {