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

Wpha Council #1269

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
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.

5 changes: 4 additions & 1 deletion pallets/phala/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ rmrk-traits = { git = "https://github.com/Phala-Network/rmrk-substrate", branch
frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false }
pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false }
pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false }
Expand Down Expand Up @@ -73,6 +74,7 @@ std = [
"frame-system/std",
"pallet-assets/std",
"pallet-democracy/std",
"pallet-elections-phragmen/std",
"sp-io/std",
"sp-std/std",
"sp-core/std",
Expand All @@ -91,7 +93,8 @@ std = [
"pallet-preimage/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks"
"frame-benchmarking/runtime-benchmarks",
"pallet-elections-phragmen/runtime-benchmarks",
]
try-runtime = ["frame-support/try-runtime"]
native = [
Expand Down
274 changes: 257 additions & 17 deletions pallets/phala/src/compute/wrapped_balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,27 @@ pub mod pallet {
use crate::pool_proxy::PoolProxy;
use crate::registry;
use crate::vault;
use crate::{BalanceOf, NegativeImbalanceOf, PhalaConfig};
use crate::{BalanceOf, NegativeImbalanceOf, PhalaConfig, PositiveImbalanceOf};
use frame_support::traits::tokens::{Fortitude, Precision};
use frame_support::{
pallet_prelude::*,
traits::{
tokens::fungibles::{Inspect, Mutate},
tokens::nonfungibles::InspectEnumerable,
Currency,
ExistenceRequirement::{AllowDeath, KeepAlive},
OnUnbalanced, StorageVersion,
tokens::{
fungibles::{Inspect, Mutate},
BalanceStatus,
},
Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency,
OnUnbalanced, ReservableCurrency, SignedImbalance, StorageVersion, WithdrawReasons,
},
};
use frame_support::traits::tokens::{Fortitude, Precision};
use frame_system::{pallet_prelude::*, RawOrigin};
use pallet_democracy::{AccountVote, ReferendumIndex, ReferendumInfo};
pub use rmrk_traits::primitives::{CollectionId, NftId};
use scale_info::TypeInfo;
use sp_runtime::traits::Zero;
use sp_std::{fmt::Display, prelude::*, result::Result};

#[pallet::config]
pub trait Config:
frame_system::Config
Expand Down Expand Up @@ -89,6 +92,14 @@ pub mod pallet {
pub type StakerAccounts<T: Config> =
StorageMap<_, Twox64Concat, T::AccountId, FinanceAccount<BalanceOf<T>>>;

#[pallet::storage]
#[pallet::getter(fn election_locks)]
pub type ElectionLocks<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf<T>>;

#[pallet::storage]
#[pallet::getter(fn election_reserves)]
pub type ElectionReserves<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf<T>>;

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
Expand Down Expand Up @@ -133,6 +144,225 @@ pub mod pallet {
ReferendumOngoing,
/// The Iteration exceed the max limitaion
IterationsIsNotVaild,

LockLargerThanTotalBalance,
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved

LiquidityRestrictions,
}

impl<T: Config> Currency<T::AccountId> for Pallet<T>
where
BalanceOf<T>: sp_runtime::traits::AtLeast32BitUnsigned + Copy + FixedPointConvert + Display,
T: pallet_assets::Config<AssetId = u32, Balance = BalanceOf<T>>,
T: Config + pallet_balances::Config + vault::Config + pallet_elections_phragmen::Config,
T: pallet_balances::Config<Balance = BalanceOf<T>>,
{
type Balance = BalanceOf<T>;
type PositiveImbalance = PositiveImbalanceOf<T>;
type NegativeImbalance = NegativeImbalanceOf<T>;
fn total_balance(who: &T::AccountId) -> Self::Balance {
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
Self::get_net_value(who.clone()).expect("Get net value should success; qed.")
}

fn free_balance(who: &T::AccountId) -> Self::Balance {
Self::total_balance(who)
}

fn can_slash(who: &T::AccountId, value: Self::Balance) -> bool {
if value.is_zero() {
return true;
}
Self::free_balance(who) >= value
}

fn total_issuance() -> Self::Balance {
<pallet_assets::pallet::Pallet<T> as Inspect<T::AccountId>>::total_issuance(
T::WPhaAssetId::get(),
)
}

fn active_issuance() -> Self::Balance {
<pallet_assets::pallet::Pallet<T> as Inspect<T::AccountId>>::total_issuance(
T::WPhaAssetId::get(),
)
}

fn deactivate(_amount: Self::Balance) {
unimplemented!()
}

fn reactivate(_amount: Self::Balance) {
unimplemented!()
}

fn minimum_balance() -> Self::Balance {
<pallet_assets::pallet::Pallet<T> as Inspect<T::AccountId>>::minimum_balance(
T::WPhaAssetId::get(),
)
}

fn burn(mut _amount: Self::Balance) -> Self::PositiveImbalance {
unimplemented!()
}

fn issue(mut _amount: Self::Balance) -> Self::NegativeImbalance {
unimplemented!()
}

fn ensure_can_withdraw(
who: &T::AccountId,
amount: Self::Balance,
_reasons: WithdrawReasons,
new_balance: Self::Balance,
) -> DispatchResult {
if amount.is_zero() {
return Ok(());
}
let lock = Self::get_election_lock(who);
ensure!(new_balance >= lock, Error::<T>::LiquidityRestrictions);
Ok(())
}

fn transfer(
_transactor: &T::AccountId,
_dest: &T::AccountId,
_value: Self::Balance,
_existence_requirement: ExistenceRequirement,
) -> DispatchResult {
unimplemented!()
}

fn slash(
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
_who: &T::AccountId,
_value: Self::Balance,
) -> (Self::NegativeImbalance, Self::Balance) {
unimplemented!()
}

fn deposit_into_existing(
_who: &T::AccountId,
_value: Self::Balance,
) -> Result<Self::PositiveImbalance, DispatchError> {
unimplemented!()
}

fn deposit_creating(_who: &T::AccountId, _value: Self::Balance) -> Self::PositiveImbalance {
unimplemented!()
}

fn withdraw(
_who: &T::AccountId,
_value: Self::Balance,
_reasons: WithdrawReasons,
_liveness: ExistenceRequirement,
) -> Result<Self::NegativeImbalance, DispatchError> {
unimplemented!()
}

fn make_free_balance_be(
_who: &T::AccountId,
_value: Self::Balance,
) -> SignedImbalance<Self::Balance, Self::PositiveImbalance> {
unimplemented!()
}
}

impl<T: Config> ReservableCurrency<T::AccountId> for Pallet<T>
where
BalanceOf<T>: sp_runtime::traits::AtLeast32BitUnsigned + Copy + FixedPointConvert + Display,
T: pallet_assets::Config<AssetId = u32, Balance = BalanceOf<T>>,
T: Config + pallet_balances::Config + vault::Config + pallet_elections_phragmen::Config,
T: pallet_balances::Config<Balance = BalanceOf<T>>,
{
fn can_reserve(who: &T::AccountId, value: Self::Balance) -> bool {
Self::total_balance(who) >= value
}
fn reserved_balance(who: &T::AccountId) -> Self::Balance {
ElectionReserves::<T>::get(who).unwrap_or_default()
}
fn reserve(who: &T::AccountId, value: Self::Balance) -> DispatchResult {
let actual = value.min(Self::total_balance(who));
ElectionReserves::<T>::mutate(who, |reserve| {
*reserve = Some(reserve.unwrap_or_default() + actual);
});
Ok(())
}
fn unreserve(who: &T::AccountId, value: Self::Balance) -> Self::Balance {
let actual = value.min(ElectionReserves::<T>::get(who).unwrap_or_default());
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
ElectionReserves::<T>::mutate(who, |reserve| {
*reserve = Some(reserve.unwrap_or_default() - actual);
});
value - actual
}
fn slash_reserved(
who: &T::AccountId,
value: Self::Balance,
) -> (Self::NegativeImbalance, Self::Balance) {
if value == Zero::zero() {
return (NegativeImbalanceOf::<T>::zero(), Zero::zero());
}
let actual = value.min(ElectionReserves::<T>::get(who).unwrap_or_default());
ElectionReserves::<T>::mutate(who, |reserve| {
*reserve = Some(reserve.unwrap_or_default() - actual);
});
Self::burn_from(who, actual)
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
.expect("burn nft when slash reserved should success; qed.");
Index0011 marked this conversation as resolved.
Show resolved Hide resolved
let imbalance = <T as PhalaConfig>::Currency::withdraw(
&T::WrappedBalancesAccountId::get(),
actual,
WithdrawReasons::all(),
ExistenceRequirement::AllowDeath,
)
.expect("slash imbalance should success; qed.");
(imbalance, value - actual)
}
fn repatriate_reserved(
_slashed: &T::AccountId,
_beneficiary: &T::AccountId,
_value: Self::Balance,
_status: BalanceStatus,
) -> Result<Self::Balance, DispatchError> {
unimplemented!()
}
}
impl<T: Config> LockableCurrency<T::AccountId> for Pallet<T>
where
BalanceOf<T>: sp_runtime::traits::AtLeast32BitUnsigned + Copy + FixedPointConvert + Display,
T: pallet_assets::Config<AssetId = u32, Balance = BalanceOf<T>>,
T: Config + pallet_balances::Config + vault::Config + pallet_elections_phragmen::Config,
T: pallet_balances::Config<Balance = BalanceOf<T>>,
{
type Moment = T::BlockNumber;
type MaxLocks = T::MaxLocks;
fn set_lock(
id: LockIdentifier,
who: &T::AccountId,
amount: Self::Balance,
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
_reasons: WithdrawReasons,
) {
if amount == Zero::zero()
|| id != <T as pallet_elections_phragmen::Config>::PalletId::get()
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
{
return;
}
let actual = amount.min(Self::total_balance(who));
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
ElectionLocks::<T>::insert(who, actual);
}
fn extend_lock(
_id: LockIdentifier,
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
who: &T::AccountId,
amount: Self::Balance,
_reasons: WithdrawReasons,
) {
let current_lock = ElectionLocks::<T>::get(who).unwrap_or_default();
let actual = (current_lock + amount).min(Self::total_balance(who));
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
ElectionLocks::<T>::mutate(who, |locks| {
*locks = Some(locks.unwrap_or_default() + actual);
});
}
fn remove_lock(_id: LockIdentifier, who: &T::AccountId) {
ElectionLocks::<T>::remove(who);
}
}

impl<T: Config> rmrk_traits::TransferHooks<T::AccountId, u32, u32> for Pallet<T>
Expand Down Expand Up @@ -196,7 +426,7 @@ pub mod pallet {
&user,
&T::WrappedBalancesAccountId::get(),
amount,
KeepAlive,
ExistenceRequirement::KeepAlive,
)?;
Self::mint_into(&user, amount)?;
if !StakerAccounts::<T>::contains_key(&user) {
Expand Down Expand Up @@ -224,14 +454,13 @@ pub mod pallet {
let free_stakes: BalanceOf<T> = <pallet_assets::pallet::Pallet<T> as Inspect<
T::AccountId,
>>::balance(T::WPhaAssetId::get(), &user);
let locked =
StakerAccounts::<T>::get(&user).map_or(Zero::zero(), |status| status.locked);
let locked = Self::get_election_lock(&user);
let withdraw_amount = (active_stakes - locked).min(free_stakes);
<T as PhalaConfig>::Currency::transfer(
&T::WrappedBalancesAccountId::get(),
&user,
withdraw_amount,
AllowDeath,
ExistenceRequirement::AllowDeath,
)?;
Self::burn_from(&user, withdraw_amount)?;
Ok(())
Expand All @@ -253,8 +482,7 @@ pub mod pallet {
Error::<T>::UnwrapAmountExceedsAvaliableStake
);
let active_stakes = Self::get_net_value(user.clone())?;
let locked =
StakerAccounts::<T>::get(&user).map_or(Zero::zero(), |status| status.locked);
let locked = Self::get_election_lock(&user);
ensure!(
amount + locked <= active_stakes,
Error::<T>::UnwrapAmountExceedsAvaliableStake,
Expand All @@ -263,7 +491,7 @@ pub mod pallet {
&T::WrappedBalancesAccountId::get(),
&user,
amount,
AllowDeath,
ExistenceRequirement::AllowDeath,
)?;
Self::burn_from(&user, amount)?;
Self::deposit_event(Event::<T>::Unwrapped { user, amount });
Expand Down Expand Up @@ -379,9 +607,14 @@ pub mod pallet {
pub fn remove_dust(who: &T::AccountId, dust: BalanceOf<T>) {
debug_assert!(dust != Zero::zero());
if dust != Zero::zero() {
let actual_removed =
pallet_assets::Pallet::<T>::burn_from(T::WPhaAssetId::get(), who, dust, Precision::BestEffort, Fortitude::Force)
.expect("slash should success with correct amount: qed.");
let actual_removed = pallet_assets::Pallet::<T>::burn_from(
T::WPhaAssetId::get(),
who,
dust,
Precision::BestEffort,
Fortitude::Force,
)
.expect("slash should success with correct amount: qed.");
let (imbalance, _remaining) = <T as PhalaConfig>::Currency::slash(
&<computation::pallet::Pallet<T>>::account_id(),
dust,
Expand All @@ -407,7 +640,7 @@ pub mod pallet {
target,
amount,
Precision::BestEffort,
Fortitude::Force
Fortitude::Force,
)?;
Ok(())
}
Expand Down Expand Up @@ -499,5 +732,12 @@ pub mod pallet {
let vote_info = pallet_democracy::Pallet::<T>::referendum_info(vote_id);
matches!(vote_info, Some(ReferendumInfo::Ongoing(_)))
}

fn get_election_lock(who: &T::AccountId) -> BalanceOf<T> {
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
let lock = StakerAccounts::<T>::get(who).map_or(Zero::zero(), |status| status.locked);
let election_lock = ElectionLocks::<T>::get(who).unwrap_or_default();
let election_reserve = ElectionReserves::<T>::get(who).unwrap_or_default();
lock.max(election_lock).max(election_reserve)
}
}
}
Loading