Skip to main content
Version: 3.2.0

PSP22 Pallet Metadata

This example shows how you can reuse the implementation of PSP22 token with the PSP22Metadata extension via pallet-assets chain extension.

First, you should implement basic version of PSP22 Pallet.

Step 1: Implement features​

  • Use openbrush::contract macro instead of ink::contract.
  • Implement PSP22PalletMetadata via `#[openbrush::implementation].
#![cfg_attr(not(feature = "std"), no_std, no_main)]

#[openbrush::contract]
#[openbrush::implementation(PSP22Pallet, PSP22PalletMetadata)]
pub mod my_psp22_pallet {
...
}

Step 2: Define storage​

Declare storage struct and declare the field related to the metadata module data structure. Then you need to derive the Storage trait and mark the corresponding field with the #[storage_field] attribute. Deriving this trait allows you to reuse the PSP22Metadata extension in your PSP22 Pallet implementation.

#[ink(storage)]
#[derive(Default, Storage)]
pub struct Contract {
#[storage_field]
pallet: psp22_pallet::Data,
}

Step 3: Define constructor​

Define constructor. Your PSP22Metadata contract is ready!

impl Contract {
/// During instantiation of the contract, you need to pass native tokens as a deposit
/// for asset creation.
#[ink(constructor)]
#[ink(payable)]
pub fn new(
asset_id: u32,
min_balance: Balance,
total_supply: Balance,
name: String,
symbol: String,
decimal: u8,
) -> Self {
let mut instance = Self::default();

psp22_pallet::Internal::_create(&mut instance, asset_id, Self::env().account_id(), min_balance)
.expect("Should create an asset");
instance.pallet.asset_id.set(&asset_id);
instance.pallet.origin.set(&Origin::Caller);
instance
.pallet
.pallet_assets
.get_or_default()
.set_metadata(asset_id, name.into(), symbol.into(), decimal)
.expect("Should set metadata");
psp22_pallet::Internal::_mint_to(&mut instance, Self::env().caller(), total_supply).expect("Should mint");

instance
}
}

Final code​

#![cfg_attr(not(feature = "std"), no_std, no_main)]

#[openbrush::implementation(PSP22Pallet, PSP22PalletMetadata)]
#[openbrush::contract]
pub mod my_psp22_pallet_metadata {
use openbrush::traits::Storage;

#[ink(storage)]
#[derive(Default, Storage)]
pub struct Contract {
#[storage_field]
pallet: psp22_pallet::Data,
}

impl Contract {
/// During instantiation of the contract, you need to pass native tokens as a deposit
/// for asset creation.
#[ink(constructor)]
#[ink(payable)]
pub fn new(
asset_id: u32,
min_balance: Balance,
total_supply: Balance,
name: String,
symbol: String,
decimal: u8,
) -> Self {
let mut instance = Self::default();

psp22_pallet::Internal::_create(&mut instance, asset_id, Self::env().account_id(), min_balance)
.expect("Should create an asset");
instance.pallet.asset_id.set(&asset_id);
instance.pallet.origin.set(&Origin::Caller);
instance
.pallet
.pallet_assets
.get_or_default()
.set_metadata(asset_id, name.into(), symbol.into(), decimal)
.expect("Should set metadata");
psp22_pallet::Internal::_mint_to(&mut instance, Self::env().caller(), total_supply).expect("Should mint");

instance
}
}
}