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

Complete merging Cashdrop into SerpTreasury #454

Merged
merged 1 commit into from
Aug 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
137 changes: 88 additions & 49 deletions lib-serml/serp/serp-treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@
#![allow(clippy::unused_unit)]

// use fixed::{types::extra::U128, FixedU128};
use frame_support::{pallet_prelude::*, transactional, PalletId};
use frame_support::{pallet_prelude::*, PalletId};
use frame_system::pallet_prelude::*;
use orml_traits::{GetByKey, MultiCurrency, MultiCurrencyExtended};
use primitives::{Balance, CurrencyId};
use sp_core::U256;
use sp_runtime::{
traits::{AccountIdConversion, Zero},
DispatchError, DispatchResult
DispatchError, DispatchResult,
};
use sp_std::prelude::*;
use support::{
Expand Down Expand Up @@ -87,14 +86,23 @@ pub mod module {
/// (Blocktime/BlockNumber - every blabla block)
type SerpTesSchedule: Get<Self::BlockNumber>;

#[pallet::constant]
// CashDrop period for transferring cashdrop from
// the `SettPayTreasuryAccountId`.
// The ideal period is after every `24 hours`.
type CashDropPeriod: Get<Self::BlockNumber>;

/// SerpUp pool/account for receiving funds SettPay Cashdrops
/// SettPayTreasury account.
type SettPayTreasuryAcc: Get<PalletId>;
#[pallet::constant]
type SettPayTreasuryAccountId: Get<Self::AccountId>;

/// The vault account to keep the accumulated Cashdrop doses from the `SettPayTreasuryAccountId`.
#[pallet::constant]
type CashDropVaultAccountId: Get<Self::AccountId>;

/// SerpUp pool/account for receiving funds Setheum Foundation's Charity Fund
/// CharityFund account.
type CharityFundAcc: Get<Self::AccountId>;
type CharityFundAccountId: Get<Self::AccountId>;

/// Dex manager is used to swap reserve asset (Setter) for propper (SettCurrency).
type Dex: DEXManager<Self::AccountId, CurrencyId, Balance>;
Expand All @@ -112,15 +120,7 @@ pub mod module {
type NonStableDropCurrencyIds: Get<Vec<CurrencyId>>;

/// The cashdrop currency ids that receive SettCurrencies.
type SetCurrencyDropCurrencyIds: Get<Vec<CurrencyId>>;

/// The default cashdrop rate to be issued to claims.
///
/// The first item of the tuple is the numerator of the cashdrop rate, second
/// item is the denominator, cashdrop_rate = numerator / denominator,
/// use (u32, u32) over `Rate` type to minimize internal division
/// operation.
type GetCashDropRate: Get<(u32, u32)>;
type SettCurrencyDropCurrencyIds: Get<Vec<CurrencyId>>;

/// The minimum transfer amounts by currency_id, to secure cashdrop from dusty claims.
type MinimumClaimableTransferAmounts: GetByKey<CurrencyId, Balance>;
Expand Down Expand Up @@ -171,8 +171,10 @@ pub mod module {
SerpUp(Balance, CurrencyId),
/// Currency SerpDown has been triggered successfully.
SerpDown(Balance, CurrencyId),
/// CashDrop has been completed successfully.
CashDrops(CurrencyId, T::AccountId, Balance),
/// CashDrop has been claimed successfully.
CashDropClaim(CurrencyId, T::AccountId, Balance),
/// CashDrop has been deposited to vault successfully.
CashDropToVault(Balance, CurrencyId),
}

/// Mapping to Minimum Claimable Transfer.
Expand All @@ -194,9 +196,6 @@ pub mod module {
// TODO: Migrate `BlockNumber` to `Timestamp`
/// Triggers Serping for all system stablecoins at every block.
fn on_initialize(now: T::BlockNumber) -> Weight {
// TODO: Update for a global-adjustment-frequency to have it's own governed custom adjustment-frequency,
// TODO: - and call serp_tes at a timestamp e.g. every 10 minutes
//
// SERP-TES Adjustment Frequency.
// Schedule for when to trigger SERP-TES
// (Blocktime/BlockNumber - every blabla block)
Expand All @@ -211,6 +210,22 @@ pub mod module {
count += 1;
}

T::WeightInfo::on_initialize(count)
} else if now % T::CashDropPeriod::get() == Zero::zero() {
// CashDrop period for transferring cashdrop from
// the `SettPayTreasuryAccountId`.
// The ideal period is after every `24 hours`.
//
// SERP TES (Token Elasticity of Supply).
// Triggers Serping for all system stablecoins to stabilize stablecoin prices.
let mut count: u32 = 0;
if Self::setter_cashdrop_to_vault().is_ok() {
count += 1;
};
if Self::usdj_cashdrop_to_vault().is_ok() {
count += 1;
};

T::WeightInfo::on_initialize(count)
} else {
0
Expand Down Expand Up @@ -250,9 +265,21 @@ impl<T: Config> SerpTreasury<T::AccountId> for Pallet<T> {
Ok(())
}

/// SerpUp ratio for Setheum Foundation's Charity Fund
fn get_charity_fund_serpup(amount: Balance, currency_id: Self::CurrencyId) -> DispatchResult {
let charity_fund_account = T::CharityFundAccountId::get();
// Charity Fund SerpUp Pool - 10%
let serping_amount: Balance = amount / 10;
// Issue the SerpUp propper to the SettPayVault
Self::issue_standard(currency_id, &charity_fund_account, serping_amount)?;

<Pallet<T>>::deposit_event(Event::SerpUpDelivery(amount, currency_id));
Ok(())
}

/// SerpUp ratio for SettPay Cashdrops
fn get_settpay_serpup(amount: Balance, currency_id: Self::CurrencyId) -> DispatchResult {
let settpay_account = T::SettPayTreasuryAcc::get().into_account();
fn get_cashdrop_serpup(amount: Balance, currency_id: Self::CurrencyId) -> DispatchResult {
let settpay_account = &T::SettPayTreasuryAccountId::get();

// SettPay SerpUp Pool - 60%
let six: Balance = 6;
Expand All @@ -264,15 +291,33 @@ impl<T: Config> SerpTreasury<T::AccountId> for Pallet<T> {
Ok(())
}

/// SerpUp ratio for Setheum Foundation's Charity Fund
fn get_charity_fund_serpup(amount: Balance, currency_id: Self::CurrencyId) -> DispatchResult {
let charity_fund_account = T::CharityFundAcc::get();
// Charity Fund SerpUp Pool - 10%
let serping_amount: Balance = amount / 10;
// Issue the SerpUp propper to the SettPayVault
Self::issue_standard(currency_id, &charity_fund_account, serping_amount)?;
/// Reward SETT cashdrop to vault
fn setter_cashdrop_to_vault() -> DispatchResult {
let free_balance = T::Currency::free_balance(T::SetterCurrencyId::get(), &T::SettPayTreasuryAccountId::get());

<Pallet<T>>::deposit_event(Event::SerpUpDelivery(amount, currency_id));
// Send 50% of funds to the CashDropVault
let five: Balance = 5;
let cashdrop_amount: Balance = five.saturating_mul(free_balance / 10);

// Transfer the CashDrop propper Rewards to the CashDropVault
T::Currency::transfer(T::SetterCurrencyId::get(), &T::SettPayTreasuryAccountId::get(), &T::CashDropVaultAccountId::get(), cashdrop_amount)?;

<Pallet<T>>::deposit_event(Event::CashDropToVault(cashdrop_amount, T::SetterCurrencyId::get()));
Ok(())
}

/// SerpUp ratio for SettPay Cashdrops
fn usdj_cashdrop_to_vault() -> DispatchResult {
let free_balance = T::Currency::free_balance(T::GetSettUSDCurrencyId::get(), &T::SettPayTreasuryAccountId::get());

// Send 50% of funds to the CashDropVault
let five: Balance = 5;
let cashdrop_amount: Balance = five.saturating_mul(free_balance / 10);

// Transfer the CashDrop propper Rewards to the CashDropVault
T::Currency::transfer(T::GetSettUSDCurrencyId::get(), &T::SettPayTreasuryAccountId::get(), &T::CashDropVaultAccountId::get(), cashdrop_amount)?;

<Pallet<T>>::deposit_event(Event::CashDropToVault(cashdrop_amount, T::GetSettUSDCurrencyId::get()));
Ok(())
}

Expand Down Expand Up @@ -341,7 +386,7 @@ impl<T: Config> SerpTreasury<T::AccountId> for Pallet<T> {
Error::<T>::InvalidAmount,
);
Self::get_buyback_serpup(amount, currency_id)?;
Self::get_settpay_serpup(amount, currency_id)?;
Self::get_cashdrop_serpup(amount, currency_id)?;
Self::get_charity_fund_serpup(amount, currency_id)?;

<Pallet<T>>::deposit_event(Event::SerpUp(amount, currency_id));
Expand Down Expand Up @@ -423,25 +468,20 @@ impl<T: Config> SerpTreasury<T::AccountId> for Pallet<T> {
transfer_amount >= minimum_claimable_transfer,
Error::<T>::TransferTooLowForCashDrop,
);
let setter_fixed_price = <T as Config>::PriceSource::get_setter_price();
let (cashdrop_numerator, cashdrop_denominator) = T::GetCashDropRate::get();

if currency_id == T::SetterCurrencyId::get() {
let transfer_drop = transfer_amount.saturating_mul(cashdrop_denominator.saturating_sub(cashdrop_numerator).unique_saturated_into());
let into_cashdrop_amount: U256 = U256::from(transfer_amount).saturating_sub(U256::from(transfer_drop));
let balance_cashdrop_amount = into_cashdrop_amount.and_then(|n| TryInto::<Balance>::try_into(n).ok()).unwrap_or_else(Zero::zero);
let balance_cashdrop_amount = transfer_amount / 50; // 2%
let serp_balance = T::Currency::free_balance(currency_id, &Self::account_id());
ensure!(
balance_cashdrop_amount <= serp_balance,
Error::<T>::CashdropNotAvailable,
);

T::Currency::transfer(T::SetterCurrencyId::get(), &Self::account_id(), who, balance_cashdrop_amount);
Self::deposit_event(Event::CashDrops(T::SetterCurrencyId::get(), who.clone(), balance_cashdrop_amount.clone()));
T::Currency::transfer(T::SetterCurrencyId::get(), &Self::account_id(), who, balance_cashdrop_amount)?;
Self::deposit_event(Event::CashDropClaim(T::SetterCurrencyId::get(), who.clone(), balance_cashdrop_amount.clone()));
} else if T::NonStableDropCurrencyIds::get().contains(&currency_id) {
let transfer_drop = transfer_amount.saturating_mul(cashdrop_denominator.saturating_sub(cashdrop_numerator).unique_saturated_into());
let into_cashdrop_amount: U256 = U256::from(transfer_amount).saturating_sub(U256::from(transfer_drop));
let balance_cashdrop_amount = into_cashdrop_amount.and_then(|n| TryInto::<Balance>::try_into(n).ok()).unwrap_or_else(Zero::zero);

let balance_cashdrop_amount = transfer_amount / 100; // 1%
let serp_balance = T::Currency::free_balance(T::SetterCurrencyId::get(), &Self::account_id());
ensure!(
balance_cashdrop_amount <= serp_balance,
Expand All @@ -453,20 +493,19 @@ impl<T: Config> SerpTreasury<T::AccountId> for Pallet<T> {
let relative_price = pool_1 / pool_0;
let relative_cashdrop = balance_cashdrop_amount / relative_price;

T::Currency::transfer(T::SetterCurrencyId::get(), &Self::account_id(), who, relative_cashdrop);
Self::deposit_event(Event::CashDrops(T::SetterCurrencyId::get(), who.clone(), relative_cashdrop.clone()));
} else if T::SetCurrencyDropCurrencyIds::get().contains(&currency_id) {
let transfer_drop = transfer_amount.saturating_mul(cashdrop_denominator.saturating_sub(cashdrop_numerator).unique_saturated_into());
let into_cashdrop_amount: U256 = U256::from(transfer_amount).saturating_sub(U256::from(transfer_drop));
let balance_cashdrop_amount = into_cashdrop_amount.and_then(|n| TryInto::<Balance>::try_into(n).ok()).unwrap_or_else(Zero::zero);
T::Currency::transfer(T::SetterCurrencyId::get(), &Self::account_id(), who, relative_cashdrop)?;
Self::deposit_event(Event::CashDropClaim(T::SetterCurrencyId::get(), who.clone(), relative_cashdrop.clone()));
} else if T::SettCurrencyDropCurrencyIds::get().contains(&currency_id) {

let balance_cashdrop_amount = transfer_amount / 50; // 4%
let serp_balance = T::Currency::free_balance(currency_id, &Self::account_id());
ensure!(
balance_cashdrop_amount <= serp_balance,
Error::<T>::CashdropNotAvailable,
);

T::Currency::transfer(currency_id, &Self::account_id(), who, balance_cashdrop_amount);
Self::deposit_event(Event::CashDrops(currency_id, who.clone(), balance_cashdrop_amount.clone()));
T::Currency::transfer(currency_id, &Self::account_id(), who, balance_cashdrop_amount)?;
Self::deposit_event(Event::CashDropClaim(currency_id, who.clone(), balance_cashdrop_amount.clone()));
}
Ok(())
}
Expand Down
34 changes: 20 additions & 14 deletions lib-serml/serp/serp-treasury/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,26 @@
#![cfg(test)]

use super::*;
use frame_support::{construct_runtime, impl_outer_event, impl_outer_origin, ord_parameter_types, parameter_types};
use frame_support::{construct_runtime, ord_parameter_types, parameter_types};
use frame_system::EnsureSignedBy;
use orml_traits::parameter_type_with_key;
use primitives::{Amount, ReserveIdentifier, TokenSymbol, TradingPair};
use sp_core::H256;
use sp_runtime::{
testing::{Header, TestXt},
traits::{IdentityLookup, One as OneT, Zero},
DispatchError, FixedPointNumber,
testing::Header,
traits::{IdentityLookup, One as OneT},
};
use sp_std::cell::RefCell;
use support::{ExchangeRate, Price, PriceProvider, Rate, Ratio};
use support::{Price, PriceProvider, Ratio};

pub type AccountId = u128;
pub type BlockNumber = u64;

pub const ALICE: AccountId = 0;
pub const BOB: AccountId = 1;
pub const CHARITY_FUND: AccountId = 2;
pub const SETTPAY: AccountId = 9;
pub const VAULT: AccountId = 10;

// Currencies constants - CurrencyId/TokenSymbol
pub const DNAR: CurrencyId = CurrencyId::Token(TokenSymbol::DNAR);
Expand Down Expand Up @@ -238,10 +239,12 @@ parameter_types! {
pub const DirhamCurrencyId: CurrencyId = DRAM; // SettinDEX currency ticker is DRAM/

pub const SerpTreasuryPalletId: PalletId = PalletId(*b"set/serp");
pub const SettPayTreasuryPalletId: PalletId = PalletId(*b"set/stpy");
pub CharutyFundAcc: AccountId = CHARITY_FUND;
pub const CharityFundAccountId: AccountId = CHARITY_FUND;
pub const SettPayTreasuryAccountId: AccountId = SETTPAY;
pub const CashDropVaultAccountId: AccountId = VAULT;

pub SerpTesSchedule: BlockNumber = 60; // Triggers SERP-TES for serping after Every 60 blocks
pub CashDropPeriod: BlockNumber = 120; // Triggers SERP-TES for serping after Every 60 blocks
pub MaxSlippageSwapWithDEX: Ratio = Ratio::one();

pub RewardableCurrencyIds: Vec<CurrencyId> = vec![
Expand All @@ -260,8 +263,7 @@ parameter_types! {
USDJ,
];
pub NonStableDropCurrencyIds: Vec<CurrencyId> = vec![DNAR, DRAM];
pub SetCurrencyDropCurrencyIds: Vec<CurrencyId> = vec![
SETT,
pub SettCurrencyDropCurrencyIds: Vec<CurrencyId> = vec![
AUDJ,
CADJ,
CHFJ,
Expand All @@ -273,7 +275,6 @@ parameter_types! {
SGDJ,
USDJ,
];
pub const GetCashDropRate: (u32, u32) = (258, 10000); // 2.58% cashdrop.
}

parameter_type_with_key! {
Expand Down Expand Up @@ -317,15 +318,16 @@ impl Config for Runtime {
type GetSettUSDCurrencyId = GetSettUSDCurrencyId;
type DirhamCurrencyId = DirhamCurrencyId;
type SerpTesSchedule = SerpTesSchedule;
type SettPayTreasuryAcc = SettPayTreasuryPalletId;
type CharityFundAcc = CharutyFundAcc;
type CashDropPeriod = CashDropPeriod;
type SettPayTreasuryAccountId = SettPayTreasuryAccountId;
type CashDropVaultAccountId = CashDropVaultAccountId;
type CharityFundAccountId = CharityFundAccountId;
type Dex = SetheumDEX;
type MaxSlippageSwapWithDEX = MaxSlippageSwapWithDEX;
type PriceSource = MockPriceSource;
type RewardableCurrencyIds = RewardableCurrencyIds;
type NonStableDropCurrencyIds = StableCurrencyIds;
type SetCurrencyDropCurrencyIds = SetCurrencyDropCurrencyIds;
type GetCashDropRate = GetCashDropRate;
type SettCurrencyDropCurrencyIds = SettCurrencyDropCurrencyIds;
type MinimumClaimableTransferAmounts = MinimumClaimableTransferAmounts;
type UpdateOrigin = EnsureSignedBy<One, AccountId>;
type PalletId = SerpTreasuryPalletId;
Expand Down Expand Up @@ -370,6 +372,10 @@ impl Default for ExtBuilder {
(CHARITY_FUND, SETT, 1000),
(CHARITY_FUND, DNAR, 1000),
(CHARITY_FUND, DRAM, 1000),
(SETTPAY, USDJ, 1000),
(SETTPAY, SETT, 1000),
(VAULT, USDJ, 1000),
(VAULT, SETT, 1000),
],
}
}
Expand Down
12 changes: 9 additions & 3 deletions lib-serml/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,18 @@ pub trait SerpTreasury<AccountId> {
/// SerpUp ratio for BuyBack Swaps to burn Dinar
fn get_buyback_serpup(amount: Self::Balance, currency_id: Self::CurrencyId) -> DispatchResult;

/// SerpUp ratio for SettPay Cashdrops
fn get_settpay_serpup(amount: Self::Balance, currency_id: Self::CurrencyId) -> DispatchResult;

/// SerpUp ratio for Setheum Foundation's Charity Fund
fn get_charity_fund_serpup(amount: Self::Balance, currency_id: Self::CurrencyId) -> DispatchResult;

/// SerpUp ratio for SettPay Cashdrops
fn get_cashdrop_serpup(amount: Self::Balance, currency_id: Self::CurrencyId) -> DispatchResult;

/// Reward SETT cashdrop to vault
fn setter_cashdrop_to_vault() -> DispatchResult;

/// Reward USDJ cashdrop to vault
fn usdj_cashdrop_to_vault() -> DispatchResult;

/// Trigger SERP-TES when required for Setter (SETT) to serp_down or serp_up.
fn setter_on_tes() -> DispatchResult;

Expand Down