Rust区块链薪资管理模块pallet-salary的使用,pallet-salary提供去中心化薪资发放与财务追踪功能

Rust区块链薪资管理模块pallet-salary的使用

pallet-salary是一个Substrate模块,用于根据等级定期向集体成员支付薪资。

安装

在项目目录中运行以下Cargo命令:

cargo add pallet-salary

或者在Cargo.toml中添加以下行:

pallet-salary = "26.0.0"

示例代码

以下是一个完整的pallet-salary使用示例:

// 导入必要的模块
use frame_support::{parameter_types, traits::Currency};
use pallet_salary as salary;
use sp_runtime::Perbill;

// 定义货币类型
pub type Balance = u128;
pub type AccountId = u64;

parameter_types! {
    pub const SalaryPeriod: u64 = 30 * 24 * 60 * 60; // 30天(秒)
    pub const SalaryBudget: Balance = 1_000_000; // 总预算
    pub const SalaryPayoutFraction: Perbill = Perbill::from_percent(100); // 支付比例
}

// 配置薪资模块
impl salary::Config for Runtime {
    type Event = Event;
    type WeightInfo = ();
    type Currency = Balances; // 使用balances模块作为货币
    type Paymaster = Treasury; // 使用国库作为支付者
    type Members = Membership; // 成员资格模块
    type Salary = FixedSalary; // 固定薪资类型
    type Period = SalaryPeriod;
    type Budget = SalaryBudget;
    type PayoutFraction = SalaryPayoutFraction;
}

// 固定薪资实现
pub struct FixedSalary;
impl salary::Salary<AccountId, Balance> for FixedSalary {
    fn get_salary(who: &AccountId, rank: u16) -> Balance {
        match rank {
            1 => 10_000, // 等级1薪资
            2 => 20_000, // 等级2薪资
            3 => 30_000, // 等级3薪资
            _ => 5_000,  // 默认薪资
        }
    }
}

// 在runtime中集成模块
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        // ...其他模块
        Salary: salary::{Module, Call, Storage, Event<T>},
    }
);

// 使用示例 - 注册成员
fn register_member(account: AccountId, rank: u16) {
    // 注册成员到成员资格模块
    Membership::add_member(account);
    // 设置成员等级
    Salary::set_rank(Origin::signed(account), rank);
}

// 使用示例 - 发放薪资
fn payout_salaries() {
    // 通常由链上调度器定期调用
    Salary::payout_salaries(Origin::none());
}

功能说明

  1. 定期支付:根据设定的周期(如30天)自动发放薪资
  2. 等级薪资:不同等级成员获得不同数额的薪资
  3. 预算控制:设置总预算限制,防止超额支付
  4. 财务追踪:所有薪资支付记录在链上可查

完整示例代码

//! 完整的pallet-salary实现示例

use frame_support::{
    construct_runtime, parameter_types,
    traits::{Currency, OnInitialize},
    weights::Weight,
};
use frame_system::EnsureRoot;
use pallet_balances as balances;
use pallet_salary as salary;
use pallet_treasury as treasury;
use sp_core::H256;
use sp_runtime::{
    testing::Header,
    traits::{BlakeTwo256, IdentityLookup},
    Perbill,
};

// 类型别名
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>;
type Block = frame_system::mocking::MockBlock<Runtime>;

// 构建测试运行时
construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
        Balances: balances::{Pallet, Call, Storage, Config<T>, Event<T>},
        Treasury: treasury::{Pallet, Call, Storage, Config, Event<T>},
        Salary: salary::{Pallet, Call, Storage, Event<T>},
    }
);

// 系统配置
parameter_types! {
    pub const BlockHashCount: u64 = 250;
    pub const SS58Prefix: u8 = 42;
}

impl frame_system::Config for Runtime {
    type BaseCallFilter = frame_support::traits::Everything;
    type BlockWeights = ();
    type BlockLength = ();
    type DbWeight = ();
    type RuntimeOrigin = RuntimeOrigin;
    type RuntimeCall = RuntimeCall;
    type Index = u64;
    type BlockNumber = u64;
    type Hash = H256;
    type Hashing = BlakeTwo256;
    type AccountId = u64;
    type Lookup = IdentityLookup<Self::AccountId>;
    type Header = Header;
    type RuntimeEvent = RuntimeEvent;
    type BlockHashCount = BlockHashCount;
    type Version = ();
    type PalletInfo = PalletInfo;
    type AccountData = balances::AccountData<u128>;
    type OnNewAccount = ();
    type OnKilledAccount = ();
    type SystemWeightInfo = ();
    type SS58Prefix = SS58Prefix;
    type OnSetCode = ();
    type MaxConsumers = frame_support::traits::ConstU32<16>;
}

