Skip to content

Commit

Permalink
Added some helpers and extrinsic_#1
Browse files Browse the repository at this point in the history
  • Loading branch information
ndkazu committed Dec 30, 2024
1 parent 0f6bd3d commit 54701b7
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 10 deletions.
122 changes: 117 additions & 5 deletions substrate/frame/opf/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,125 @@
pub use super::*;
impl<T: Config> Pallet<T> {

pub fn pot_account() -> AccountIdOf<T> {
// Get Pot account
T::PotId::get().into_account_truncating()
}

/// Funds transfer from the Pot to a project account
pub fn spend(amount: BalanceOf<T>, beneficiary: AccountIdOf<T>) -> DispatchResult {
// Get Pot account
let pot_account: AccountIdOf<T> = Self::pot_account();

//Operate the transfer
T::NativeBalance::transfer(&pot_account, &beneficiary, amount, Preservation::Preserve)?;

Ok(())
}

/// Series of checks on the Pot, to ensure that we have enough funds
/// before executing a Spend --> used in tests.
pub fn pot_check(spend: BalanceOf<T>) -> DispatchResult {
// Get Pot account
let pot_account = Self::pot_account();

// Check that the Pot as enough funds for the transfer
let balance = T::NativeBalance::balance(&pot_account);
let minimum_balance = T::NativeBalance::minimum_balance();
let remaining_balance = balance.saturating_sub(spend);

ensure!(remaining_balance > minimum_balance, Error::<T>::InsufficientPotReserves);
ensure!(balance > spend, Error::<T>::InsufficientPotReserves);
Ok(())
}

// Helper function for project registration
pub fn register_new(project_id: ProjectId<T>, amount: BalanceOf<T>) -> DispatchResult{
pub fn register_new(project_id: ProjectId<T>) -> DispatchResult{
let submission_block = T::BlockNumberProvider::current_block_number();

Check failure on line 57 in substrate/frame/opf/src/functions.rs

View workflow job for this annotation

GitHub Actions / cargo-check-all-crate-macos

unused variable: `submission_block`
let project_infos: ProjectInfo<T> = ProjectInfo { project_id, submission_block, amount};
let mut bounded = Projects::get();
let _ = bounded.try_push(project_infos);
Projects::put(bounded);
let mut bounded: BoundedVec<ProjectId<T>, T::MaxProjects> = WhiteListedProjectAccounts::<T>::get();
let _ = bounded.try_push(project_id);
WhiteListedProjectAccounts::<T>::put(bounded);
Ok(())
}

// Voting Period checks
pub fn period_check() -> DispatchResult {
// Get current voting round & check if we are in voting period or not
let current_round_index = VotingRoundNumber::<T>::get().saturating_sub(1);
let round = VotingRounds::<T>::get(current_round_index).ok_or(Error::<T>::NoRoundFound)?;
let now = T::BlockNumberProvider::current_block_number();
ensure!(now < round.round_ending_block, Error::<T>::VotingRoundOver);
Ok(())
}

pub fn unlist_project(project_id: ProjectId<T>) -> DispatchResult {
WhiteListedProjectAccounts::<T>::mutate(|value| {
let mut val = value.clone();
val.retain(|x| *x != project_id);
*value = val;
});

Ok(())
}

// The total reward to be distributed is a portion or inflation, determined in another pallet
// Reward calculation is executed within the Voting period
pub fn calculate_rewards(total_reward: BalanceOf<T>) -> DispatchResult {
let projects = WhiteListedProjectAccounts::<T>::get();
let round_number = VotingRoundNumber::<T>::get().saturating_sub(1);
let round = VotingRounds::<T>::get(round_number).ok_or(Error::<T>::NoRoundFound)?;
if projects.clone().len() > 0 as usize {
let total_positive_votes_amount = round.total_positive_votes_amount;
let total_negative_votes_amount = round.total_negative_votes_amount;

let total_votes_amount =
total_positive_votes_amount.saturating_sub(total_negative_votes_amount);

// for each project, calculate the percentage of votes, the amount to be distributed,
// and then populate the storage Projects
for project in projects {
if ProjectFunds::<T>::contains_key(&project) {
let funds = ProjectFunds::<T>::get(&project);
let project_positive_reward = funds[0];
let project_negative_reward = funds[1];

let project_reward =
project_positive_reward.saturating_sub(project_negative_reward);

let project_percentage =
Percent::from_rational(project_reward, total_votes_amount);
let final_amount = project_percentage * total_reward;

// Send calculated reward for reward distribution
let now = T::BlockNumberProvider::current_block_number();
let project_info = ProjectInfo {
project_id: project.clone(),
submission_block: now,
amount: final_amount,
};

let mut rewarded = Projects::<T>::get();
rewarded
.try_push(project_info.clone())
.map_err(|_| Error::<T>::MaximumProjectsNumber)?;

Projects::<T>::mutate(|value| {
*value = rewarded;
});

let when = T::BlockNumberProvider::current_block_number();
Self::deposit_event(Event::<T>::ProjectFundingAccepted {
project_id: project,
when,
round_number,
amount: project_info.amount,
})

}
}
}

Ok(())
}

}
34 changes: 31 additions & 3 deletions substrate/frame/opf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,21 @@ pub mod pallet {
#[pallet::storage]
pub type Projects<T: Config> =
StorageValue<_, BoundedVec<ProjectInfo<T>, T::MaxProjects>, ValueQuery>;

/// List of Whitelisted Project registered
#[pallet::storage]
pub type WhiteListedProjectAccounts<T: Config> =
StorageValue<_, BoundedVec<ProjectId<T>, T::MaxProjects>, ValueQuery>;

/// Returns (positive_funds,negative_funds) of Whitelisted Project accounts
#[pallet::storage]
pub type ProjectFunds<T: Config> = StorageMap<
_,
Twox64Concat,
ProjectId<T>,
BoundedVec<BalanceOf<T>, ConstU32<2>>,
ValueQuery,
>;

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
Expand Down Expand Up @@ -183,6 +198,14 @@ pub mod pallet {
FundsReserveFailed,
/// An invalid result was returned
InvalidResult,
/// The reward calculation failed due to an internal error
FailedRewardCalculation,
/// Voting round is over
VotingRoundOver,
/// This voting round does not exists
NoRoundFound,
/// Maximum number of projects submission for reward distribution as been reached
MaximumProjectsNumber,
}

/*#[pallet::hooks]
Expand All @@ -197,10 +220,10 @@ pub mod pallet {

#[pallet::call_index(0)]
#[transactional]
pub fn register_project(origin: OriginFor<T>, project_id: ProjectId<T>, amount: BalanceOf<T>) -> DispatchResult{
pub fn register_project(origin: OriginFor<T>, project_id: ProjectId<T>) -> DispatchResult{
let _caller = ensure_signed(origin)?;
let when = T::BlockNumberProvider::current_block_number();
Self::register_new(project_id.clone(), amount)?;
Self::register_new(project_id.clone())?;
Self::deposit_event(Event::Projectlisted {
when,
project_id,
Expand All @@ -210,7 +233,12 @@ pub mod pallet {

#[pallet::call_index(1)]
#[transactional]
pub fn unregister_project(origin: OriginFor<T>) -> DispatchResult {
pub fn unregister_project(origin: OriginFor<T>, project_id: ProjectId<T> ) -> DispatchResult {
ensure_root(origin)?;
let when = T::BlockNumberProvider::current_block_number();
Self::unlist_project(project_id.clone())?;
Self::deposit_event(Event::<T>::ProjectUnlisted { when, project_id });

Ok(())
}

Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/opf/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ pub use frame_support::{
pub use pallet_conviction_voting::Conviction;
pub use frame_system::{pallet_prelude::*, RawOrigin};
pub use scale_info::prelude::vec::Vec;
pub use sp_runtime::traits::{
pub use sp_runtime::{traits::{
AccountIdConversion, BlockNumberProvider, Convert, Dispatchable, Saturating, StaticLookup, Zero,
};
}, Percent};
pub use sp_std::boxed::Box;

pub type BalanceOf<T> = <<T as Config>::NativeBalance as fungible::Inspect<
Expand Down

0 comments on commit 54701b7

Please sign in to comment.