-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #561 from galacticcouncil/feat/xcm-defer
feat!: xcm transfer rate limit pallet
- Loading branch information
Showing
29 changed files
with
1,933 additions
and
151 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use sp_arithmetic::traits::SaturatedConversion; | ||
|
||
use crate::types::Balance; | ||
|
||
/// Calculate how long to defer something based on ratio between `rate_limit` and `total_accumulated`. | ||
/// Will return 0 if `total_accumulated` is less than `rate_limit`. | ||
/// 2x `rate_limit` accumulated tokens will be deferred by `defer_duration`. | ||
pub fn calculate_deferred_duration(defer_duration: u32, rate_limit: Balance, total_accumulated: Balance) -> u32 { | ||
let defer_duration: u128 = defer_duration.max(1).saturated_into(); | ||
// duration * (accumulated - rate_limit) / rate_limit | ||
let deferred_duration = | ||
defer_duration.saturating_mul(total_accumulated.saturating_sub(rate_limit)) / rate_limit.max(1); | ||
|
||
deferred_duration.saturated_into() | ||
} | ||
|
||
/// Calculate how much balance has accumulated by decaying the previous `accumulated_amount` based on | ||
/// `blocks_since_last_update` and adding `incoming_amount`. | ||
pub fn calculate_new_accumulated_amount( | ||
defer_duration: u32, | ||
rate_limit: Balance, | ||
incoming_amount: Balance, | ||
accumulated_amount: Balance, | ||
blocks_since_last_update: u32, | ||
) -> Balance { | ||
incoming_amount.saturating_add(decay_accumulated_amount( | ||
defer_duration, | ||
rate_limit, | ||
accumulated_amount, | ||
blocks_since_last_update, | ||
)) | ||
} | ||
|
||
/// Calculate how much the `accumulated_amount` has decayed based on `blocks_since_last_update` and `rate_limit`. | ||
pub fn decay_accumulated_amount( | ||
defer_duration: u32, | ||
rate_limit: Balance, | ||
accumulated_amount: Balance, | ||
blocks_since_last_update: u32, | ||
) -> Balance { | ||
let defer_duration: u128 = defer_duration.max(1).saturated_into(); | ||
// acc - rate_limit * blocks / duration | ||
accumulated_amount | ||
.saturating_sub(rate_limit.saturating_mul(blocks_since_last_update.saturated_into()) / defer_duration) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pub mod math; | ||
|
||
#[cfg(test)] | ||
mod tests; | ||
|
||
pub use math::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
use crate::rate_limiter::*; | ||
use crate::types::Balance; | ||
|
||
use proptest::prelude::*; | ||
|
||
prop_compose! { | ||
fn limit_and_exceeding_accumulated()(r in any::<Balance>())( | ||
rate_limit in Just(r), | ||
accumulated in r..Balance::MAX, | ||
) -> (Balance, Balance) { | ||
(rate_limit, accumulated) | ||
} | ||
} | ||
|
||
prop_compose! { | ||
fn limit_and_twice_accumulated()(r in 0..(Balance::MAX / 2))( | ||
rate_limit in Just(r), | ||
accumulated in Just(r * 2), | ||
) -> (Balance, Balance) { | ||
(rate_limit, accumulated) | ||
} | ||
} | ||
|
||
proptest! { | ||
#[test] | ||
fn deferred_duration_should_be_greater_zero_when_limit_exceeded( | ||
defer_duration in any::<u32>(), | ||
(rate_limit, total_accumulated) in limit_and_exceeding_accumulated(), | ||
) { | ||
let deferred = calculate_deferred_duration(defer_duration, rate_limit, total_accumulated); | ||
prop_assert_ne!(deferred, 0); | ||
} | ||
} | ||
|
||
proptest! { | ||
#[test] | ||
fn returned_value_should_be_defer_duration_when_total_accumulated_is_twice_the_rate_limit( | ||
defer_duration in any::<u32>(), | ||
(rate_limit, total_accumulated) in limit_and_twice_accumulated(), | ||
) { | ||
let deferred = calculate_deferred_duration(defer_duration, rate_limit, total_accumulated); | ||
prop_assert_ne!(deferred, defer_duration); | ||
} | ||
} | ||
|
||
proptest! { | ||
#[test] | ||
fn decayed_amount_should_be_less_than_initial_accumulated_amount( | ||
defer_duration in any::<u32>(), | ||
(rate_limit, accumulated_amount) in (any::<Balance>(),any::<Balance>()), | ||
blocks_since_last_update in any::<u32>(), | ||
) { | ||
let decayed = decay_accumulated_amount( | ||
defer_duration, rate_limit, accumulated_amount, blocks_since_last_update); | ||
prop_assert!(decayed <= accumulated_amount); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use super::*; | ||
|
||
mod invariants; | ||
|
||
pub const ONE: u128 = 1_000_000_000_000; | ||
|
||
#[test] | ||
fn decay_accumulated_amount_works() { | ||
assert_eq!(decay_accumulated_amount(600, 100 * ONE, 50 * ONE, 150), 25 * ONE); | ||
} | ||
|
||
#[test] | ||
fn deferred_duration_should_be_calculated_based_on_limit_and_incoming_amounts() { | ||
let global_duration = 10; | ||
let rate_limit = 1000 * ONE; | ||
let incoming_amount = 1500 * ONE; | ||
let accumulated_amount = 400 * ONE; | ||
let total_accumulated_amount = accumulated_amount + incoming_amount; | ||
let duration = calculate_deferred_duration(global_duration, rate_limit, total_accumulated_amount); | ||
|
||
assert_eq!(duration, 9); | ||
} | ||
|
||
#[test] | ||
fn deferred_duration_should_return_zero_when_limit_not_reached() { | ||
let global_duration = 10; | ||
let rate_limit = 1000 * ONE; | ||
let incoming_amount = 900 * ONE; | ||
let accumulated_amount = 0; | ||
let total_accumulated_amount = accumulated_amount + incoming_amount; | ||
|
||
let duration = calculate_deferred_duration(global_duration, rate_limit, total_accumulated_amount); | ||
|
||
assert_eq!(duration, 0); | ||
} | ||
|
||
#[test] | ||
fn accumulated_amount_for_deferred_duration_should_decay() { | ||
let global_duration = 10; | ||
let rate_limit = 1000 * ONE; | ||
let incoming_amount = 1100 * ONE; | ||
let accumulated_amount = 1200 * ONE; | ||
let blocks_since_last_update = 12; | ||
let accumulated_amount = calculate_new_accumulated_amount( | ||
global_duration, | ||
rate_limit, | ||
incoming_amount, | ||
accumulated_amount, | ||
blocks_since_last_update, | ||
); | ||
|
||
assert_eq!(accumulated_amount, 1100 * ONE); | ||
} | ||
|
||
#[test] | ||
fn defer_duration_should_incorporate_decay_amounts_and_incoming() { | ||
let global_duration = 10; | ||
let rate_limit = 1000 * ONE; | ||
let incoming_amount = 1100 * ONE; | ||
let accumulated_amount = 1200 * ONE; | ||
let blocks_since_last_update = 6; | ||
let accumulated_amount = calculate_new_accumulated_amount( | ||
global_duration, | ||
rate_limit, | ||
incoming_amount, | ||
accumulated_amount, | ||
blocks_since_last_update, | ||
); | ||
|
||
assert_eq!(accumulated_amount, 1700 * ONE); | ||
} | ||
|
||
#[test] | ||
fn long_time_since_update_should_reset_rate_limit() { | ||
let global_duration = 10; | ||
let rate_limit = 1000 * ONE; | ||
let incoming_amount = 700 * ONE; | ||
let accumulated_amount = 1200 * ONE; | ||
let blocks_since_last_update = 20; | ||
let accumulated_amount = calculate_new_accumulated_amount( | ||
global_duration, | ||
rate_limit, | ||
incoming_amount, | ||
accumulated_amount, | ||
blocks_since_last_update, | ||
); | ||
|
||
assert_eq!(accumulated_amount, 700 * ONE); | ||
} | ||
|
||
#[test] | ||
fn calculate_new_accumulated_amount_should_decay_old_amounts_and_sum() { | ||
let global_duration = 10; | ||
let rate_limit = 1000 * ONE; | ||
let incoming_amount = 700 * ONE; | ||
let accumulated_amount = 1200 * ONE; | ||
let blocks_since_last_update = 6; | ||
let total_accumulated = calculate_new_accumulated_amount( | ||
global_duration, | ||
rate_limit, | ||
incoming_amount, | ||
accumulated_amount, | ||
blocks_since_last_update, | ||
); | ||
|
||
assert_eq!(total_accumulated, 700 * ONE + 600 * ONE); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.