// 余额模块配置
parameter_types! {
    pub const ExistentialDeposit: u128 = 1;
    pub const MaxLocks: u32 = 50;
    pub const MaxReserves: u32 = 50;
}

impl balances::Config for Runtime {
    type Balance = u128;
    type DustRemoval = ();
    type RuntimeEvent = RuntimeEvent;
    type ExistentialDeposit = ExistentialDeposit;
    type AccountStore = System;
    type WeightInfo = ();
    type MaxLocks = MaxLocks;
    type MaxReserves = MaxReserves;
    type ReserveIdentifier = [u8; 8];
    type RuntimeHoldReason = ();
    type RuntimeFreezeReason = ();
    type FreezeIdentifier = ();
    type MaxHolds = ();
    type MaxFreezes = ();
}

// 国库模块配置
parameter_types! {
    pub const ProposalBond: Permill = Permill::from_percent(5);
    pub const ProposalBondMinimum: u128 = 1;
    pub const SpendPeriod: u64 = 2;
    pub const Burn: Permill = Permill::from_percent(50);
    pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
    pub const MaxApprovals: u32 = 100;
}

impl treasury::Config for Runtime {
    type PalletId = TreasuryPalletId;
    type Currency = Balances;
    type ApproveOrigin = EnsureRoot<u64>;
    type RejectOrigin = EnsureRoot<u64>;
    type RuntimeEvent = RuntimeEvent;
    type OnSlash = ();
    type ProposalBond = ProposalBond;
    type ProposalBondMinimum = ProposalBondMinimum;
    type SpendPeriod = SpendPeriod;
    type Burn = Burn;
    type BurnDestination = ();
    type SpendFunds = ();
    type WeightInfo = ();
    type MaxApprovals = MaxApprovals;
    type SpendOrigin = frame_support::traits::NeverEnsureOrigin<u128>;
}

// 薪资模块配置
parameter_types! {
    pub const SalaryPeriod: u64 = 30 * 24 * 60 * 60; // 30天(秒)
    pub const SalaryBudget: u128 = 1_000_000; // 总预算
    pub const SalaryPayoutFraction: Perbill = Perbill::from_percent(100); // 支付比例
}

// 简单的成员资格模块模拟
pub struct Membership;
impl salary::Membership<Runtime> for Membership {
    fn is_member(who: &u64) -> bool {
        // 实际应用中应从存储中查询
        *who == 1 || *who == 2 || *who == 3
    }

    fn add_member(who: &u64) {
        // 实际应用中应更新存储
        println!("Added member: {}", who);
    }
}

// 固定薪资实现
pub struct FixedSalary;
impl salary::Salary<u64, u128> for FixedSalary {
    fn get_salary(who: &u64, rank: u16) -> u128 {
        match rank {
            1 => 10_000, // 等级1薪资
            2 => 20_000, // 等级2薪资
            3 => 30_000, // 等级3薪资
            _ => 5_000,  // 默认薪资
        }
    }
}

impl salary::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type WeightInfo = ();
    type Currency = Balances;
    type Paymaster = Treasury;
    type Members = Membership;
    type Salary = FixedSalary;
    type Period = SalaryPeriod;
    type Budget = SalaryBudget;
    type PayoutFraction = SalaryPayoutFraction;
}

// 测试示例
#[test]
fn test_salary_payout() {
    // 初始化测试环境
    let mut t = frame_system::GenesisConfig::default()
        .build_storage::<Runtime>()
        .unwrap();
    
    balances::GenesisConfig::<Runtime> {
        balances: vec![
            // 给国库初始资金
            (1, 100_000_000),
        ],
    }
    .assimilate_storage(&mut t)
    .unwrap();

    let mut ext = sp_io::TestExternalities::new(t);
    ext.execute_with(|| {
        // 初始化区块
        System::set_block_number(1);
        
        // 注册成员
        Membership::add_member(&2); // 账户2
        Salary::set_rank(RuntimeOrigin::signed(2), 2).unwrap(); // 设置为等级2
        
        // 模拟时间流逝到薪资周期结束
        for _ in 0..SalaryPeriod::get() {
            System::set_block_number(System::block_number() + 1);
            Salary::on_initialize(System::block_number());
        }
        
        // 检查薪资是否发放
        assert_eq!(Balances::free_balance(&2), 20_000);
    });
}

功能说明

  1. 定期支付:根据设定的周期(如30天)自动发放薪资
  2. 等级薪资:不同等级成员获得不同数额的薪资
  3. 预算控制:设置总预算限制,防止超额支付
  4. 财务追踪:所有薪资支付记录在链上可查

1 回复

Rust区块链薪资管理模块pallet-salary使用指南

模块介绍

