1

I'm planning to write a pallet to distribute token to many users in substrate blockchain (Ex: 500k-1m users). Should I do a for loop in a user list and transfer token to them? Do you have any example?

2
  • Is it a one-time job? Or a call that you could call it multiple times? Oct 5, 2022 at 17:41
  • I like one-time job than call it multiple times. Do you know the advantage/disadvantage of each way. Just wonder can we distribute token to 500k-1m users with one-time job? Oct 5, 2022 at 18:17

1 Answer 1

3

Both are easy to implement. But if it is an extrinsic call, you might need to pay more attention to the bandwidth/weight costs.


One-time job in migration way.

Find your Executive type in the runtime lib.rs and add a TokenDistribution:

pub type Executive = frame_executive::Executive<
    Runtime,
    Block,
    ChainContext<Runtime>,
    Runtime,
    AllPalletsWithSystem,
+   TokenDistribution,
>;

Define the struct TokenDistribution and implement OnRuntimeUpgrade for it:

use frame_support::traits::OnRuntimeUpgrade;

pub struct TokenDistribution;
impl OnRuntimeUpgrade for TokenDistribution {
    fn on_runtime_upgrade() -> Weight {
        let fund_account = x;
        let distribute_amount = y;

        load_user_list().into_iter().for_each(|user: AccountId| {
            // `Balances` is the pallet name of your `pallet-balances` 
            // instance which defines in the runtime `lib.rs`           
            Balances::transfer(
                Origin::signed(fund_account),
                user.into(),
                distribute_amount
            );
        });
        
        // Or you could calculate a more precise weight here
        RuntimeBlockWeights::get().max_block
    }
}

In the next runtime upgrade, the distribution will be applied.

I believe this is the cleanest way to do it.

And remember to remove these codes before the next-next runtime upgrade.

2
  • Can we do 500k-1m transactions in 1 extrinsic call. Is there any limit by BlockWeight or anything else? Oct 6, 2022 at 7:49
  • 1
    I'm not pretty sure about that. But you could split it into multiple calls. It looks like this Vec<Scheduler::schedule(Utility::batch(Vec<transfer>))>. Make sure that your chain has pallet-scheduler and pallet-utility, Oct 6, 2022 at 8:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.