ManicMinter Contract
This tutorial will not include complete code from the contract to keep it short and focused on the cross contract calls and e2e tests. The full code for this example is available here
Storage
To start with delete the boilerplate code from the lib.rs
file.
The storage will be defined as follows:
pub struct ManicMinter {
/// Contract owner
owner: AccountId,
/// Oxygen contract address
token_contract: AccountId,
/// Minting price. Caller must pay this price to mint one new token from Oxygen contract
price: Balance,
}
Error and Types
We will define the error and types as follows:
/// The ManicMinter error types.
pub enum Error {
/// Returned if not enough balance to fulfill a request is available.
BadMintValue,
/// Returned if the token contract account is not set during the contract creation.
ContractNotSet,
/// The call is not allowed if the caller is not the owner of the contract
NotOwner,
/// Returned if multiplication of price and amount overflows
OverFlow,
/// Returned if the cross contract transaction failed
TransactionFailed,
}
pub type Result<T> = core::result::Result<T, Error>;
Contract Trait
The following trait will be used to define the contract interface:
pub trait Minting {
/// Mint new tokens from Oxygen contract
#[ink(message, payable)]
fn manic_mint(&mut self, amount: Balance) -> Result<()>;
/// Set minting price for one Oxygen token
#[ink(message)]
fn set_price(&mut self, price: Balance) -> Result<()>;
/// Get minting price for one Oxygen token
#[ink(message)]
fn get_price(&self) -> Balance;
}
Constructor
The constructor will be defined as follows:
impl ManicMinter {
#[ink(constructor)]
pub fn new(contract_acc: AccountId) -> Self {
Self {
owner: Self::env().caller(),
token_contract: contract_acc,
price: 0,
}
}
}
Cross Contract Call
The manic_mint
method will execute cross contract call to Oxygen contract using Call Builder
. The method will be defined as follows:
impl Minting for ManicMinter {
#[ink(message, payable)]
fn manic_mint(&mut self, amount: Balance) -> Result<()> {
//---- snip ----
let mint_result = build_call::<DefaultEnvironment>()
.call(self.token_contract)
.gas_limit(5000000000)
.exec_input(
ExecutionInput::new(Selector::new(ink::selector_bytes!("PSP22Mintable::mint")))
.push_arg(caller)
.push_arg(amount),
)
.returns::<()>()
.try_invoke();
//---- snip ----
}
}