如何修改Substrate的Nicks Pallet:将昵称设置改为向指定账户转账付费
刚接触Substrate和Rust的时候改Pallet确实容易摸不着头绪,我来一步步带你把Nicks的「预留货币设昵称」改成「向Alice付费设昵称」——你已经fork好仓库了,接下来就按下面的步骤来~
步骤1:明确核心修改方向
Nicks Pallet原本的set函数是用Reserve机制锁定用户余额来实现昵称设置,我们要把这部分替换成直接向Alice转账的逻辑,同时调整移除昵称时的退款逻辑(毕竟钱已经转走了,不需要再退还)。
步骤2:修改
set函数的核心逻辑 找到你fork的Nicks Pallet里的src/lib.rs,定位到set可调用函数,把原来的预留代码换成转账逻辑:
#[pallet::call_index(0)] #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn set(origin: OriginFor<T>, name: Vec<u8>) -> DispatchResult { let who = ensure_signed(origin)?; // 校验昵称长度(保留原有逻辑) ensure!(name.len() <= T::MaxLength::get() as usize, Error::<T>::TooLong); // 替换原有的预留逻辑为转账给Alice let fee = T::ReservationFee::get(); // 硬编码Alice的默认账户ID([1u8;32]是Alice的标准AccountId32) let alice = AccountId32::from([1u8; 32]); // 执行转账,KeepAlive保证用户转账后账户不会被销毁 T::Currency::transfer(&who, &alice, fee, ExistenceRequirement::KeepAlive)?; // 更新昵称存储(原来的deposit字段现在可以存支付的费用,或者不需要的话可以修改存储结构) <NameOf<T>>::insert(&who, (name, fee)); Self::deposit_event(Event::NameSet { who }); Ok(()) }
注意:如果想以后灵活修改收款账户(比如不用硬编码Alice),可以在Pallet的Config trait里加一个关联类型type PaymentReceiver: Get<Self::AccountId>,然后在Runtime配置里指定收款账户就行。
步骤3:调整
clear函数的退款逻辑 原来的clear函数会把预留的余额还给用户,现在钱已经转给Alice了,所以直接删除昵称存储即可:
#[pallet::call_index(1)] #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn clear(origin: OriginFor<T>) -> DispatchResult { let who = ensure_signed(origin)?; // 移除原来的退款逻辑,直接删除昵称记录 <NameOf<T>>::take(&who).ok_or(Error::<T>::Unnamed)?; Self::deposit_event(Event::NameCleared { who }); Ok(()) }
步骤4:编译并测试
- 先单独编译Pallet:在fork的Nicks Pallet目录下运行
cargo build,确保没有编译错误。 - 回到你的Substrate项目根目录,编译整个Runtime:
cargo build --release。 - 启动本地节点,用Polkadot JS Apps连接后,调用
nicks.set函数测试:检查自己的余额是否减少,Alice的余额是否增加,昵称是否成功设置。
额外注意事项
- 确保导入了
sp_core::crypto::AccountId32,不然硬编码Alice的账户ID会报错。 - 如果你修改了Pallet的
Configtrait(比如加了PaymentReceiver),需要在你的Runtime的lib.rs里更新Nicks的配置,比如:impl pallet_nicks::Config for Runtime { type Event = Event; type Currency = Balances; type ReservationFee = ConstU128<1000>; // 自定义付费金额 type MaxLength = ConstU32<16>; type PaymentReceiver = ConstAccountId32<[1u8; 32]>; // 指定收款账户为Alice } - 如果要处理旧用户的预留数据(比如升级前已经设置昵称的用户),需要写存储迁移逻辑,把他们的预留余额直接转成已支付费用,或者退还后让他们重新付费设置。
内容的提问来源于stack exchange,提问作者Giovanni_Visione
相关产品推荐
相关产品推荐