pallet-salary是Substrate框架中的一个功能模块,专门为区块链系统提供去中心化的薪资管理和财务追踪功能。它允许组织或DAO在区块链上透明地管理成员薪资发放、预算分配和财务记录。

主要功能

  1. 去中心化薪资发放
  2. 薪资周期管理
  3. 薪资预算分配与追踪
  4. 薪资支付记录
  5. 多币种支持

使用方法

1. 添加依赖

在项目的runtime/Cargo.toml中添加pallet-salary依赖:

[dependencies.pallet-salary]
default-features = false
git = 'https://github.com/substrate-developer-hub/substrate-node-template'
branch = 'latest'

2. 配置runtime

runtime/src/lib.rs中配置pallet-salary:

impl pallet_salary::Config for Runtime {
    type RuntimeEvent = RuntimeEvent;
    type Currency = Balances;
    type Paymaster = Treasury; // 使用国库作为支付账户
    type WeightInfo = ();
}

3. 初始化薪资系统

// 设置薪资周期(例如每月一次)
Salary::set_pay_period(30 * DAYS);

// 设置薪资预算
Salary::set_budget(1_000_000);

使用示例

1. 添加员工并设置薪资

// 添加员工并设置月薪
Salary::add_employee(employee_account, 5000);

// 更新员工薪资
Salary::update_salary(employee_account, 6000);

2. 发放薪资

// 管理员触发薪资发放
Salary::pay_salaries(origin);

3. 查询功能

// 查询员工薪资
let salary = Salary::employee_salary(employee_account);

// 查询当前薪资周期剩余预算
let remaining_budget = Salary::remaining_budget();

// 查询员工支付历史
let payment_history = Salary::payment_history(employee_account);

高级功能

多币种薪资

// 使用多币种支持
Salary::add_employee_with_currency(employee_account, 5000, CurrencyId::USD);

// 发放特定币种薪资
Salary::pay_salary_in_currency(employee_account, CurrencyId::USD);

薪资自动化

// 设置自动支付
Salary::enable_auto_pay(true);

// 设置自动支付阈值(当预算充足时自动支付)
Salary::set_auto_pay_threshold(800_000);

完整示例代码

//! 完整的薪资管理模块使用示例

use frame_support::{decl_module, dispatch::DispatchResult};
use frame_system::ensure_root;
use sp_runtime::traits::AccountIdConversion;

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
    use super::*;
    use frame_support::pallet_prelude::*;
    use frame_system::pallet_prelude::*;

    #[pallet::config]
    pub trait Config: frame_system::Config {
        type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
        type Currency: Currency<Self::AccountId>;
    }

    #[pallet::pallet]
    pub struct Pallet<T>(_);

    #[pallet::storage]
    #[pallet::getter(fn something)]
    pub type Something<T> = StorageValue<_, u32>;

    #[pallet::event]
    #[pallet::generate_deposit(pub(super) fn deposit_event)]
    pub enum Event<T: Config> {
        SalaryPaid(T::AccountId, u128),
        EmployeeAdded(T::AccountId, u128),
    }

    #[pallet::call]
    impl<T: Config> Pallet<T> {
        /// 添加新员工
        #[pallet::weight(10_000)]
        pub fn add_employee(origin: OriginFor<T>, employee: T::AccountId, salary: u128) -> DispatchResult {
            ensure_root(origin)?;
            
            // 实际实现中这里会调用pallet-salary的add_employee
            Self::deposit_event(Event::EmployeeAdded(employee, salary));
            Ok(())
        }

        /// 发放薪资
        #[pallet::weight(10_000)]
        pub fn pay_salary(origin: OriginFor<T>, employee: T::AccountId) -> DispatchResult {
            ensure_root(origin)?;
            
            // 实际实现中这里会调用pallet-salary的pay_salary
            Self::deposit_event(Event::SalaryPaid(employee, 5000)); // 示例固定金额
            Ok(())
        }
    }
}

// 运行时配置
pub struct Runtime;
impl frame_system::Config for Runtime {
    type AccountId = u64;
    type RuntimeCall = ();
    type RuntimeEvent = ();
    type RuntimeOrigin = ();
    type BlockNumber = u32;
}

impl pallet::Config for Runtime {
    type RuntimeEvent = ();
    type Currency = ();
}

最佳实践

  1. 定期检查薪资预算,避免资金不足
  2. 为敏感操作设置多重签名
  3. 利用区块链事件系统监听薪资支付事件
  4. 结合pallet-treasury实现更复杂的资金管理

注意事项

  • 确保支付账户有足够余额
  • 薪资周期设置应考虑区块链出块时间
  • 大规模员工系统可能需要优化存储结构

pallet-salary为区块链组织提供了透明、不可篡改的薪资管理解决方案,特别适合DAO、开源项目和其他去中心化组织的财务管理需求。

回到顶部