Refactoring Checkpoint: (WIP)

This commit is contained in:
2025-12-14 10:29:31 +03:00
parent 09735eb97a
commit c89d7cac55
1424 changed files with 6415 additions and 6064 deletions
@@ -0,0 +1,92 @@
[package]
name = "pezpallet-pez-treasury"
version = "1.0.0"
description = "PezkuwiChain Programmatic Treasury with Synthetic Halving"
authors.workspace = true
homepage.workspace = true
edition.workspace = true
license.workspace = true
publish = false
repository.workspace = true
documentation = "https://docs.rs/pezpallet-pez-treasury"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { workspace = true, default-features = false, features = ["derive"] }
scale-info = { default-features = false, features = [
"derive",
], workspace = true }
serde = { version = "1.0", default-features = false, features = [
"derive",
], optional = true }
pezframe-support = { default-features = false, workspace = true }
pezframe-system = { default-features = false, workspace = true }
log = { default-features = false, workspace = true }
pezsp-runtime = { default-features = false, workspace = true }
pezsp-std = { default-features = false, workspace = true }
# PezkuwiChain'in özel tiplerini ve trait'lerini içeren kütüphane
pezkuwi-primitives = { workspace = true, default-features = false }
# Standart Bizinikiwi paletleri
pezpallet-balances = { default-features = false, workspace = true }
pezpallet-scheduler = { default-features = false, workspace = true }
# Test ve Benchmark için Gerekli İsteğe Bağlı Bağımlılıklar
pezframe-benchmarking = { optional = true, workspace = true }
pezsp-core = { workspace = true, default-features = false, optional = true }
pezsp-io = { workspace = true, default-features = false, optional = true }
[dev-dependencies]
# Test için gerekli olan bağımlılıklar
pezsp-core = { workspace = true, default-features = false }
pezsp-io = { workspace = true, default-features = false }
pezpallet-assets = { workspace = true, default-features = false, features = [
"std",
] } # <-- BU SATIRI EKLEYİN
[features]
default = ["std"]
std = [
"codec/std",
"pezframe-benchmarking?/std",
"pezframe-support/std",
"pezframe-system/std",
"log/std",
"pezpallet-assets/std",
"pezpallet-balances/std",
"pezpallet-scheduler/std",
"pezkuwi-primitives/std",
"scale-info/std",
"serde",
"serde?/std",
"pezsp-core?/std",
"pezsp-io?/std",
"pezsp-runtime/std",
"pezsp-std/std",
]
runtime-benchmarks = [
"pezframe-benchmarking",
"pezframe-benchmarking/runtime-benchmarks",
"pezframe-support/runtime-benchmarks",
"pezframe-system/runtime-benchmarks",
"pezpallet-assets/runtime-benchmarks",
"pezpallet-balances/runtime-benchmarks",
"pezpallet-scheduler/runtime-benchmarks",
"pezkuwi-primitives/runtime-benchmarks",
"pezsp-core",
"pezsp-io",
"pezsp-io?/runtime-benchmarks",
"pezsp-runtime/runtime-benchmarks",
]
try-runtime = [
"pezframe-support/try-runtime",
"pezframe-system/try-runtime",
"pezpallet-assets/try-runtime",
"pezpallet-balances/try-runtime",
"pezpallet-scheduler/try-runtime",
"pezsp-runtime/try-runtime",
]
@@ -0,0 +1,92 @@
// pezkuwi/pallets/pez-treasury/src/benchmarking.rs
#![cfg(feature = "runtime-benchmarks")]
use super::*;
use crate::Pallet as PezTreasury;
use pezframe_benchmarking::v2::*;
use pezframe_support::traits::{
fungibles::{Inspect, Mutate},
Get, // HATA GİDERİLDİ: .get() fonksiyonu için bu trait eklendi
};
use pezframe_system::RawOrigin;
use pezsp_runtime::traits::{Saturating, Zero};
#[benchmarks]
mod benchmarks {
use super::*;
#[benchmark]
fn initialize_treasury() {
crate::TreasuryStartBlock::<T>::kill();
crate::HalvingInfo::<T>::kill();
crate::NextReleaseMonth::<T>::kill();
#[extrinsic_call]
initialize_treasury(RawOrigin::Root);
assert!(crate::TreasuryStartBlock::<T>::get().is_some());
let halving_info = crate::HalvingInfo::<T>::get();
assert_eq!(halving_info.current_period, 0);
assert!(!halving_info.monthly_amount.is_zero());
}
#[benchmark]
fn force_genesis_distribution() {
// Clear the flag to allow benchmark run (tests the new storage operation)
crate::GenesisDistributionDone::<T>::kill();
#[block]
{
PezTreasury::<T>::do_genesis_distribution().unwrap();
}
let treasury_account = PezTreasury::<T>::treasury_account_id();
let presale_account = T::PresaleAccount::get();
let founder_account = T::FounderAccount::get();
assert!(!T::Assets::balance(T::PezAssetId::get(), &treasury_account).is_zero());
assert!(!T::Assets::balance(T::PezAssetId::get(), &presale_account).is_zero());
assert!(!T::Assets::balance(T::PezAssetId::get(), &founder_account).is_zero());
}
#[benchmark]
fn release_monthly_funds() {
// Setup
crate::TreasuryStartBlock::<T>::kill();
crate::HalvingInfo::<T>::kill();
crate::NextReleaseMonth::<T>::kill();
crate::GenesisDistributionDone::<T>::kill();
// Deprecated `remove_all` yerine `clear` kullanılıyor.
crate::MonthlyReleases::<T>::clear(u32::MAX, None);
// First do genesis distribution to properly fund the treasury
PezTreasury::<T>::do_genesis_distribution().unwrap();
PezTreasury::<T>::do_initialize_treasury().unwrap();
let treasury_account = PezTreasury::<T>::treasury_account_id();
let initial_monthly_amount = PezTreasury::<T>::halving_info().monthly_amount;
let incentive_amount = initial_monthly_amount * 75u32.into() / 100u32.into();
let government_amount = initial_monthly_amount.saturating_sub(incentive_amount);
// Ensure treasury has MORE than enough balance for the release
// Mint additional 10x the monthly amount to ensure sufficient balance
let _ = T::Assets::mint_into(
T::PezAssetId::get(),
&treasury_account,
initial_monthly_amount * 10u32.into(),
);
let current_block = pezframe_system::Pallet::<T>::block_number();
let target_block = current_block + crate::BLOCKS_PER_MONTH.into() + 1u32.into();
pezframe_system::Pallet::<T>::set_block_number(target_block);
#[extrinsic_call]
release_monthly_funds(RawOrigin::Root);
assert_eq!(PezTreasury::<T>::get_incentive_pot_balance(), incentive_amount);
assert_eq!(PezTreasury::<T>::get_government_pot_balance(), government_amount);
}
impl_benchmark_test_suite!(PezTreasury, crate::mock::new_test_ext(), crate::mock::Test);
}
@@ -0,0 +1,469 @@
#![cfg_attr(not(feature = "std"), no_std)]
//! # PEZ Treasury Pallet
//!
//! A pallet for managing the PEZ token distribution and treasury with automated halving mechanics.
//!
//! ## Overview
//!
//! This pallet manages the complete lifecycle of PEZ token distribution including:
//!
//! - **Genesis Distribution**: One-time initial distribution to treasury, presale, and founder
//! accounts
//! - **Halving Mechanism**: Automatic reduction of monthly releases every 48 months (4 years)
//! - **Monthly Releases**: Scheduled distribution to incentive and government pots
//! - **Multi-Pot System**: Separate accounts for treasury, incentive rewards, and governance
//!
//! ## Token Economics
//!
//! - **Total Supply**: 5,000,000,000 PEZ (5 billion tokens)
//! - **Treasury Allocation**: 96.25% (4,812,500,000 PEZ)
//! - **Presale Allocation**: 1.875% (93,750,000 PEZ)
//! - **Founder Allocation**: 1.875% (93,750,000 PEZ)
//!
//! ## Halving Schedule
//!
//! - **Halving Period**: Every 48 months (4 years)
//! - **Period Duration**: 20,736,000 blocks (~4 years at 10 blocks/minute)
//! - **Distribution**: 70% to Incentive Pot, 30% to Government Pot
//! - **Automatic Halving**: Monthly release amount halves at the start of each new period
//!
//! ## Security Features
//!
//! - **One-Time Genesis**: Genesis distribution can only occur once (protected by storage flag)
//! - **Privileged Operations**: All extrinsics require privileged origin (root or governance)
//! - **Block-Based Scheduling**: Monthly releases based on block numbers for determinism
//!
//! ## Interface
//!
//! ### Extrinsics
//!
//! - `force_genesis_distribution()` - Perform initial token distribution (one-time only,
//! privileged)
//! - `initialize_treasury()` - Initialize the halving mechanism and start monthly releases
//! (privileged)
//! - `release_monthly_funds()` - Release monthly funds to incentive and government pots
//! (privileged)
//!
//! ### Storage
//!
//! - `HalvingInfo` - Current halving period data and monthly release amount
//! - `MonthlyReleases` - Historical record of all monthly distributions
//! - `GenesisDistributionDone` - Flag to prevent duplicate genesis distribution
//!
//! ### Runtime Integration Example
//!
//! ```ignore
//! impl pezpallet_pez_treasury::Config for Runtime {
//! type RuntimeEvent = RuntimeEvent;
//! type Assets = Assets;
//! type WeightInfo = pezpallet_pez_treasury::weights::BizinikiwiWeight<Runtime>;
//! type PezAssetId = ConstU32<1>; // PEZ asset ID
//! type TreasuryPalletId = TreasuryPalletId;
//! type IncentivePotId = IncentivePotId;
//! type GovernmentPotId = GovernmentPotId;
//! type PresaleAccount = PresaleAccount;
//! type FounderAccount = FounderAccount;
//! type ForceOrigin = EnsureRoot<AccountId>;
//! }
//! ```
pub use pallet::*;
pub use weights::WeightInfo;
pub mod migrations;
pub mod weights;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
use pezframe_support::{
traits::{
fungibles::{Inspect, Mutate},
tokens::Preservation,
Get,
},
PalletId,
};
use pezframe_system::pezpallet_prelude::BlockNumberFor;
use scale_info::TypeInfo;
use pezsp_runtime::traits::{AccountIdConversion, Saturating, Zero};
#[pezframe_support::pallet]
pub mod pallet {
use super::*;
use pezframe_support::pezpallet_prelude::*;
use pezframe_system::pezpallet_prelude::*;
// use pezsp_runtime::traits::CheckedDiv;
pub const HALVING_PERIOD_MONTHS: u32 = 48; // 4 years = 48 months
pub const BLOCKS_PER_MONTH: u32 = 432_000; // ~30 days * 24 hours * 60 minutes * 10 blocks/minute
pub const HALVING_PERIOD_BLOCKS: u32 = HALVING_PERIOD_MONTHS * BLOCKS_PER_MONTH;
pub const TOTAL_SUPPLY: u128 = 5_000_000_000 * 1_000_000_000_000; // 5 billion PEZ (12 decimal)
pub const TREASURY_ALLOCATION: u128 = 4_812_500_000 * 1_000_000_000_000; // %96.25
pub const PRESALE_ALLOCATION: u128 = 93_750_000 * 1_000_000_000_000; // %1.875
pub const FOUNDER_ALLOCATION: u128 = 93_750_000 * 1_000_000_000_000; // %1.875
#[pallet::pallet]
#[pallet::storage_version(migrations::STORAGE_VERSION)]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: pezframe_system::Config + TypeInfo {
type Assets: Mutate<Self::AccountId>;
type WeightInfo: weights::WeightInfo;
#[pallet::constant]
type PezAssetId: Get<<Self::Assets as Inspect<Self::AccountId>>::AssetId>;
#[pallet::constant]
type TreasuryPalletId: Get<PalletId>;
#[pallet::constant]
type IncentivePotId: Get<PalletId>;
#[pallet::constant]
type GovernmentPotId: Get<PalletId>;
#[pallet::constant]
type PresaleAccount: Get<Self::AccountId>;
#[pallet::constant]
type FounderAccount: Get<Self::AccountId>;
type ForceOrigin: EnsureOrigin<Self::RuntimeOrigin>;
}
pub type BalanceOf<T> =
<<T as Config>::Assets as Inspect<<T as pezframe_system::Config>::AccountId>>::Balance;
#[pallet::storage]
#[pallet::getter(fn halving_info)]
pub type HalvingInfo<T: Config> = StorageValue<_, HalvingData<T>, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn monthly_releases)]
pub type MonthlyReleases<T: Config> =
StorageMap<_, Blake2_128Concat, u32, MonthlyRelease<T>, OptionQuery>;
#[pallet::storage]
#[pallet::getter(fn next_release_month)]
pub type NextReleaseMonth<T: Config> = StorageValue<_, u32, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn treasury_start_block)]
pub type TreasuryStartBlock<T: Config> = StorageValue<_, BlockNumberFor<T>, OptionQuery>;
#[pallet::storage]
#[pallet::getter(fn genesis_distribution_done)]
pub type GenesisDistributionDone<T: Config> = StorageValue<_, bool, ValueQuery>;
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
pub struct HalvingData<T: Config> {
pub current_period: u32,
pub period_start_block: BlockNumberFor<T>,
pub monthly_amount: BalanceOf<T>,
pub total_released: BalanceOf<T>,
}
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
pub struct MonthlyRelease<T: Config> {
pub month_index: u32,
pub release_block: BlockNumberFor<T>,
pub amount_released: BalanceOf<T>,
pub incentive_amount: BalanceOf<T>,
pub government_amount: BalanceOf<T>,
}
impl<T: Config> Default for HalvingData<T> {
fn default() -> Self {
Self {
current_period: 0,
period_start_block: Zero::zero(),
monthly_amount: Zero::zero(),
total_released: Zero::zero(),
}
}
}
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
TreasuryInitialized {
start_block: BlockNumberFor<T>,
initial_monthly_amount: BalanceOf<T>,
},
MonthlyFundsReleased {
month_index: u32,
total_amount: BalanceOf<T>,
incentive_amount: BalanceOf<T>,
government_amount: BalanceOf<T>,
},
NewHalvingPeriod {
period: u32,
new_monthly_amount: BalanceOf<T>,
},
GenesisDistributionCompleted {
treasury_amount: BalanceOf<T>,
presale_amount: BalanceOf<T>,
founder_amount: BalanceOf<T>,
},
}
#[pallet::error]
pub enum Error<T> {
TreasuryAlreadyInitialized,
TreasuryNotInitialized,
MonthlyReleaseAlreadyDone,
InsufficientTreasuryBalance,
InvalidHalvingPeriod,
ReleaseTooEarly,
GenesisDistributionAlreadyDone,
}
#[pallet::genesis_config]
#[derive(pezframe_support::DefaultNoBound)]
pub struct GenesisConfig<T: Config> {
pub initialize_treasury: bool,
#[serde(skip)]
pub _phantom: core::marker::PhantomData<T>,
}
#[pallet::genesis_build]
impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
fn build(&self) {
if self.initialize_treasury {
let _ = Pallet::<T>::do_initialize_treasury();
}
}
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::initialize_treasury())]
pub fn initialize_treasury(origin: OriginFor<T>) -> DispatchResult {
T::ForceOrigin::ensure_origin(origin)?;
Self::do_initialize_treasury()
}
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::release_monthly_funds())]
pub fn release_monthly_funds(origin: OriginFor<T>) -> DispatchResult {
T::ForceOrigin::ensure_origin(origin)?;
Self::do_monthly_release()
}
#[pallet::call_index(2)]
#[pallet::weight(T::WeightInfo::force_genesis_distribution())]
pub fn force_genesis_distribution(origin: OriginFor<T>) -> DispatchResult {
T::ForceOrigin::ensure_origin(origin)?;
Self::do_genesis_distribution()
}
}
impl<T: Config> Pallet<T> {
pub fn treasury_account_id() -> T::AccountId {
T::TreasuryPalletId::get().into_account_truncating()
}
pub fn incentive_pot_account_id() -> T::AccountId {
T::IncentivePotId::get().into_account_truncating()
}
pub fn government_pot_account_id() -> T::AccountId {
T::GovernmentPotId::get().into_account_truncating()
}
pub fn do_genesis_distribution() -> DispatchResult {
// SECURITY: Ensure genesis distribution can only happen once
ensure!(
!GenesisDistributionDone::<T>::get(),
Error::<T>::GenesisDistributionAlreadyDone
);
let treasury_account = Self::treasury_account_id();
let presale_account = T::PresaleAccount::get();
let founder_account = T::FounderAccount::get();
let treasury_amount: BalanceOf<T> = TREASURY_ALLOCATION
.try_into()
.map_err(|_| Error::<T>::InsufficientTreasuryBalance)?;
let presale_amount: BalanceOf<T> = PRESALE_ALLOCATION
.try_into()
.map_err(|_| Error::<T>::InsufficientTreasuryBalance)?;
let founder_amount: BalanceOf<T> = FOUNDER_ALLOCATION
.try_into()
.map_err(|_| Error::<T>::InsufficientTreasuryBalance)?;
T::Assets::mint_into(T::PezAssetId::get(), &treasury_account, treasury_amount)?;
T::Assets::mint_into(T::PezAssetId::get(), &presale_account, presale_amount)?;
T::Assets::mint_into(T::PezAssetId::get(), &founder_account, founder_amount)?;
// Mark genesis distribution as completed
GenesisDistributionDone::<T>::put(true);
Self::deposit_event(Event::GenesisDistributionCompleted {
treasury_amount,
presale_amount,
founder_amount,
});
Ok(())
}
pub fn do_initialize_treasury() -> DispatchResult {
ensure!(
TreasuryStartBlock::<T>::get().is_none(),
Error::<T>::TreasuryAlreadyInitialized
);
let current_block = pezframe_system::Pallet::<T>::block_number();
let treasury_balance = TREASURY_ALLOCATION;
let first_period_total =
treasury_balance.checked_div(2).ok_or(Error::<T>::InvalidHalvingPeriod)?;
let monthly_amount = first_period_total
.checked_div(HALVING_PERIOD_MONTHS.into())
.ok_or(Error::<T>::InvalidHalvingPeriod)?;
let monthly_amount_balance: BalanceOf<T> =
monthly_amount.try_into().map_err(|_| Error::<T>::InsufficientTreasuryBalance)?;
let halving_data = HalvingData {
current_period: 0,
period_start_block: current_block,
monthly_amount: monthly_amount_balance,
total_released: Zero::zero(),
};
TreasuryStartBlock::<T>::put(current_block);
HalvingInfo::<T>::put(halving_data);
NextReleaseMonth::<T>::put(0);
Self::deposit_event(Event::TreasuryInitialized {
start_block: current_block,
initial_monthly_amount: monthly_amount_balance,
});
Ok(())
}
pub fn do_monthly_release() -> DispatchResult {
ensure!(TreasuryStartBlock::<T>::get().is_some(), Error::<T>::TreasuryNotInitialized);
let current_block = pezframe_system::Pallet::<T>::block_number();
let start_block = TreasuryStartBlock::<T>::get().unwrap();
let next_month = NextReleaseMonth::<T>::get();
ensure!(
!MonthlyReleases::<T>::contains_key(next_month),
Error::<T>::MonthlyReleaseAlreadyDone
);
let blocks_passed = current_block.saturating_sub(start_block);
let months_passed: u32 = (blocks_passed / BLOCKS_PER_MONTH.into())
.try_into()
.map_err(|_| Error::<T>::InvalidHalvingPeriod)?;
// To release month 0, months_passed must be >= 1 (next_month + 1)
// To release month 1, months_passed must be >= 2
ensure!(months_passed > next_month, Error::<T>::ReleaseTooEarly);
let mut halving_data = HalvingInfo::<T>::get();
let current_period_passed_months =
months_passed.saturating_sub(halving_data.current_period * HALVING_PERIOD_MONTHS);
if current_period_passed_months >= HALVING_PERIOD_MONTHS {
halving_data.current_period = halving_data.current_period.saturating_add(1);
halving_data.monthly_amount = halving_data
.monthly_amount
.checked_div(&2u32.into())
.ok_or(Error::<T>::InvalidHalvingPeriod)?;
halving_data.period_start_block = current_block;
Self::deposit_event(Event::NewHalvingPeriod {
period: halving_data.current_period,
new_monthly_amount: halving_data.monthly_amount,
});
}
let monthly_amount = halving_data.monthly_amount;
let incentive_amount = monthly_amount
.checked_mul(&75u32.into())
.and_then(|v| v.checked_div(&100u32.into()))
.ok_or(Error::<T>::InvalidHalvingPeriod)?;
let government_amount = monthly_amount.saturating_sub(incentive_amount);
let treasury_account = Self::treasury_account_id();
let incentive_pot = Self::incentive_pot_account_id();
let government_pot = Self::government_pot_account_id();
T::Assets::transfer(
T::PezAssetId::get(),
&treasury_account,
&incentive_pot,
incentive_amount,
Preservation::Preserve,
)
.map_err(|_| Error::<T>::InsufficientTreasuryBalance)?;
T::Assets::transfer(
T::PezAssetId::get(),
&treasury_account,
&government_pot,
government_amount,
Preservation::Preserve,
)
.map_err(|_| Error::<T>::InsufficientTreasuryBalance)?;
halving_data.total_released =
halving_data.total_released.saturating_add(monthly_amount);
HalvingInfo::<T>::put(halving_data);
let release_info = MonthlyRelease {
month_index: next_month,
release_block: current_block,
amount_released: monthly_amount,
incentive_amount,
government_amount,
};
MonthlyReleases::<T>::insert(next_month, release_info);
NextReleaseMonth::<T>::put(next_month + 1);
Self::deposit_event(Event::MonthlyFundsReleased {
month_index: next_month,
total_amount: monthly_amount,
incentive_amount,
government_amount,
});
Ok(())
}
pub fn get_current_halving_info() -> HalvingData<T> {
HalvingInfo::<T>::get()
}
pub fn get_incentive_pot_balance() -> BalanceOf<T> {
let pot_account = Self::incentive_pot_account_id();
T::Assets::balance(T::PezAssetId::get(), &pot_account)
}
pub fn get_government_pot_balance() -> BalanceOf<T> {
let pot_account = Self::government_pot_account_id();
T::Assets::balance(T::PezAssetId::get(), &pot_account)
}
}
}
@@ -0,0 +1,245 @@
//! Storage migrations for pezpallet-pez-treasury
use super::*;
use pezframe_support::{
traits::{Get, GetStorageVersion, OnRuntimeUpgrade, StorageVersion},
weights::Weight,
};
use pezsp_std::marker::PhantomData;
/// Current storage version
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
/// Migration from v0 to v1
/// This migration handles the initial version setup for pezpallet-pez-treasury
pub mod v1 {
use super::*;
pub struct MigrateToV1<T>(PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for MigrateToV1<T> {
fn on_runtime_upgrade() -> Weight {
let current = Pallet::<T>::on_chain_storage_version();
log::info!(
"🔄 Running migration for pezpallet-pez-treasury from {:?} to {:?}",
current,
STORAGE_VERSION
);
if current == StorageVersion::new(0) {
let mut weight = Weight::zero();
// Example migration logic for treasury storage
// If storage format changes in the future, implement transformation here
// Count existing storage items for logging
let monthly_releases_count = MonthlyReleases::<T>::iter().count() as u64;
let has_halving_info = if HalvingInfo::<T>::exists() { 1u64 } else { 0u64 };
let has_treasury_start =
if TreasuryStartBlock::<T>::get().is_some() { 1u64 } else { 0u64 };
let has_genesis_done =
if GenesisDistributionDone::<T>::get() { 1u64 } else { 0u64 };
let migrated = monthly_releases_count +
has_halving_info +
has_treasury_start +
has_genesis_done;
// Update storage version
STORAGE_VERSION.put::<Pallet<T>>();
log::info!("✅ Migrated {} entries in pezpallet-pez-treasury", migrated);
log::info!(" MonthlyReleases: {}, HalvingInfo: {}, TreasuryStartBlock: {}, GenesisDistributionDone: {}",
monthly_releases_count, has_halving_info, has_treasury_start, has_genesis_done);
// Return weight used
// Reads: all storage items + version read
// Writes: version write
weight = weight.saturating_add(T::DbWeight::get().reads_writes(migrated + 1, 1));
weight
} else {
log::info!(
"👌 pezpallet-pez-treasury migration not needed, current version is {:?}",
current
);
T::DbWeight::get().reads(1)
}
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<pezsp_std::vec::Vec<u8>, pezsp_runtime::TryRuntimeError> {
let current = Pallet::<T>::on_chain_storage_version();
log::info!("🔍 Pre-upgrade check for pezpallet-pez-treasury");
log::info!(" Current version: {:?}", current);
// Encode current storage counts for verification
let monthly_releases_count = MonthlyReleases::<T>::iter().count() as u32;
let next_release_month = NextReleaseMonth::<T>::get();
let has_treasury_start = TreasuryStartBlock::<T>::get().is_some();
let genesis_done = GenesisDistributionDone::<T>::get();
log::info!(" MonthlyReleases entries: {}", monthly_releases_count);
log::info!(" NextReleaseMonth: {}", next_release_month);
log::info!(" TreasuryStartBlock exists: {}", has_treasury_start);
log::info!(" GenesisDistributionDone: {}", genesis_done);
Ok((monthly_releases_count, next_release_month, has_treasury_start, genesis_done)
.encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: pezsp_std::vec::Vec<u8>) -> Result<(), pezsp_runtime::TryRuntimeError> {
use codec::Decode;
let (
pre_monthly_releases_count,
pre_next_release_month,
pre_has_treasury_start,
pre_genesis_done,
): (u32, u32, bool, bool) = Decode::decode(&mut &state[..])
.map_err(|_| "Failed to decode pre-upgrade state")?;
log::info!("🔍 Post-upgrade check for pezpallet-pez-treasury");
// Verify storage version was updated
let current_version = Pallet::<T>::on_chain_storage_version();
assert_eq!(current_version, STORAGE_VERSION, "Storage version not updated correctly");
log::info!("✅ Storage version updated to {:?}", current_version);
// Verify storage counts (should be same or more, never less)
let post_monthly_releases_count = MonthlyReleases::<T>::iter().count() as u32;
let post_next_release_month = NextReleaseMonth::<T>::get();
let post_has_treasury_start = TreasuryStartBlock::<T>::get().is_some();
let post_genesis_done = GenesisDistributionDone::<T>::get();
log::info!(
" MonthlyReleases entries: {} -> {}",
pre_monthly_releases_count,
post_monthly_releases_count
);
log::info!(
" NextReleaseMonth: {} -> {}",
pre_next_release_month,
post_next_release_month
);
log::info!(
" TreasuryStartBlock exists: {} -> {}",
pre_has_treasury_start,
post_has_treasury_start
);
log::info!(" GenesisDistributionDone: {} -> {}", pre_genesis_done, post_genesis_done);
// Verify no data was lost
assert!(
post_monthly_releases_count >= pre_monthly_releases_count,
"MonthlyReleases entries decreased during migration"
);
// NextReleaseMonth should not decrease
assert!(
post_next_release_month >= pre_next_release_month,
"NextReleaseMonth decreased during migration"
);
// Treasury start block should not be removed if it existed
if pre_has_treasury_start {
assert!(post_has_treasury_start, "TreasuryStartBlock was removed during migration");
}
// Genesis done flag should not change from true to false
if pre_genesis_done {
assert!(post_genesis_done, "GenesisDistributionDone was reset during migration");
}
log::info!("✅ Post-upgrade checks passed for pezpallet-pez-treasury");
Ok(())
}
}
}
/// Example migration for future version changes
/// This demonstrates how to handle storage format changes in treasury data
pub mod v2 {
use super::*;
/// Example: Migration when halving data or release format changes
pub struct MigrateToV2<T>(PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for MigrateToV2<T> {
fn on_runtime_upgrade() -> Weight {
let current = Pallet::<T>::on_chain_storage_version();
if current < StorageVersion::new(2) {
log::info!("🔄 Running migration for pezpallet-pez-treasury to v2");
// Example migration logic
// 1. Transform halving data if format changed
// 2. Migrate monthly release records if needed
// 3. Update version
// For now, this is just a template
StorageVersion::new(2).put::<Pallet<T>>();
log::info!("✅ Completed migration to pezpallet-pez-treasury v2");
T::DbWeight::get().reads_writes(1, 1)
} else {
log::info!("👌 pezpallet-pez-treasury v2 migration not needed");
T::DbWeight::get().reads(1)
}
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<pezsp_std::vec::Vec<u8>, pezsp_runtime::TryRuntimeError> {
log::info!("🔍 Pre-upgrade check for pezpallet-pez-treasury v2");
Ok(pezsp_std::vec::Vec::new())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: pezsp_std::vec::Vec<u8>) -> Result<(), pezsp_runtime::TryRuntimeError> {
log::info!("✅ Post-upgrade check passed for pezpallet-pez-treasury v2");
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mock::{new_test_ext, Test};
use pezframe_support::traits::OnRuntimeUpgrade;
#[test]
fn test_migration_v1() {
new_test_ext().execute_with(|| {
// Set initial storage version to 0
StorageVersion::new(0).put::<Pallet<Test>>();
// Run migration
let weight = v1::MigrateToV1::<Test>::on_runtime_upgrade();
// Verify version was updated
assert_eq!(Pallet::<Test>::on_chain_storage_version(), STORAGE_VERSION);
// Verify weight is non-zero
assert!(weight != Weight::zero());
});
}
#[test]
fn test_migration_idempotent() {
new_test_ext().execute_with(|| {
// Set current version
STORAGE_VERSION.put::<Pallet<Test>>();
// Run migration again
let weight = v1::MigrateToV1::<Test>::on_runtime_upgrade();
// Should be a no-op
assert_eq!(weight, pezframe_support::weights::constants::RocksDbWeight::get().reads(1));
});
}
}
@@ -0,0 +1,249 @@
// pezkuwi/pallets/pez-treasury/src/mock.rs
// VERSION 3: AccountId tipi H256 yapıldı (u64 yerine)
use crate as pezpallet_pez_treasury;
use pezframe_support::{
assert_ok, construct_runtime, parameter_types,
traits::{ConstU128, ConstU32, OnFinalize, OnInitialize},
PalletId,
};
use pezsp_core::H256;
use pezsp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
BuildStorage,
};
type Block = pezframe_system::mocking::MockBlock<Test>;
construct_runtime!(
pub enum Test
{
System: pezframe_system,
Balances: pezpallet_balances,
Assets: pezpallet_assets,
PezTreasury: pezpallet_pez_treasury,
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
}
impl pezframe_system::Config for Test {
type BaseCallFilter = pezframe_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = pezframe_support::weights::constants::RocksDbWeight;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = H256; // V3: u64 -> H256 değişti
type Lookup = IdentityLookup<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pezpallet_balances::AccountData<u128>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = ConstU32<16>;
type SingleBlockMigrations = ();
type MultiBlockMigrator = ();
type PreInherents = ();
type PostInherents = ();
type PostTransactions = ();
type RuntimeTask = ();
type ExtensionsWeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = 1;
}
impl pezpallet_balances::Config for Test {
type MaxLocks = ();
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type Balance = u128;
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = ();
type FreezeIdentifier = ();
type MaxFreezes = ();
type RuntimeHoldReason = ();
type RuntimeFreezeReason = ();
type DoneSlashHandler = ();
}
parameter_types! {
pub const AssetDeposit: u128 = 100;
pub const ApprovalDeposit: u128 = 1;
pub const StringLimit: u32 = 50;
pub const MetadataDepositBase: u128 = 10;
pub const MetadataDepositPerByte: u128 = 1;
}
impl pezpallet_assets::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Balance = u128;
type AssetId = u32;
type AssetIdParameter = u32;
type Currency = Balances;
type CreateOrigin =
pezframe_support::traits::AsEnsureOriginWithArg<pezframe_system::EnsureSigned<Self::AccountId>>;
type ForceOrigin = pezframe_system::EnsureRoot<Self::AccountId>;
type AssetDeposit = AssetDeposit;
type AssetAccountDeposit = ConstU128<0>;
type MetadataDepositBase = MetadataDepositBase;
type MetadataDepositPerByte = MetadataDepositPerByte;
type ApprovalDeposit = ApprovalDeposit;
type StringLimit = StringLimit;
type Freezer = ();
type Extra = ();
type CallbackHandle = ();
type WeightInfo = ();
type RemoveItemsLimit = ConstU32<1000>;
type Holder = ();
type ReserveData = ();
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}
// CRITICAL: Bu üç PalletId FARKLI olmak ZORUNDA
parameter_types! {
pub const PezTreasuryPalletId: PalletId = PalletId(*b"py/pztrs");
pub const PezIncentivePotId: PalletId = PalletId(*b"py/pzinc");
pub const PezGovernmentPotId: PalletId = PalletId(*b"py/pzgov");
pub const PezAssetId: u32 = 1;
}
// V3: Test accounts - H256 formatında
use pezsp_runtime::traits::AccountIdConversion;
pub fn alice() -> H256 {
H256::from_low_u64_be(1)
}
pub fn bob() -> H256 {
H256::from_low_u64_be(2)
}
pub fn charlie() -> H256 {
H256::from_low_u64_be(3)
}
pub fn presale() -> H256 {
H256::from_low_u64_be(10)
}
pub fn founder() -> H256 {
H256::from_low_u64_be(11)
}
parameter_types! {
pub PresaleAccount: H256 = presale();
pub FounderAccount: H256 = founder();
}
impl pezpallet_pez_treasury::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Assets = Assets;
type WeightInfo = ();
type PezAssetId = PezAssetId;
type TreasuryPalletId = PezTreasuryPalletId;
type IncentivePotId = PezIncentivePotId;
type GovernmentPotId = PezGovernmentPotId;
type PresaleAccount = PresaleAccount;
type FounderAccount = FounderAccount;
type ForceOrigin = pezframe_system::EnsureRoot<Self::AccountId>;
}
// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> pezsp_io::TestExternalities {
let mut t = pezframe_system::GenesisConfig::<Test>::default().build_storage().unwrap();
pezpallet_balances::GenesisConfig::<Test> {
balances: vec![
(alice(), 1_000_000_000_000_000),
(bob(), 1_000_000_000_000_000),
(charlie(), 1_000_000_000_000_000),
(presale(), 1_000_000_000_000_000),
(founder(), 1_000_000_000_000_000),
],
dev_accounts: None,
}
.assimilate_storage(&mut t)
.unwrap();
let mut ext = pezsp_io::TestExternalities::new(t);
ext.execute_with(|| {
System::set_block_number(1);
// Create PEZ asset
assert_ok!(Assets::force_create(
RuntimeOrigin::root(),
PezAssetId::get(),
alice(),
true,
1
));
});
ext
}
// Helper function to run to specific block
pub fn run_to_block(n: u64) {
while System::block_number() < n {
if System::block_number() > 1 {
AllPalletsWithSystem::on_finalize(System::block_number());
}
System::set_block_number(System::block_number() + 1);
AllPalletsWithSystem::on_initialize(System::block_number());
}
}
// V3: Helper to assert balance - H256 account ile
pub fn assert_pez_balance(account: H256, expected: u128) {
assert_eq!(
Assets::balance(PezAssetId::get(), account),
expected,
"PEZ balance mismatch for account {:?}. Expected: {}, Got: {}",
account,
expected,
Assets::balance(PezAssetId::get(), account)
);
}
// V3: Helper fonksiyonlar - H256 dönüyor
#[allow(dead_code)]
pub fn treasury_account() -> H256 {
PezTreasuryPalletId::get().into_account_truncating()
}
#[allow(dead_code)]
pub fn incentive_pot_account() -> H256 {
PezIncentivePotId::get().into_account_truncating()
}
#[allow(dead_code)]
pub fn government_pot_account() -> H256 {
PezGovernmentPotId::get().into_account_truncating()
}
// V3: Debug helper
#[allow(dead_code)]
pub fn debug_pot_accounts() {
println!("\n=== PalletId Debug ===");
println!("Treasury bytes: {:?}", PezTreasuryPalletId::get().0);
println!("Incentive bytes: {:?}", PezIncentivePotId::get().0);
println!("Government bytes: {:?}", PezGovernmentPotId::get().0);
println!("======================\n");
}
@@ -0,0 +1,969 @@
// pezkuwi/pallets/pez-treasury/src/tests.rs
use crate::{mock::*, Error, Event};
use pezframe_support::{assert_noop, assert_ok};
use pezsp_runtime::traits::Zero; // FIXED: Import Zero trait for is_zero() method
// =============================================================================
// 1. GENESIS DISTRIBUTION TESTS
// =============================================================================
#[test]
fn genesis_distribution_works() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
let treasury_amount = 4_812_500_000 * 1_000_000_000_000u128;
let presale_amount = 93_750_000 * 1_000_000_000_000u128;
let founder_amount = 93_750_000 * 1_000_000_000_000u128;
assert_pez_balance(treasury_account(), treasury_amount);
assert_pez_balance(presale(), presale_amount);
assert_pez_balance(founder(), founder_amount);
let total = treasury_amount + presale_amount + founder_amount;
assert_eq!(total, 5_000_000_000 * 1_000_000_000_000u128);
System::assert_has_event(
Event::GenesisDistributionCompleted { treasury_amount, presale_amount, founder_amount }
.into(),
);
});
}
#[test]
fn force_genesis_distribution_requires_root() {
new_test_ext().execute_with(|| {
assert_noop!(
PezTreasury::force_genesis_distribution(RuntimeOrigin::signed(alice())),
pezsp_runtime::DispatchError::BadOrigin
);
});
}
#[test]
fn force_genesis_distribution_works_with_root() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::force_genesis_distribution(RuntimeOrigin::root()));
assert!(Assets::balance(PezAssetId::get(), treasury_account()) > 0);
assert!(Assets::balance(PezAssetId::get(), presale()) > 0);
assert!(Assets::balance(PezAssetId::get(), founder()) > 0);
});
}
#[test]
fn genesis_distribution_can_only_happen_once() {
new_test_ext().execute_with(|| {
// First call should succeed
assert_ok!(PezTreasury::do_genesis_distribution());
// Verify flag is set
assert!(PezTreasury::genesis_distribution_done());
// Second call should fail
assert_noop!(
PezTreasury::do_genesis_distribution(),
Error::<Test>::GenesisDistributionAlreadyDone
);
// Verify balances didn't double
let treasury_amount = 4_812_500_000 * 1_000_000_000_000u128;
assert_pez_balance(treasury_account(), treasury_amount);
});
}
// =============================================================================
// 2. TREASURY INITIALIZATION TESTS
// =============================================================================
#[test]
fn initialize_treasury_works() {
new_test_ext().execute_with(|| {
let start_block = System::block_number();
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Verify storage
assert_eq!(PezTreasury::treasury_start_block(), Some(start_block));
let halving_info = PezTreasury::halving_info();
assert_eq!(halving_info.current_period, 0);
assert_eq!(halving_info.period_start_block, start_block);
assert!(!halving_info.monthly_amount.is_zero());
// Verify next release month
assert_eq!(PezTreasury::next_release_month(), 0);
// Verify event
System::assert_has_event(
Event::TreasuryInitialized {
start_block,
initial_monthly_amount: halving_info.monthly_amount,
}
.into(),
);
});
}
#[test]
fn initialize_treasury_fails_if_already_initialized() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Try to initialize again
assert_noop!(
PezTreasury::initialize_treasury(RuntimeOrigin::root()),
Error::<Test>::TreasuryAlreadyInitialized
);
});
}
#[test]
fn initialize_treasury_requires_root() {
new_test_ext().execute_with(|| {
assert_noop!(
PezTreasury::initialize_treasury(RuntimeOrigin::signed(alice())),
pezsp_runtime::DispatchError::BadOrigin
);
});
}
#[test]
fn initialize_treasury_calculates_correct_monthly_amount() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let halving_info = PezTreasury::halving_info();
// First period total = 96.25% / 2 = 48.125%
let treasury_total = 4_812_500_000 * 1_000_000_000_000u128;
let first_period = treasury_total / 2;
let expected_monthly = first_period / 48; // 48 months
assert_eq!(halving_info.monthly_amount, expected_monthly);
});
}
// =============================================================================
// 3. MONTHLY RELEASE TESTS
// =============================================================================
#[test]
fn release_monthly_funds_works() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial_monthly = PezTreasury::halving_info().monthly_amount;
let incentive_expected = initial_monthly * 75 / 100;
let government_expected = initial_monthly - incentive_expected;
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert_pez_balance(PezTreasury::incentive_pot_account_id(), incentive_expected);
assert_pez_balance(PezTreasury::government_pot_account_id(), government_expected);
assert_eq!(PezTreasury::next_release_month(), 1);
let halving_info = PezTreasury::halving_info();
assert_eq!(halving_info.total_released, initial_monthly);
});
}
#[test]
fn release_monthly_funds_fails_if_not_initialized() {
new_test_ext().execute_with(|| {
assert_noop!(
PezTreasury::release_monthly_funds(RuntimeOrigin::root()),
Error::<Test>::TreasuryNotInitialized
);
});
}
#[test]
fn release_monthly_funds_fails_if_too_early() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Try to release before time
run_to_block(100);
assert_noop!(
PezTreasury::release_monthly_funds(RuntimeOrigin::root()),
Error::<Test>::ReleaseTooEarly
);
});
}
#[test]
fn release_monthly_funds_fails_if_already_released() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Try to release same month again
assert_noop!(
PezTreasury::release_monthly_funds(RuntimeOrigin::root()),
Error::<Test>::ReleaseTooEarly
);
});
}
#[test]
fn release_monthly_funds_splits_correctly() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let monthly_amount = PezTreasury::halving_info().monthly_amount;
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
let incentive_balance =
Assets::balance(PezAssetId::get(), PezTreasury::incentive_pot_account_id());
let government_balance =
Assets::balance(PezAssetId::get(), PezTreasury::government_pot_account_id());
// 75% to incentive, 25% to government
assert_eq!(incentive_balance, monthly_amount * 75 / 100);
// lib.rs'deki mantıkla aynı olmalı (saturating_sub)
let incentive_amount_calculated = monthly_amount * 75 / 100;
assert_eq!(government_balance, monthly_amount - incentive_amount_calculated);
// Total should equal monthly amount
assert_eq!(incentive_balance + government_balance, monthly_amount);
});
}
#[test]
fn multiple_monthly_releases_work() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let monthly_amount = PezTreasury::halving_info().monthly_amount;
// Release month 0
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert_eq!(PezTreasury::next_release_month(), 1);
// Release month 1
run_to_block(864_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert_eq!(PezTreasury::next_release_month(), 2);
// Release month 2
run_to_block(1_296_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert_eq!(PezTreasury::next_release_month(), 3);
// Verify total released
let halving_info = PezTreasury::halving_info();
assert_eq!(halving_info.total_released, monthly_amount * 3);
});
}
// =============================================================================
// 4. HALVING LOGIC TESTS
// =============================================================================
#[test]
fn halving_occurs_after_48_months() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial_monthly = PezTreasury::halving_info().monthly_amount;
// Release 47 months (no halving yet)
for month in 0..47 {
run_to_block(1 + (month + 1) * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
}
// Still period 0
assert_eq!(PezTreasury::halving_info().current_period, 0);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_monthly);
// Release 48th month - halving should occur
run_to_block(1 + 48 * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Now in period 1 with halved amount
let halving_info = PezTreasury::halving_info();
assert_eq!(halving_info.current_period, 1);
assert_eq!(halving_info.monthly_amount, initial_monthly / 2);
// Verify event
System::assert_has_event(
Event::NewHalvingPeriod { period: 1, new_monthly_amount: initial_monthly / 2 }.into(),
);
});
}
#[test]
fn multiple_halvings_work() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial_monthly = PezTreasury::halving_info().monthly_amount;
// First halving at month 48
run_to_block(1 + 48 * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert_eq!(PezTreasury::halving_info().current_period, 1);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_monthly / 2);
// Second halving at month 96
run_to_block(1 + 96 * 432_000 + 1);
for _ in 49..=96 {
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
}
assert_eq!(PezTreasury::halving_info().current_period, 2);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_monthly / 4);
// Third halving at month 144
run_to_block(1 + 144 * 432_000 + 1);
for _ in 97..=144 {
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
}
assert_eq!(PezTreasury::halving_info().current_period, 3);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_monthly / 8);
});
}
#[test]
fn halving_period_start_block_updates() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let period_0_start = PezTreasury::halving_info().period_start_block;
// Trigger halving
run_to_block(1 + 48 * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
let period_1_start = PezTreasury::halving_info().period_start_block;
assert!(period_1_start > period_0_start);
assert_eq!(period_1_start, System::block_number());
});
}
// =============================================================================
// 5. ERROR CASES
// =============================================================================
#[test]
fn insufficient_treasury_balance_error() {
new_test_ext().execute_with(|| {
// Initialize without genesis distribution (treasury empty)
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
run_to_block(432_001);
// This should fail due to insufficient balance
assert_noop!(
PezTreasury::release_monthly_funds(RuntimeOrigin::root()),
Error::<Test>::InsufficientTreasuryBalance
);
});
}
#[test]
fn release_requires_root_origin() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
run_to_block(432_001);
assert_noop!(
PezTreasury::release_monthly_funds(RuntimeOrigin::signed(alice())),
pezsp_runtime::DispatchError::BadOrigin
);
});
}
// =============================================================================
// 6. EDGE CASES
// =============================================================================
#[test]
fn release_exactly_at_boundary_block_fails() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Tam 432_000. blok (start_block=1 olduğu için) 431_999 blok geçti demektir.
// Bu, 1 tam ay (432_000 blok) değildir.
run_to_block(432_000);
assert_noop!(
PezTreasury::release_monthly_funds(RuntimeOrigin::root()),
Error::<Test>::ReleaseTooEarly
);
});
}
#[test]
fn release_one_block_before_boundary_fails() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
run_to_block(432_000 - 1);
assert_noop!(
PezTreasury::release_monthly_funds(RuntimeOrigin::root()),
Error::<Test>::ReleaseTooEarly
);
});
}
#[test]
fn skip_months_and_release() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Skip directly to month 3
run_to_block(1 + 3 * 432_000 + 1);
// Should release month 0
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert_eq!(PezTreasury::next_release_month(), 1);
// Can still release subsequent months
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert_eq!(PezTreasury::next_release_month(), 2);
});
}
#[test]
fn very_large_block_number() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Jump to very large block number
System::set_block_number(u64::MAX / 2);
// Should still be able to release (if months passed)
// This tests overflow protection
let result = PezTreasury::release_monthly_funds(RuntimeOrigin::root());
// Result depends on whether enough months passed
// Main point: no panic/overflow
assert!(result.is_ok() || result.is_err());
});
}
#[test]
fn zero_amount_division_protection() {
new_test_ext().execute_with(|| {
// Initialize without any balance
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let halving_info = PezTreasury::halving_info();
// Should not panic, should have some calculated amount
assert!(!halving_info.monthly_amount.is_zero());
});
}
// =============================================================================
// 7. GETTER FUNCTIONS TESTS
// =============================================================================
#[test]
fn get_current_halving_info_works() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let info = PezTreasury::get_current_halving_info();
assert_eq!(info.current_period, 0);
assert!(!info.monthly_amount.is_zero());
assert_eq!(info.total_released, 0);
});
}
#[test]
fn get_incentive_pot_balance_works() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
let balance = PezTreasury::get_incentive_pot_balance();
assert!(balance > 0);
});
}
#[test]
fn get_government_pot_balance_works() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
let balance = PezTreasury::get_government_pot_balance();
assert!(balance > 0);
});
}
// =============================================================================
// 8. ACCOUNT ID TESTS
// =============================================================================
#[test]
fn treasury_account_id_is_consistent() {
new_test_ext().execute_with(|| {
let account1 = PezTreasury::treasury_account_id();
let account2 = PezTreasury::treasury_account_id();
assert_eq!(account1, account2);
});
}
#[test]
fn pot_accounts_are_different() {
new_test_ext().execute_with(|| {
debug_pot_accounts();
let treasury = PezTreasury::treasury_account_id();
let incentive = PezTreasury::incentive_pot_account_id();
let government = PezTreasury::government_pot_account_id();
println!("\n=== Account IDs from Pallet ===");
println!("Treasury: {:?}", treasury);
println!("Incentive: {:?}", incentive);
println!("Government: {:?}", government);
println!("================================\n");
// Tüm üçü farklı olmalı
assert_ne!(treasury, incentive, "Treasury and Incentive must be different");
assert_ne!(treasury, government, "Treasury and Government must be different");
assert_ne!(incentive, government, "Incentive and Government must be different");
println!("✓ All pot accounts are different!");
});
}
// =============================================================================
// 9. MONTHLY RELEASE STORAGE TESTS
// =============================================================================
#[test]
fn monthly_release_records_stored_correctly() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let monthly_amount = PezTreasury::halving_info().monthly_amount;
let incentive_expected = monthly_amount * 75 / 100;
let government_expected = monthly_amount - incentive_expected;
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Verify monthly release record
let release = PezTreasury::monthly_releases(0).unwrap();
assert_eq!(release.month_index, 0);
assert_eq!(release.amount_released, monthly_amount);
assert_eq!(release.incentive_amount, incentive_expected);
assert_eq!(release.government_amount, government_expected);
assert_eq!(release.release_block, System::block_number());
});
}
#[test]
fn multiple_monthly_releases_stored_separately() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Release month 0
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Release month 1
run_to_block(864_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Verify both records exist
assert!(PezTreasury::monthly_releases(0).is_some());
assert!(PezTreasury::monthly_releases(1).is_some());
let release_0 = PezTreasury::monthly_releases(0).unwrap();
let release_1 = PezTreasury::monthly_releases(1).unwrap();
assert_eq!(release_0.month_index, 0);
assert_eq!(release_1.month_index, 1);
assert_ne!(release_0.release_block, release_1.release_block);
});
}
// =============================================================================
// 10. INTEGRATION TESTS
// =============================================================================
#[test]
fn full_lifecycle_test() {
new_test_ext().execute_with(|| {
// 1. Genesis distribution
assert_ok!(PezTreasury::do_genesis_distribution());
let treasury_initial = Assets::balance(PezAssetId::get(), treasury_account());
assert!(treasury_initial > 0);
// 2. Initialize treasury
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let monthly_amount = PezTreasury::halving_info().monthly_amount;
// 3. Release first month
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
let treasury_after_month_0 = Assets::balance(PezAssetId::get(), treasury_account());
assert_eq!(treasury_initial - treasury_after_month_0, monthly_amount);
// 4. Release multiple months
for month in 1..10 {
run_to_block(1 + (month + 1) * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
}
// 5. Verify cumulative release
let halving_info = PezTreasury::halving_info();
assert_eq!(halving_info.total_released, monthly_amount * 10);
// 6. Verify treasury balance decreased correctly
let treasury_after_10_months = Assets::balance(PezAssetId::get(), treasury_account());
assert_eq!(treasury_initial - treasury_after_10_months, monthly_amount * 10);
});
}
#[test]
fn full_halving_cycle_test() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial_monthly = PezTreasury::halving_info().monthly_amount;
let mut cumulative_released = 0u128;
// Period 0: 48 months at initial rate
for month in 0..48 {
run_to_block(1 + (month + 1) * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
if month < 47 {
cumulative_released += initial_monthly;
} else {
// 48. sürümde (index 47) halving tetiklenir ve yarı tutar kullanılır
cumulative_released += initial_monthly / 2;
}
}
assert_eq!(PezTreasury::halving_info().current_period, 1);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_monthly / 2);
// Period 1: 48 months at half rate
for month in 48..96 {
run_to_block(1 + (month + 1) * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
if month < 95 {
cumulative_released += initial_monthly / 2;
} else {
// 96. sürümde (index 95) ikinci halving tetiklenir
cumulative_released += initial_monthly / 4;
}
}
assert_eq!(PezTreasury::halving_info().current_period, 2);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_monthly / 4);
// Verify total released matches expectation
assert_eq!(PezTreasury::halving_info().total_released, cumulative_released);
});
}
// =============================================================================
// 11. PRECISION AND ROUNDING TESTS
// =============================================================================
#[test]
fn division_rounding_is_consistent() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let monthly_amount = PezTreasury::halving_info().monthly_amount;
let incentive_amount = monthly_amount * 75 / 100;
let government_amount = monthly_amount - incentive_amount;
// Verify no rounding loss
assert_eq!(incentive_amount + government_amount, monthly_amount);
});
}
#[test]
fn halving_precision_maintained() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial = PezTreasury::halving_info().monthly_amount;
// Trigger halving
run_to_block(1 + 48 * 432_000 + 1);
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
let after_halving = PezTreasury::halving_info().monthly_amount;
// Check halving is exactly half (no precision loss)
assert_eq!(after_halving, initial / 2);
});
}
// =============================================================================
// 12. EVENT EMISSION TESTS
// =============================================================================
#[test]
fn all_events_emitted_correctly() {
new_test_ext().execute_with(|| {
// Genesis distribution event
assert_ok!(PezTreasury::do_genesis_distribution());
assert!(System::events().iter().any(|e| matches!(
e.event,
RuntimeEvent::PezTreasury(Event::GenesisDistributionCompleted { .. })
)));
// Treasury initialized event
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
assert!(System::events().iter().any(|e| matches!(
e.event,
RuntimeEvent::PezTreasury(Event::TreasuryInitialized { .. })
)));
// Monthly funds released event
run_to_block(432_001);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
assert!(System::events().iter().any(|e| matches!(
e.event,
RuntimeEvent::PezTreasury(Event::MonthlyFundsReleased { .. })
)));
});
}
#[test]
fn halving_event_emitted_at_correct_time() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Clear existing events
System::reset_events();
// Release up to halving point
run_to_block(1 + 48 * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Verify halving event emitted
assert!(System::events().iter().any(|e| matches!(
e.event,
RuntimeEvent::PezTreasury(Event::NewHalvingPeriod { period: 1, .. })
)));
});
}
// =============================================================================
// 13. STRESS TESTS
// =============================================================================
#[test]
fn many_consecutive_releases() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
// Release 100 months consecutively
for month in 0..100 {
run_to_block(1 + (month + 1) * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
}
// Verify state is consistent
assert_eq!(PezTreasury::next_release_month(), 100);
// Should be in period 2 (after 2 halvings at months 48 and 96)
assert_eq!(PezTreasury::halving_info().current_period, 2);
});
}
#[test]
fn treasury_never_goes_negative() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let _initial_balance = Assets::balance(PezAssetId::get(), treasury_account()); // FIXED: Prefixed with underscore
// Try to release many months
for month in 0..200 {
run_to_block(1 + (month + 1) * 432_000 + 1);
let before_balance = Assets::balance(PezAssetId::get(), treasury_account());
let result = PezTreasury::release_monthly_funds(RuntimeOrigin::root());
if result.is_ok() {
let after_balance = Assets::balance(PezAssetId::get(), treasury_account());
// Balance should decrease or stay the same, never increase
assert!(after_balance <= before_balance);
// Balance should never go below zero
assert!(after_balance >= 0);
} else {
// If release fails, balance should be unchanged
assert_eq!(before_balance, Assets::balance(PezAssetId::get(), treasury_account()));
break;
}
}
});
}
// =============================================================================
// 14. BOUNDARY CONDITION TESTS
// =============================================================================
#[test]
fn first_block_initialization() {
new_test_ext().execute_with(|| {
System::set_block_number(1);
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
assert_eq!(PezTreasury::treasury_start_block(), Some(1));
});
}
#[test]
fn last_month_of_period_before_halving() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial_amount = PezTreasury::halving_info().monthly_amount;
// Release month 47 (last before halving)
run_to_block(1 + 47 * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Should still be in period 0
assert_eq!(PezTreasury::halving_info().current_period, 0);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_amount);
});
}
#[test]
fn first_month_after_halving() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial_amount = PezTreasury::halving_info().monthly_amount;
// Trigger halving at month 48
run_to_block(1 + 48 * 432_000 + 1);
assert_ok!(PezTreasury::release_monthly_funds(RuntimeOrigin::root()));
// Should be in period 1 with halved amount
assert_eq!(PezTreasury::halving_info().current_period, 1);
assert_eq!(PezTreasury::halving_info().monthly_amount, initial_amount / 2);
});
}
// =============================================================================
// 15. MATHEMATICAL CORRECTNESS TESTS
// =============================================================================
#[test]
fn total_supply_equals_sum_of_allocations() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
let treasury = Assets::balance(PezAssetId::get(), treasury_account());
let presale_acc = Assets::balance(PezAssetId::get(), presale());
let founder_acc = Assets::balance(PezAssetId::get(), founder());
let total = treasury + presale_acc + founder_acc;
let expected_total = 5_000_000_000 * 1_000_000_000_000u128;
assert_eq!(total, expected_total);
});
}
#[test]
fn percentage_allocations_correct() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
let total_supply = 5_000_000_000 * 1_000_000_000_000u128;
let treasury = Assets::balance(PezAssetId::get(), treasury_account());
let presale_acc = Assets::balance(PezAssetId::get(), presale());
let founder_acc = Assets::balance(PezAssetId::get(), founder());
assert_eq!(treasury, total_supply * 9625 / 10000);
assert_eq!(presale_acc, total_supply * 1875 / 100000);
assert_eq!(founder_acc, total_supply * 1875 / 100000);
});
}
#[test]
fn first_period_total_is_half_of_treasury() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::do_genesis_distribution());
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let monthly_amount = PezTreasury::halving_info().monthly_amount;
let first_period_total = monthly_amount * 48;
let treasury_allocation = 4_812_500_000 * 1_000_000_000_000u128;
let expected_first_period = treasury_allocation / 2;
let diff = expected_first_period.saturating_sub(first_period_total);
// Kalanların toplamı 48'den az olmalı (her ay en fazla 1 birim kalan)
assert!(diff < 48, "Rounding error too large: {}", diff);
});
}
#[test]
fn geometric_series_sum_validates() {
new_test_ext().execute_with(|| {
assert_ok!(PezTreasury::initialize_treasury(RuntimeOrigin::root()));
let initial_monthly = PezTreasury::halving_info().monthly_amount;
// Sum of geometric series: a(1 - r^n) / (1 - r)
// For halving: first_period * (1 - 0.5^n) / 0.5
// With infinite halvings approaches: first_period * 2
let first_period_total = initial_monthly * 48;
let treasury_allocation = 4_812_500_000 * 1_000_000_000_000u128;
// After infinite halvings, total distributed = treasury_allocation
// first_period_total * 2 = treasury_allocation
let diff = treasury_allocation.saturating_sub(first_period_total * 2);
// Kalanların toplamı (2 ile çarpılmış) 96'dan az olmalı
assert!(diff < 96, "Rounding error too large: {}", diff);
});
}
@@ -0,0 +1,106 @@
//! Autogenerated weights for `pezpallet_pez_treasury`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE BIZINIKIWI BENCHMARK CLI VERSION 32.0.0
//! DATE: 2025-12-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `MamostePC`, CPU: `11th Gen Intel(R) Core(TM) i9-11950H @ 2.60GHz`
//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024
// Executed Command:
// ./target/release/frame-omni-bencher
// v1
// benchmark
// pallet
// --runtime
// ./target/release/wbuild/asset-hub-pezkuwichain-runtime/asset_hub_pezkuwichain_runtime.wasm
// --pallet
// pezpallet_pez_treasury
// --extrinsic
// *
// --steps
// 50
// --repeat
// 20
// --output
// ./pezcumulus/teyrchains/pezpallets/pez-treasury/src/weights.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use pezframe_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions needed for `pezpallet_pez_treasury`.
pub trait WeightInfo {
fn initialize_treasury() -> Weight;
fn force_genesis_distribution() -> Weight;
fn release_monthly_funds() -> Weight;
}
/// Weight functions for `pezpallet_pez_treasury`.
pub struct BizinikiwiWeight<T>(PhantomData<T>);
impl<T: pezframe_system::Config> WeightInfo for BizinikiwiWeight<T> {
/// Storage: `PezTreasury::TreasuryStartBlock` (r:1 w:1)
/// Proof: `PezTreasury::TreasuryStartBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `PezTreasury::NextReleaseMonth` (r:0 w:1)
/// Proof: `PezTreasury::NextReleaseMonth` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `PezTreasury::HalvingInfo` (r:0 w:1)
/// Proof: `PezTreasury::HalvingInfo` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`)
fn initialize_treasury() -> Weight {
// Proof Size summary in bytes:
// Measured: `3`
// Estimated: `1489`
// Minimum execution time: 7_724_000 picoseconds.
Weight::from_parts(8_079_000, 0)
.saturating_add(Weight::from_parts(0, 1489))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: `PezTreasury::GenesisDistributionDone` (r:1 w:1)
/// Proof: `PezTreasury::GenesisDistributionDone` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`)
/// Storage: `Assets::Asset` (r:1 w:1)
/// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
/// Storage: `Assets::Account` (r:3 w:3)
/// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:3 w:3)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn force_genesis_distribution() -> Weight {
// Proof Size summary in bytes:
// Measured: `489`
// Estimated: `8817`
// Minimum execution time: 62_294_000 picoseconds.
Weight::from_parts(64_751_000, 0)
.saturating_add(Weight::from_parts(0, 8817))
.saturating_add(T::DbWeight::get().reads(8))
.saturating_add(T::DbWeight::get().writes(8))
}
/// Storage: `PezTreasury::TreasuryStartBlock` (r:1 w:0)
/// Proof: `PezTreasury::TreasuryStartBlock` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `PezTreasury::NextReleaseMonth` (r:1 w:1)
/// Proof: `PezTreasury::NextReleaseMonth` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
/// Storage: `PezTreasury::MonthlyReleases` (r:1 w:1)
/// Proof: `PezTreasury::MonthlyReleases` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`)
/// Storage: `PezTreasury::HalvingInfo` (r:1 w:1)
/// Proof: `PezTreasury::HalvingInfo` (`max_values`: Some(1), `max_size`: Some(40), added: 535, mode: `MaxEncodedLen`)
/// Storage: `Assets::Asset` (r:1 w:1)
/// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(210), added: 2685, mode: `MaxEncodedLen`)
/// Storage: `Assets::Account` (r:3 w:3)
/// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(134), added: 2609, mode: `MaxEncodedLen`)
/// Storage: `AssetsFreezer::FrozenBalances` (r:1 w:0)
/// Proof: `AssetsFreezer::FrozenBalances` (`max_values`: None, `max_size`: Some(84), added: 2559, mode: `MaxEncodedLen`)
/// Storage: `System::Account` (r:2 w:2)
/// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`)
fn release_monthly_funds() -> Weight {
// Proof Size summary in bytes:
// Measured: `701`
// Estimated: `8817`
// Minimum execution time: 103_894_000 picoseconds.
Weight::from_parts(109_089_000, 0)
.saturating_add(Weight::from_parts(0, 8817))
.saturating_add(T::DbWeight::get().reads(11))
.saturating_add(T::DbWeight::get().writes(9))
}
}