Attribute Macro brush_lang::trait_definition
source · [−]#[trait_definition]
Expand description
Defines extensible trait in the scope of brush::contract.
It is a common rust trait, so you can use any features of rust inside of this trait.
If this trait contains some methods marked with #[ink(message)]
or #[ink(constructor)]
attributes,
this macro will extract these attributes and will put them into a separate trait
(the separate trait only is used to call methods from the original trait), but the macro will not touch methods.
This macro stores definition of the trait in a temporary file during build process.
Based on this definition #[brush::contract]
will generate implementation of additional traits.
** Note ** The name of the trait defined via this macro must be unique for the whole project. ** Note ** You can’t use aliases, generics, and other rust’s stuff in signatures of ink!’s methods.
Example: Definition
mod doc {
use ink_prelude::collections::BTreeMap;
use brush::traits::{AccountId, Balance, InkStorage};
#[derive(Default, Debug)]
pub struct Data {
pub balances: BTreeMap<AccountId, Balance>,
}
#[brush::trait_definition]
pub trait PSP22Storage: InkStorage {
fn get(&self) -> &Data;
fn get_mut(&mut self) -> &mut Data;
}
#[brush::trait_definition]
pub trait PSP22: PSP22Storage {
/// Returns the account Balance for the specified `owner`.
#[ink(message)]
fn balance_of(&self, owner: AccountId) -> Balance {
self.get().balances.get(&owner).copied().unwrap_or(0)
}
/// Transfers `value` amount of tokens from the caller's account to account `to`.
#[ink(message)]
fn transfer(&mut self, to: AccountId, value: Balance) {
self._transfer_from_to(to, to, value)
}
fn _transfer_from_to(&mut self, from: AccountId, to: AccountId, amount: Balance) {
let from_balance = self.balance_of(from);
assert!(from_balance >= amount, "InsufficientBalance");
self.get_mut().balances.insert(from, from_balance - amount);
let to_balance = self.balance_of(to);
self.get_mut().balances.insert(to, to_balance + amount);
}
}
}
Example: Implementation
It uses storage trait from above.
#[brush::contract]
mod base_psp22 {
use ink_prelude::collections::BTreeMap;
use brush::traits::InkStorage;
use ink_storage::traits::StorageLayout;
use ink_storage::traits::SpreadLayout;
#[derive(Default, Debug, SpreadLayout)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo, StorageLayout))]
pub struct Data {
pub supply: Balance,
pub balances: BTreeMap<AccountId, Balance>,
pub allowances: BTreeMap<(AccountId, AccountId), Balance>,
}
#[brush::trait_definition]
pub trait PSP22ExampleStorage: InkStorage {
fn get(&self) -> &Data;
fn get_mut(&mut self) -> &mut Data;
}
#[brush::trait_definition]
pub trait PSP22Example: PSP22ExampleStorage {
/// Returns the account Balance for the specified `owner`.
#[ink(message)]
fn balance_of(&self, owner: AccountId) -> Balance {
self.get().balances.get(&owner).copied().unwrap_or(0)
}
/// Transfers `value` amount of tokens from the caller's account to account `to`.
#[ink(message)]
fn transfer(&mut self, to: AccountId, value: Balance) {
let from = Self::env().caller();
self._transfer_from_to(from, to, value)
}
fn _transfer_from_to(&mut self, from: AccountId, to: AccountId, amount: Balance) {
let from_balance = self.balance_of(from);
assert!(from_balance >= amount, "InsufficientBalance");
self.get_mut().balances.insert(from, from_balance - amount);
let to_balance = self.balance_of(to);
self.get_mut().balances.insert(to, to_balance + amount);
}
}
#[ink(storage)]
#[derive(Default)]
pub struct PSP22Struct {
example: Data,
hated_account: AccountId,
}
impl PSP22ExampleStorage for PSP22Struct {
fn get(&self) -> &Data {
&self.example
}
fn get_mut(&mut self) -> &mut Data {
&mut self.example
}
}
impl PSP22Example for PSP22Struct {
// Let's override method to reject transactions to bad account
fn _transfer_from_to(&mut self, from: AccountId, to: AccountId, amount: Balance) {
assert!(to != self.hated_account, "I hate this account!");
let from_balance = self.balance_of(from);
assert!(from_balance >= amount, "InsufficientBalance");
self.get_mut().balances.insert(from, from_balance - amount);
let to_balance = self.balance_of(to);
self.get_mut().balances.insert(to, to_balance + amount);
}
}
impl PSP22Struct {
#[ink(constructor)]
pub fn new(hated_account: AccountId) -> Self {
let mut instance = Self::default();
instance.hated_account = hated_account;
instance
}
}
}