Test a Transfer Transaction
Testing each function is an important part of developing pallets for production. This guide steps you through best practices for writing test cases for a basic transfer function.
Outline the transfer function
A transfer function has two key elements: subtracting a balance from an account and adding that balance to another account. Here, we'll start by outlining this function:
#[pallet::weight(10_000)]
pub (super) fn transfer(
origin: OriginFor<T>,
to: T::AccountId,
#[pallet::compact] amount: T::Balance,
) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;
Accounts::<T>::mutate(&sender, |bal| {
*bal = bal.saturating_sub(amount);
});
Accounts::<T>::mutate(&to, |bal| {
*bal = bal.saturating_add(amount);
});
Self::deposit_event(Event::<T>::Transferred(sender, to, amount))
Ok(().into())
}Check that the sender has enough balance
The first thing to verify, is whether the sender has enough balance. In a separate tests.rs file, write out this first test case:
Configure error handling
To implement some error check, replace mutate with try_mutate to use ensure!. This will check whether bal is greater or equal to amount and throw an error message if not:
Run cargo test from your pallet's directory.
Check that sending account doesn't go below minimum balance
Inside your transfer_works function:
Check that both tests work together
Use #[transactional] to generate a wrapper around both checks:
Handle dust accounts
Make sure that sending and receiving accounts aren't dust accounts. Use T::MinBalance::get():
Examples
Tests in the
reward-coinexample pallet.
Resources
Last updated