Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f108616
Added on_initialize hook that yields interest for total_staking_balances
Oct 27, 2021
70821af
Merge remote-tracking branch 'origin/master' into feature/homa-lite-p…
Oct 27, 2021
3b1ecf7
made minor improvement
Oct 27, 2021
a91409e
Added an integration test for yielding interest on total_staking_curr…
Oct 27, 2021
4d19b85
Merge remote-tracking branch 'origin/master' into feature/homa-lite-p…
Oct 28, 2021
e0db399
cargo run --release --color=never --bin=acala --features=runtime-benc…
Oct 28, 2021
d797e83
cargo run --release --color=never --bin=acala --features=runtime-benc…
Oct 28, 2021
1b2ab1b
cargo run --release --color=never --bin=acala --features=runtime-benc…
Oct 28, 2021
c0ad7b2
cargo run --release --color=never --bin=acala --features=runtime-benc…
Oct 28, 2021
ed1cdc2
Added helper function to ensure event is emited when TotalStakingCurr…
Oct 29, 2021
4543d0d
Add assert to ensure the correct event is emited
Oct 29, 2021
99b1509
Fixed benchmark test
Oct 29, 2021
0c8c620
Merge remote-tracking branch 'origin/master' into feature/homa-lite-p…
Oct 29, 2021
2005356
cargo run --release --color=never --bin=acala --features=runtime-benc…
Oct 29, 2021
3c07811
cargo run --release --color=never --bin=acala --features=runtime-benc…
Oct 29, 2021
6e3ff15
Made minor improvement to address PR comments
Oct 31, 2021
e9d5154
Fixed integration test
Oct 31, 2021
70d3014
Used checked_rem instead of % for better safety
Nov 1, 2021
a310d45
Merge remote-tracking branch 'origin/master' into feature/homa-lite-p…
Nov 1, 2021
604fc16
Fixed a clippy build error
Nov 1, 2021
b9b59cd
Fixed integration tests for acala runtime
Nov 1, 2021
e43b30b
cached a variable locally to avoid duplicate storage read
Nov 1, 2021
a86cb55
Made improvement to address PR comments.
Nov 2, 2021
0e89ba4
minor improvements
Nov 2, 2021
e2c7d6a
improved how `update_total_staking_currency_storage` is implemented
Nov 2, 2021
7936c71
Update modules/homa-lite/src/lib.rs
xlc Nov 2, 2021
9d8bff3
Made on_intialize more accurate via benchmarking 2 cases separately.
Nov 2, 2021
05fd826
Merge branch 'feature/homa-lite-periodic-update' of github.com:AcalaN…
Nov 2, 2021
6a678cc
Fixed a broken unit test
Nov 2, 2021
31942cd
Merge remote-tracking branch 'origin/master' into feature/homa-lite-p…
Nov 3, 2021
d803a14
Addressed a PR comment
Nov 7, 2021
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions modules/homa-lite/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"]
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false, optional = true}
frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false }
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false }
Expand All @@ -36,6 +37,7 @@ std = [
"frame-support/std",
"frame-system/std",
"scale-info/std",
"sp-arithmetic/std",
"sp-runtime/std",
"sp-core/std",
"sp-std/std",
Expand All @@ -49,5 +51,6 @@ runtime-benchmarks = [
"frame-benchmarking",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
35 changes: 35 additions & 0 deletions modules/homa-lite/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ pub struct Module<T: Config>(crate::Pallet<T>);
const SEED: u32 = 0;

benchmarks! {
on_initialize {
let _ = crate::Pallet::<T>::set_staking_interest_rate_per_update(
RawOrigin::Root.into(),
Permill::from_percent(1)
);
let _ = crate::Pallet::<T>::set_total_staking_currency(RawOrigin::Root.into(), 1_000_000_000_000_000_000);
}: {
let _ = crate::Pallet::<T>::on_initialize(<T as frame_system::Config>::BlockNumber::default());
}

on_initialize_without_work {}: {
// interest rate is not calculated becasue `set_staking_interest_rate_per_update` is not called.
let _ = crate::Pallet::<T>::on_initialize(<T as frame_system::Config>::BlockNumber::default());
}

mint {
let amount = 1_000_000_000_000;
let caller: T::AccountId = account("caller", 0, SEED);
Expand Down Expand Up @@ -78,6 +93,7 @@ benchmarks! {

replace_schedule_unbond {}: _(RawOrigin::Root, vec![(1_000_000, <T as frame_system::Config>::BlockNumber::default()), (1_000_000_000, <T as frame_system::Config>::BlockNumber::default())])

set_staking_interest_rate_per_update {}: _(RawOrigin::Root, Permill::default())
redeem_with_available_staking_balance {
let amount = 1_000_000_000_000_000;
let caller: T::AccountId = account("caller", 0, SEED);
Expand All @@ -99,6 +115,18 @@ mod tests {
use crate::mock::*;
use frame_support::assert_ok;

#[test]
fn test_on_initialize() {
ExtBuilder::default().build().execute_with(|| {
assert_ok!(Pallet::<Runtime>::test_benchmark_on_initialize());
});
}
#[test]
fn test_on_initialize_without_work() {
ExtBuilder::default().build().execute_with(|| {
assert_ok!(Pallet::<Runtime>::test_benchmark_on_initialize_without_work());
});
}
#[test]
fn test_mint() {
ExtBuilder::default().build().execute_with(|| {
Expand Down Expand Up @@ -160,6 +188,13 @@ mod tests {
assert_ok!(Pallet::<Runtime>::test_benchmark_replace_schedule_unbond());
});
}

#[test]
fn test_set_staking_interest_rate_per_update() {
ExtBuilder::default().build().execute_with(|| {
assert_ok!(Pallet::<Runtime>::test_benchmark_set_staking_interest_rate_per_update());
});
}
#[test]
fn test_redeem_with_available_staking_balance() {
ExtBuilder::default().build().execute_with(|| {
Expand Down
108 changes: 82 additions & 26 deletions modules/homa-lite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use orml_traits::{
arithmetic::Signed, BalanceStatus, MultiCurrency, MultiCurrencyExtended, MultiReservableCurrency, XcmTransfer,
};
use primitives::{Balance, CurrencyId};
use sp_arithmetic::traits::CheckedRem;
use sp_runtime::{
traits::{BlockNumberProvider, Bounded, Saturating, Zero},
ArithmeticError, FixedPointNumber, Permill,
Expand Down Expand Up @@ -138,6 +139,10 @@ pub mod module {
/// Maximum number of scheduled unbonds allowed
#[pallet::constant]
type MaxScheduledUnbonds: Get<u32>;

/// The number of blocks to pass before TotalStakingCurrency is updated.
#[pallet::constant]
type StakingUpdateFrequency: Get<Self::BlockNumber>;
}

#[pallet::error]
Expand Down Expand Up @@ -200,6 +205,9 @@ pub mod module {
///\[staking_amount_added\]
ScheduledUnbondWithdrew(Balance),

/// Interest rate for TotalStakingCurrency is set
StakingInterestRatePerUpdateSet(Permill),

/// The amount of the staking currency available to be redeemed is set.
/// \[total_available_staking_balance\]
AvailableStakingBalanceSet(Balance),
Expand Down Expand Up @@ -243,6 +251,12 @@ pub mod module {
pub type ScheduledUnbond<T: Config> =
StorageValue<_, BoundedVec<(Balance, RelayChainBlockNumberOf<T>), T::MaxScheduledUnbonds>, ValueQuery>;

/// Every T::StakingUpdateFrequency blocks, TotalStakingCurrency gain interest by this rate.
/// StakingInterestRatePerUpdate: Value: Permill
#[pallet::storage]
#[pallet::getter(fn staking_interest_rate_per_update)]
pub type StakingInterestRatePerUpdate<T: Config> = StorageValue<_, Permill, ValueQuery>;

#[pallet::pallet]
pub struct Pallet<T>(_);

Expand Down Expand Up @@ -287,6 +301,24 @@ pub mod module {

current_weight
}

fn on_initialize(n: T::BlockNumber) -> Weight {
// Update the total amount of Staking balance by acrueing the interest periodically.
let interest_rate = Self::staking_interest_rate_per_update();
if !interest_rate.is_zero()
&& n.checked_rem(&T::StakingUpdateFrequency::get())
.map_or(false, |n| n.is_zero())
{
// Inflate the staking total by the interest rate.
// This will only fail when current TotalStakingCurrency is 0. In this case it is OK to fail.
let _ = Self::update_total_staking_currency_storage(|current| {
Ok(current.saturating_add(interest_rate.mul(current)))
});
<T as Config>::WeightInfo::on_initialize()
} else {
<T as Config>::WeightInfo::on_initialize_without_work()
}
}
}

#[pallet::call]
Expand Down Expand Up @@ -320,12 +352,7 @@ pub mod module {
#[transactional]
pub fn set_total_staking_currency(origin: OriginFor<T>, staking_total: Balance) -> DispatchResult {
T::GovernanceOrigin::ensure_origin(origin)?;
ensure!(!staking_total.is_zero(), Error::<T>::InvalidTotalStakingCurrency);

TotalStakingCurrency::<T>::put(staking_total);
Self::deposit_event(Event::<T>::TotalStakingCurrencySet(staking_total));

Ok(())
Self::update_total_staking_currency_storage(|_n| Ok(staking_total))
}

/// Adjusts the total_staking_currency by the given difference.
Expand Down Expand Up @@ -355,16 +382,13 @@ pub mod module {
);

// Adjust the current total.
TotalStakingCurrency::<T>::mutate(|current| {
if by_amount.is_positive() {
*current = current.saturating_add(by_balance);
Self::update_total_staking_currency_storage(|current_staking_total| {
Ok(if by_amount.is_positive() {
current_staking_total.saturating_add(by_balance)
} else {
*current = current.saturating_sub(by_balance);
}
Self::deposit_event(Event::<T>::TotalStakingCurrencySet(*current));
});

Ok(())
current_staking_total.saturating_sub(by_balance)
})
})
}

/// Updates the cap for how much Staking currency can be used to Mint liquid currency.
Expand Down Expand Up @@ -635,6 +659,25 @@ pub mod module {
let _ = Self::process_redeem_requests_with_available_staking_balance(max_num_matches)?;
Ok(())
}

/// Set the interest rate for TotalStakingCurrency.
/// TotakStakingCurrency is incremented every `T::StakingUpdateFrequency` blocks
///
/// Requires `T::GovernanceOrigin`
///
/// Parameters:
/// - `interest_rate`: the new interest rate for TotalStakingCurrency.
#[pallet::weight(< T as Config >::WeightInfo::set_staking_interest_rate_per_update())]
#[transactional]
pub fn set_staking_interest_rate_per_update(origin: OriginFor<T>, interest_rate: Permill) -> DispatchResult {
T::GovernanceOrigin::ensure_origin(origin)?;

StakingInterestRatePerUpdate::<T>::put(interest_rate);

Self::deposit_event(Event::<T>::StakingInterestRatePerUpdateSet(interest_rate));

Ok(())
}
}

impl<T: Config> Pallet<T> {
Expand Down Expand Up @@ -810,16 +853,17 @@ pub mod module {
liquid_to_mint = (Permill::one().saturating_sub(T::MaxRewardPerEra::get())).mul(liquid_to_mint);
liquid_to_mint = Self::convert_staking_to_liquid(liquid_to_mint)?;

// Ensure the total amount staked doesn't exceed the cap.
let new_total_staking_currency = Self::total_staking_currency()
.checked_add(staking_remaining)
.ok_or(ArithmeticError::Overflow)?;
ensure!(
new_total_staking_currency <= Self::staking_currency_mint_cap(),
Error::<T>::ExceededStakingCurrencyMintCap
);

TotalStakingCurrency::<T>::put(new_total_staking_currency);
// Update staking total and ensure the new total doesn't exceed the cap.
Self::update_total_staking_currency_storage(|total_staking_currency| {
let new_total_staking_currency = total_staking_currency
.checked_add(staking_remaining)
.ok_or(ArithmeticError::Overflow)?;
ensure!(
new_total_staking_currency <= Self::staking_currency_mint_cap(),
Error::<T>::ExceededStakingCurrencyMintCap
);
Ok(new_total_staking_currency)
})?;

// All checks pass. Proceed with Xcm transfer.
T::XcmTransfer::transfer(
Expand Down Expand Up @@ -894,7 +938,7 @@ pub mod module {
);
let actual_staking_amount = Self::convert_liquid_to_staking(actual_liquid_amount)?;

TotalStakingCurrency::<T>::mutate(|x| *x = x.saturating_sub(actual_staking_amount));
Self::update_total_staking_currency_storage(|total| Ok(total.saturating_sub(actual_staking_amount)))?;

// Redeem from the available_staking_balances costs only the xcm unbond fee.
T::Currency::deposit(
Expand Down Expand Up @@ -968,6 +1012,18 @@ pub mod module {
Self::xcm_dest_weight(),
)
}

/// Helper function that update the storage of total_staking_currency and emit event.
fn update_total_staking_currency_storage(
f: impl FnOnce(Balance) -> Result<Balance, DispatchError>,
) -> DispatchResult {
TotalStakingCurrency::<T>::try_mutate(|current| {
*current = f(*current)?;
ensure!(!current.is_zero(), Error::<T>::InvalidTotalStakingCurrency);
Self::deposit_event(Event::<T>::TotalStakingCurrencySet(*current));
Ok(())
})
}
}

impl<T: Config> ExchangeRateProvider for Pallet<T> {
Expand Down
2 changes: 2 additions & 0 deletions modules/homa-lite/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ parameter_types! {
pub const MaxScheduledUnbonds: u32 = 14;
pub const SubAccountIndex: u16 = 0;
pub ParachainId: ParaId = ParaId::from(PARACHAIN_ID);
pub const StakingUpdateFrequency: BlockNumber = 100;
}
ord_parameter_types! {
pub const Root: AccountId = ROOT;
Expand Down Expand Up @@ -306,6 +307,7 @@ impl Config for Runtime {
type MaximumRedeemRequestMatchesForMint = MaximumRedeemRequestMatchesForMint;
type RelayChainUnbondingSlashingSpans = RelayChainUnbondingSlashingSpans;
type MaxScheduledUnbonds = MaxScheduledUnbonds;
type StakingUpdateFrequency = StakingUpdateFrequency;
}

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>;
Expand Down
Loading