From 8a0197d6b28cd27ee20a04c5f3e4828b74cb850e Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 28 Sep 2022 12:34:39 +0000 Subject: [PATCH] Add pallet fat_tokenomic --- pallets/phala/src/fat.rs | 6 ++ pallets/phala/src/fat_tokenomic.rs | 127 ++++++++++++++++++++++++++++ pallets/phala/src/lib.rs | 1 + pallets/phala/src/migrations/mod.rs | 8 +- 4 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 pallets/phala/src/fat_tokenomic.rs diff --git a/pallets/phala/src/fat.rs b/pallets/phala/src/fat.rs index a4360028ec..c2452353ae 100644 --- a/pallets/phala/src/fat.rs +++ b/pallets/phala/src/fat.rs @@ -393,6 +393,12 @@ pub mod pallet { } Ok(()) } + + pub fn get_system_contract(contract: &ContractId) -> Option { + let contract_info = Contracts::::get(&contract)?; + let cluster_info = Clusters::::get(&contract_info.cluster_id)?; + Some(cluster_info.system_contract) + } } #[pallet::hooks] diff --git a/pallets/phala/src/fat_tokenomic.rs b/pallets/phala/src/fat_tokenomic.rs new file mode 100644 index 0000000000..bc3afbb5ad --- /dev/null +++ b/pallets/phala/src/fat_tokenomic.rs @@ -0,0 +1,127 @@ +//! The Fat Contract tokenomic module + +pub use self::pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use crate::mq::MessageOriginInfo; + use frame_support::{ + dispatch::DispatchResult, + pallet_prelude::*, + traits::{Currency, ExistenceRequirement::*, PalletInfo, StorageVersion}, + }; + use frame_system::pallet_prelude::*; + use phala_types::messaging::ContractId; + use sp_core::crypto::{AccountId32, UncheckedFrom}; + use sp_runtime::traits::Zero; + + type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + #[pallet::config] + pub trait Config: frame_system::Config { + type Event: From> + IsType<::Event>; + type Currency: Currency; + } + + const STORAGE_VERSION: StorageVersion = StorageVersion::new(5); + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::storage_version(STORAGE_VERSION)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + /// (contract, user) -> stake + #[pallet::storage] + pub type ContractUserStakes = + StorageMap<_, Twox64Concat, (ContractId, T::AccountId), BalanceOf, ValueQuery>; + + /// contract -> stake + #[pallet::storage] + pub type ContractTotalStakes = + StorageMap<_, Twox64Concat, ContractId, BalanceOf, ValueQuery>; + + /// Minimum allowed stake + #[pallet::storage] + pub type MinStake = StorageValue<_, BalanceOf, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + ContractDepositChanged { + contract: ContractId, + deposit: BalanceOf, + }, + } + + #[pallet::error] + pub enum Error { + ContractNotFound, + InvalidAmountOfStake, + } + + #[pallet::call] + impl Pallet + where + T: crate::mq::Config, + T: crate::fat::Config, + T: frame_system::Config, + { + #[pallet::weight(0)] + pub fn adjust_stake( + origin: OriginFor, + contract: ContractId, + amount: BalanceOf, + ) -> DispatchResult { + let user = ensure_signed(origin)?; + ensure!( + amount == Zero::zero() || amount >= MinStake::::get(), + Error::::InvalidAmountOfStake + ); + + let mut total = ContractTotalStakes::::get(&contract); + let orig = ContractUserStakes::::get((&contract, &user)); + if amount == orig { + return Ok(()); + } + if amount > orig { + let delta = amount - orig; + total += delta; + ::Currency::transfer(&user, &Self::pallet_id(), delta, KeepAlive)?; + } else { + let delta = orig - amount; + total -= delta; + ::Currency::transfer(&Self::pallet_id(), &user, delta, AllowDeath)?; + } + ContractUserStakes::::insert((&contract, &user), amount); + ContractTotalStakes::::insert(contract, total); + + Self::deposit_event(Event::ContractDepositChanged { + contract, + deposit: total, + }); + + if let Some(the_system_contract) = + crate::fat::Pallet::::get_system_contract(&contract) + { + let selector: u32 = 0xa24bcb44; // ContractDeposit::change_deposit() + let message = (selector.to_be_bytes(), contract, total).encode(); + Self::push_ink_message(the_system_contract, message); + } + Ok(()) + } + } + + impl Pallet { + fn pallet_id() -> AccountId32 { + let pallet_id: u64 = T::PalletInfo::index::() + .expect("Pallet index of fat_tokenomic not found") as _; + AccountId32::unchecked_from(sp_core::H256::from_low_u64_be(pallet_id)) + } + } + + impl MessageOriginInfo for Pallet { + type Config = T; + } +} diff --git a/pallets/phala/src/lib.rs b/pallets/phala/src/lib.rs index 9de173c888..e33b34115a 100644 --- a/pallets/phala/src/lib.rs +++ b/pallets/phala/src/lib.rs @@ -17,6 +17,7 @@ pub mod migrations; pub mod utils; pub mod fat; +pub mod fat_tokenomic; pub mod mining; pub mod mq; pub mod ott; diff --git a/pallets/phala/src/migrations/mod.rs b/pallets/phala/src/migrations/mod.rs index 8ffda3f9a3..5dd9f40857 100644 --- a/pallets/phala/src/migrations/mod.rs +++ b/pallets/phala/src/migrations/mod.rs @@ -14,10 +14,10 @@ type MiningBalanceOf = /// Alias for the runtime that implements all Phala Pallets pub trait PhalaPallets: - fat::Config + mining::Config + mq::Config + registry::Config + stakepool::Config + fat::Config + mining::Config + mq::Config + registry::Config + stakepool::Config + fat_tokenomic::Config {} impl PhalaPallets for T where - T: fat::Config + mining::Config + mq::Config + registry::Config + stakepool::Config + T: fat::Config + mining::Config + mq::Config + registry::Config + stakepool::Config + fat_tokenomic::Config {} type Versions = ( @@ -26,6 +26,7 @@ type Versions = ( StorageVersion, StorageVersion, StorageVersion, + StorageVersion, ); #[allow(dead_code)] @@ -36,6 +37,7 @@ fn get_versions() -> Versions { StorageVersion::get::>(), StorageVersion::get::>(), StorageVersion::get::>(), + StorageVersion::get::>(), ) } @@ -47,6 +49,7 @@ fn unified_versions(version: u16) -> Versions { StorageVersion::new(version), StorageVersion::new(version), StorageVersion::new(version), + StorageVersion::new(version), ) } @@ -57,4 +60,5 @@ fn set_unified_version(version: u16) { StorageVersion::new(version).put::>(); StorageVersion::new(version).put::>(); StorageVersion::new(version).put::>(); + StorageVersion::new(version).put::>(); }