Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
polkadot-sdk
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
parity
Mirrored projects
polkadot-sdk
Commits
13cccba9
Unverified
Commit
13cccba9
authored
1 year ago
by
Liam Aharon
Browse files
Options
Downloads
Patches
Plain Diff
test reward and expiry adjustment
parent
37428699
Branches
gh-readonly-queue/master/pr-4006-1bca825cc27599dfea7b254d0ce00e3c51e632ea
Branches containing commit
No related merge requests found
Pipeline
#461432
failed with stages
in 4 minutes and 8 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
substrate/frame/asset-rewards/src/lib.rs
+41
-17
41 additions, 17 deletions
substrate/frame/asset-rewards/src/lib.rs
substrate/frame/asset-rewards/src/tests.rs
+171
-134
171 additions, 134 deletions
substrate/frame/asset-rewards/src/tests.rs
with
212 additions
and
151 deletions
substrate/frame/asset-rewards/src/lib.rs
+
41
−
17
View file @
13cccba9
...
...
@@ -80,7 +80,7 @@ pub type PoolId = u32;
pub
(
crate
)
const
PRECISION_SCALING_FACTOR
:
u32
=
u32
::
MAX
;
/// A pool staker.
#[derive(Debug,
Default,
Decode,
Encode,
MaxEncodedLen,
TypeInfo)]
#[derive(Debug,
Default,
Clone,
Decode,
Encode,
MaxEncodedLen,
TypeInfo)]
pub
struct
PoolStakerInfo
<
Balance
>
{
/// Amount of tokens staked.
amount
:
Balance
,
...
...
@@ -91,7 +91,7 @@ pub struct PoolStakerInfo<Balance> {
}
/// A staking pool.
#[derive(Debug,
Decode,
Encode,
Default,
PartialEq,
Eq,
MaxEncodedLen,
TypeInfo)]
#[derive(Debug,
Clone,
Decode,
Encode,
Default,
PartialEq,
Eq,
MaxEncodedLen,
TypeInfo)]
pub
struct
PoolInfo
<
AccountId
,
AssetId
,
Balance
,
BlockNumber
>
{
/// The asset that is staked in this pool.
staking_asset_id
:
AssetId
,
...
...
@@ -120,7 +120,10 @@ pub mod pallet {
traits
::
tokens
::{
AssetId
,
Preservation
},
};
use
frame_system
::
pallet_prelude
::
*
;
use
sp_runtime
::
traits
::{
AccountIdConversion
,
BadOrigin
,
EnsureDiv
,
Saturating
};
use
sp_runtime
::{
traits
::{
AccountIdConversion
,
BadOrigin
,
EnsureDiv
,
Saturating
},
DispatchResult
,
};
#[pallet::pallet]
pub
struct
Pallet
<
T
>
(
_
);
...
...
@@ -463,11 +466,12 @@ pub mod pallet {
new_reward_rate_per_block
:
T
::
Balance
,
)
->
DispatchResult
{
let
caller
=
ensure_signed
(
origin
)
?
;
let
mut
pool_info
=
Pools
::
<
T
>
::
get
(
pool_id
)
.ok_or
(
Error
::
<
T
>
::
NonExistentPool
)
?
;
let
pool_info
=
Pools
::
<
T
>
::
get
(
pool_id
)
.ok_or
(
Error
::
<
T
>
::
NonExistentPool
)
?
;
ensure!
(
pool_info
.admin
==
caller
,
BadOrigin
);
Self
::
update_pool_rewards
(
&
pool_id
,
None
)
?
;
let
mut
pool_info
=
Pools
::
<
T
>
::
get
(
pool_id
)
.ok_or
(
Error
::
<
T
>
::
NonExistentPool
)
?
;
pool_info
.reward_rate_per_block
=
new_reward_rate_per_block
;
Pools
::
<
T
>
::
insert
(
pool_id
,
pool_info
);
...
...
@@ -497,7 +501,7 @@ pub mod pallet {
Ok
(())
}
/// Modify a
pool admin
.
/// Modify a
expiry block
.
///
/// TODO: Actually handle this in code
pub
fn
set_pool_expiry_block
(
...
...
@@ -512,6 +516,8 @@ pub mod pallet {
Error
::
<
T
>
::
ExpiryBlockMustBeInTheFuture
);
Self
::
update_pool_rewards
(
&
pool_id
,
None
)
?
;
let
mut
pool_info
=
Pools
::
<
T
>
::
get
(
pool_id
)
.ok_or
(
Error
::
<
T
>
::
NonExistentPool
)
?
;
ensure!
(
pool_info
.admin
==
caller
,
BadOrigin
);
pool_info
.expiry_block
=
new_expiry_block
;
...
...
@@ -557,25 +563,34 @@ pub mod pallet {
}
/// Update pool reward state, and optionally also a staker's rewards.
///
/// Returns the updated pool info and optional staker info.
pub
fn
update_pool_rewards
(
pool_id
:
&
PoolId
,
staker
:
Option
<&
T
::
AccountId
>
,
)
->
DispatchResult
{
)
->
Result
<
(
PoolInfo
<
T
::
AccountId
,
T
::
AssetId
,
T
::
Balance
,
BlockNumberFor
<
T
>>
,
Option
<
PoolStakerInfo
<
T
::
Balance
>>
,
),
DispatchError
,
>
{
let
reward_per_token
=
Self
::
reward_per_token
(
pool_id
)
?
;
let
mut
pool_info
=
Pools
::
<
T
>
::
get
(
pool_id
)
.ok_or
(
Error
::
<
T
>
::
NonExistentPool
)
?
;
pool_info
.last_update_block
=
frame_system
::
Pallet
::
<
T
>
::
block_number
();
pool_info
.reward_per_token_stored
=
reward_per_token
;
Pools
::
<
T
>
::
insert
(
pool_id
,
pool_info
);
Pools
::
<
T
>
::
insert
(
pool_id
,
pool_info
.clone
()
);
if
let
Some
(
staker
)
=
staker
{
let
mut
staker_info
=
PoolStakers
::
<
T
>
::
get
(
pool_id
,
staker
)
.unwrap_or_default
();
staker_info
.rewards
=
Self
::
derive_rewards
(
pool_id
,
staker
)
?
;
staker_info
.reward_per_token_paid
=
reward_per_token
;
PoolStakers
::
<
T
>
::
insert
(
pool_id
,
staker
,
staker_info
);
PoolStakers
::
<
T
>
::
insert
(
pool_id
,
staker
,
staker_info
.clone
());
return
Ok
((
pool_info
,
Some
(
staker_info
)));
}
Ok
(())
Ok
((
pool_info
,
None
))
}
/// Derives the current reward per token for this pool.
...
...
@@ -588,18 +603,19 @@ pub mod pallet {
return
Ok
(
pool_info
.reward_per_token_stored
)
}
let
blocks_elapsed
:
u32
=
match
frame_system
::
Pallet
::
<
T
>
::
block_number
()
.saturating_sub
(
pool_info
.last_update_block
)
.try_into
()
{
Ok
(
b
)
=>
b
,
Err
(
_
)
=>
return
Err
(
Error
::
<
T
>
::
BlockNumberConversionError
.into
()),
};
let
rewardable_blocks_elapsed
:
u32
=
match
Self
::
last_block_reward_applicable
(
pool_info
.expiry_block
)
.saturating_sub
(
pool_info
.last_update_block
)
.try_into
()
{
Ok
(
b
)
=>
b
,
Err
(
_
)
=>
return
Err
(
Error
::
<
T
>
::
BlockNumberConversionError
.into
()),
};
Ok
(
pool_info
.reward_per_token_stored
.saturating_add
(
pool_info
.reward_rate_per_block
.saturating_mul
(
blocks_elapsed
.into
())
.saturating_mul
(
rewardable_
blocks_elapsed
.into
())
.saturating_mul
(
PRECISION_SCALING_FACTOR
.into
())
.ensure_div
(
pool_info
.total_tokens_staked
)
?
,
))
...
...
@@ -621,5 +637,13 @@ pub mod pallet {
.ensure_div
(
PRECISION_SCALING_FACTOR
.into
())
?
.saturating_add
(
staker_info
.rewards
))
}
fn
last_block_reward_applicable
(
pool_expiry_block
:
BlockNumberFor
<
T
>
)
->
BlockNumberFor
<
T
>
{
if
frame_system
::
Pallet
::
<
T
>
::
block_number
()
<
pool_expiry_block
{
frame_system
::
Pallet
::
<
T
>
::
block_number
()
}
else
{
pool_expiry_block
}
}
}
}
This diff is collapsed.
Click to expand it.
substrate/frame/asset-rewards/src/tests.rs
+
171
−
134
View file @
13cccba9
...
...
@@ -573,139 +573,176 @@ mod set_pool_expiry_block {
}
}
mod
integration
{
use
super
::
*
;
/// Assert that an amount has been hypothetically earned by a staker.
fn
assert_hypothetically_earned
(
staker
:
u128
,
expected_earned
:
u128
,
pool_id
:
u32
,
reward_asset_id
:
NativeOrWithId
<
u32
>
,
)
{
hypothetically!
({
// Get the pre-harvest balance.
let
balance_before
:
<
MockRuntime
as
Config
>
::
Balance
=
<<
MockRuntime
as
Config
>
::
Assets
>
::
balance
(
reward_asset_id
.clone
(),
&
staker
);
// Harvest the rewards.
assert_ok!
(
StakingRewards
::
harvest_rewards
(
RuntimeOrigin
::
signed
(
staker
),
pool_id
,
None
));
// Sanity check: staker rewards are reset to 0.
assert_eq!
(
PoolStakers
::
<
MockRuntime
>
::
get
(
pool_id
,
staker
)
.unwrap
()
.rewards
,
0
);
// Check that the staker has earned the expected amount.
let
balance_after
=
<<
MockRuntime
as
Config
>
::
Assets
>
::
balance
(
reward_asset_id
.clone
(),
&
staker
);
assert_eq!
(
balance_after
-
balance_before
,
<
u128
as
Into
<<
MockRuntime
as
Config
>
::
Balance
>>
::
into
(
expected_earned
)
);
});
}
#[test]
/// In this integration test scenario, we will consider 2 stakers each staking and unstaking at
/// different intervals, and assert their claimable rewards are as expected.
///
/// Note: There are occasionally off by 1 errors due to rounding. In practice, this is
/// insignificant.
fn
two_stakers
()
{
new_test_ext
()
.execute_with
(||
{
// Setup
let
admin
=
1
;
let
staker1
=
10u128
;
let
staker2
=
20
;
let
staking_asset_id
=
NativeOrWithId
::
<
u32
>
::
WithId
(
1
);
let
reward_asset_id
=
NativeOrWithId
::
<
u32
>
::
Native
;
let
reward_rate_per_block
=
100
;
let
expiry_block
=
25u64
.into
();
create_tokens
(
admin
,
vec!
[
staking_asset_id
.clone
()]);
assert_ok!
(
StakingRewards
::
create_pool
(
RuntimeOrigin
::
signed
(
admin
),
Box
::
new
(
staking_asset_id
.clone
()),
Box
::
new
(
reward_asset_id
.clone
()),
reward_rate_per_block
,
expiry_block
,
None
));
let
pool_id
=
0
;
let
pool_account_id
=
StakingRewards
::
pool_account_id
(
&
pool_id
)
.unwrap
();
<<
MockRuntime
as
Config
>
::
Assets
>
::
set_balance
(
reward_asset_id
.clone
(),
&
pool_account_id
,
100_000
,
);
<<
MockRuntime
as
Config
>
::
Assets
>
::
set_balance
(
staking_asset_id
.clone
(),
&
staker1
,
100_000
,
);
<<
MockRuntime
as
Config
>
::
Assets
>
::
set_balance
(
staking_asset_id
.clone
(),
&
staker2
,
100_000
,
);
/// Assert that an amount has been hypothetically earned by a staker.
fn
assert_hypothetically_earned
(
staker
:
u128
,
expected_earned
:
u128
,
pool_id
:
u32
,
reward_asset_id
:
NativeOrWithId
<
u32
>
,
)
{
hypothetically!
({
// Get the pre-harvest balance.
let
balance_before
:
<
MockRuntime
as
Config
>
::
Balance
=
<<
MockRuntime
as
Config
>
::
Assets
>
::
balance
(
reward_asset_id
.clone
(),
&
staker
);
// Harvest the rewards.
assert_ok!
(
StakingRewards
::
harvest_rewards
(
RuntimeOrigin
::
signed
(
staker
),
pool_id
,
None
));
// Sanity check: staker rewards are reset to 0.
assert_eq!
(
PoolStakers
::
<
MockRuntime
>
::
get
(
pool_id
,
staker
)
.unwrap
()
.rewards
,
0
);
// Check that the staker has earned the expected amount.
let
balance_after
=
<<
MockRuntime
as
Config
>
::
Assets
>
::
balance
(
reward_asset_id
.clone
(),
&
staker
);
assert_eq!
(
balance_after
-
balance_before
,
<
u128
as
Into
<<
MockRuntime
as
Config
>
::
Balance
>>
::
into
(
expected_earned
)
);
});
}
// Block 7: Staker 1 stakes 100 tokens.
System
::
set_block_number
(
7
);
assert_ok!
(
StakingRewards
::
stake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// At this point
// - Staker 1 has earned 0 tokens.
// - Staker 1 is earning 100 tokens per block.
// Check that Staker 1 has earned 0 tokens.
assert_hypothetically_earned
(
staker1
,
0
,
pool_id
,
reward_asset_id
.clone
());
// Block 9: Staker 2 stakes 100 tokens.
System
::
set_block_number
(
9
);
assert_ok!
(
StakingRewards
::
stake
(
RuntimeOrigin
::
signed
(
staker2
),
pool_id
,
100
));
// At this point
// - Staker 1 has earned 200 (100*2) tokens.
// - Staker 2 has earned 0 tokens.
// - Staker 1 is earning 50 tokens per block.
// - Staker 2 is earning 50 tokens per block.
// Check that Staker 1 has earned 200 tokens and Staker 2 has earned 0 tokens.
assert_hypothetically_earned
(
staker1
,
200
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
0
,
pool_id
,
reward_asset_id
.clone
());
// Block 12: Staker 1 stakes an additional 100 tokens.
System
::
set_block_number
(
12
);
assert_ok!
(
StakingRewards
::
stake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// At this point
// - Staker 1 has earned 350 (200 + (50 * 3)) tokens.
// - Staker 2 has earned 150 (50 * 3) tokens.
// - Staker 1 is earning 66.66 tokens per block.
// - Staker 2 is earning 33.33 tokens per block.
// Check that Staker 1 has earned 350 tokens and Staker 2 has earned 150 tokens.
assert_hypothetically_earned
(
staker1
,
349
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
149
,
pool_id
,
reward_asset_id
.clone
());
// Block 22: Staker 1 unstakes 100 tokens.
System
::
set_block_number
(
22
);
assert_ok!
(
StakingRewards
::
unstake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// - Staker 1 has earned 1016 (350 + 66.66 * 10) tokens.
// - Staker 2 has earned 483 (150 + 33.33 * 10) tokens.
// - Staker 1 is earning 50 tokens per block.
// - Staker 2 is earning 50 tokens per block.
assert_hypothetically_earned
(
staker1
,
1015
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
483
,
pool_id
,
reward_asset_id
.clone
());
// Block 23: Staker 1 unstakes 100 tokens.
System
::
set_block_number
(
23
);
assert_ok!
(
StakingRewards
::
unstake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// - Staker 1 has earned 1065 (1015 + 50) tokens.
// - Staker 2 has earned 533 (483 + 50) tokens.
// - Staker 1 is earning 0 tokens per block.
// - Staker 2 is earning 100 tokens per block.
assert_hypothetically_earned
(
staker1
,
1064
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
533
,
pool_id
,
reward_asset_id
.clone
());
});
}
/// In this integration test scenario, we
/// 1. Consider 2 stakers each staking and unstaking at different intervals, and assert their
/// claimable rewards are as expected.
/// 2. Check that rewards are correctly halted after the pool's expiry block, and resume when the
/// pool is extended.
/// 3. Check that reward rates adjustment works correctly.
///
/// Note: There are occasionally off by 1 errors due to rounding. In practice this is
/// insignificant.
#[test]
fn
two_stakers_integration_test
()
{
new_test_ext
()
.execute_with
(||
{
// Setup
let
admin
=
1
;
let
staker1
=
10u128
;
let
staker2
=
20
;
let
staking_asset_id
=
NativeOrWithId
::
<
u32
>
::
WithId
(
1
);
let
reward_asset_id
=
NativeOrWithId
::
<
u32
>
::
Native
;
let
reward_rate_per_block
=
100
;
let
expiry_block
=
25u64
.into
();
create_tokens
(
admin
,
vec!
[
staking_asset_id
.clone
()]);
assert_ok!
(
StakingRewards
::
create_pool
(
RuntimeOrigin
::
signed
(
admin
),
Box
::
new
(
staking_asset_id
.clone
()),
Box
::
new
(
reward_asset_id
.clone
()),
reward_rate_per_block
,
expiry_block
,
None
));
let
pool_id
=
0
;
let
pool_account_id
=
StakingRewards
::
pool_account_id
(
&
pool_id
)
.unwrap
();
<<
MockRuntime
as
Config
>
::
Assets
>
::
set_balance
(
reward_asset_id
.clone
(),
&
pool_account_id
,
100_000
,
);
<<
MockRuntime
as
Config
>
::
Assets
>
::
set_balance
(
staking_asset_id
.clone
(),
&
staker1
,
100_000
);
<<
MockRuntime
as
Config
>
::
Assets
>
::
set_balance
(
staking_asset_id
.clone
(),
&
staker2
,
100_000
);
// Block 7: Staker 1 stakes 100 tokens.
System
::
set_block_number
(
7
);
assert_ok!
(
StakingRewards
::
stake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// At this point
// - Staker 1 has earned 0 tokens.
// - Staker 1 is earning 100 tokens per block.
// Check that Staker 1 has earned 0 tokens.
assert_hypothetically_earned
(
staker1
,
0
,
pool_id
,
reward_asset_id
.clone
());
// Block 9: Staker 2 stakes 100 tokens.
System
::
set_block_number
(
9
);
assert_ok!
(
StakingRewards
::
stake
(
RuntimeOrigin
::
signed
(
staker2
),
pool_id
,
100
));
// At this point
// - Staker 1 has earned 200 (100*2) tokens.
// - Staker 2 has earned 0 tokens.
// - Staker 1 is earning 50 tokens per block.
// - Staker 2 is earning 50 tokens per block.
// Check that Staker 1 has earned 200 tokens and Staker 2 has earned 0 tokens.
assert_hypothetically_earned
(
staker1
,
200
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
0
,
pool_id
,
reward_asset_id
.clone
());
// Block 12: Staker 1 stakes an additional 100 tokens.
System
::
set_block_number
(
12
);
assert_ok!
(
StakingRewards
::
stake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// At this point
// - Staker 1 has earned 350 (200 + (50 * 3)) tokens.
// - Staker 2 has earned 150 (50 * 3) tokens.
// - Staker 1 is earning 66.66 tokens per block.
// - Staker 2 is earning 33.33 tokens per block.
// Check that Staker 1 has earned 350 tokens and Staker 2 has earned 150 tokens.
assert_hypothetically_earned
(
staker1
,
349
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
149
,
pool_id
,
reward_asset_id
.clone
());
// Block 22: Staker 1 unstakes 100 tokens.
System
::
set_block_number
(
22
);
assert_ok!
(
StakingRewards
::
unstake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// - Staker 1 has earned 1016 (350 + 66.66 * 10) tokens.
// - Staker 2 has earned 483 (150 + 33.33 * 10) tokens.
// - Staker 1 is earning 50 tokens per block.
// - Staker 2 is earning 50 tokens per block.
assert_hypothetically_earned
(
staker1
,
1015
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
483
,
pool_id
,
reward_asset_id
.clone
());
// Block 23: Staker 1 unstakes 100 tokens.
System
::
set_block_number
(
23
);
assert_ok!
(
StakingRewards
::
unstake
(
RuntimeOrigin
::
signed
(
staker1
),
pool_id
,
100
));
// - Staker 1 has earned 1065 (1015 + 50) tokens.
// - Staker 2 has earned 533 (483 + 50) tokens.
// - Staker 1 is earning 0 tokens per block.
// - Staker 2 is earning 100 tokens per block.
assert_hypothetically_earned
(
staker1
,
1064
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
533
,
pool_id
,
reward_asset_id
.clone
());
// Block 50: Stakers should only have earned 2 blocks worth of tokens (expiry is 25).
System
::
set_block_number
(
50
);
// - Staker 1 has earned 1065 tokens.
// - Staker 2 has earned 733 (533 + 2 * 100) tokens.
// - Staker 1 is earning 0 tokens per block.
// - Staker 2 is earning 0 tokens per block.
assert_hypothetically_earned
(
staker1
,
1064
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
733
,
pool_id
,
reward_asset_id
.clone
());
// Block 51: Extend the pool expiry block to 60.
System
::
set_block_number
(
51
);
// - Staker 1 is earning 0 tokens per block.
// - Staker 2 is earning 100 tokens per block.
assert_ok!
(
StakingRewards
::
set_pool_expiry_block
(
RuntimeOrigin
::
signed
(
admin
),
pool_id
,
60u64
));
assert_hypothetically_earned
(
staker1
,
1064
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
733
,
pool_id
,
reward_asset_id
.clone
());
// Block 53: Check rewards are resumed.
// - Staker 1 has earned 1065 tokens.
// - Staker 2 has earned 933 (733 + 2 * 100) tokens.
// - Staker 2 is earning 100 tokens per block.
System
::
set_block_number
(
53
);
assert_hypothetically_earned
(
staker1
,
1064
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
933
,
pool_id
,
reward_asset_id
.clone
());
// Block 55: Halve the block reward.
// - Staker 1 has earned 1065 tokens.
// - Staker 2 has earned 1133 (933 + 2 * 100) tokens.
// - Staker 2 is earning 50 tokens per block.
System
::
set_block_number
(
55
);
assert_ok!
(
StakingRewards
::
set_pool_reward_rate_per_block
(
RuntimeOrigin
::
signed
(
admin
),
pool_id
,
50
));
assert_hypothetically_earned
(
staker1
,
1064
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
1133
,
pool_id
,
reward_asset_id
.clone
());
// Block 60: Check rewards were adjusted correctly.
// - Staker 1 has earned 1065 tokens.
// - Staker 2 has earned 1383 (1133 + 5 * 50) tokens.
System
::
set_block_number
(
60
);
assert_hypothetically_earned
(
staker1
,
1064
,
pool_id
,
reward_asset_id
.clone
());
assert_hypothetically_earned
(
staker2
,
1383
,
pool_id
,
reward_asset_id
.clone
());
});
}
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment