Cấu trúc cơ bản của ink! smart contract

Cấu trúc cơ bản của ink! smart contract

Định nghĩa ink! contract

  • Sử dụng #[ink::contract]
    #[ink::contract]
    mod <tên module> {
        ...
    }

Cách định nghĩa on-chain storage

  • Sử dụng #[ink::storage]
    #[ink(storage)]
    pub struct <tên contract> {
        // Các trường dữ liệu on-chain
    }

Ví dụ 1 : Hỗ trợ hầu hết các kiễu dữ liệu nguyên thuỷ Rust

#[ink(storage)]
pub struct MyContract {
    // Store a bool
    my_bool: bool,
    // Store some number
    my_number: u32,
    // Store some String
    my_string: String,
    // Store some u32 in a vec
    my_vector: Vec<u32>,
}
/* --snip-- */

Ví dụ 2: Substrate Types như AccountId, Hash, Balance

#[ink(storage)]
pub struct MyContract {
    // Store some AccountId
    my_account: AccountId,
    // Store some Balance
    my_balance: Balance,
    // Store some Hash
    my_hash: Hash,
}
/* --snip-- */

Ví dụ 3: Mapping

#[ink(storage)]
#[derive(Default)]
pub struct Mappings {
    /// Mapping from owner to number of owned token.
    balances: Mapping<AccountId, Balance>,
    /// Mapping from owner to aliases.
    names: Mapping<AccountId, Vec<String>>,
}

Ví dụ 4: Enum và Struct

Lưu ý import 2 thư viện này ở Cargo.toml

[dependencies]
...
scale-info = { version = "2.6", default-features = false, features = ["derive"]}
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
  • Định nghĩa Enum
#[derive(scale::Encode, scale::Decode, Debug)]
#[cfg_attr(feature = "std", derive(StorageLayout, scale_info::TypeInfo))]
pub enum Status {
    /// An auction has not started yet.
    NotStarted,
    /// We are in the starting period of the auction, collecting initial bids.
    OpeningPeriod,
}
mod MyContract {
    use ink::prelude::string::String;
    use ink::prelude::vec::Vec;
 
    // Định nghĩa struct lưu thông tin Status 
    #[derive(scale::Encode, scale::Decode, Debug)]
    #[cfg_attr(feature = "std", derive(StorageLayout, scale_info::TypeInfo))]
    pub struct Auction {
        /// Branded name of the auction event.
        name: String,
        /// Some hash identifying the auction subject.
        subject: Hash,
        /// Auction status.
        status: Status, // Enum: Usage shown in next section
        /// Candle auction can have no winner.
        /// If auction is finalized, that means that the winner is determined.
        finalized: bool,
        /// vector
        vector: Vec<u8>,
    }
 
    #[ink(storage)]
    pub struct MyContract {
        // Store Auctions in a vec
        auctions: Vec<Auction>,
    }
}
 

Hàm WRITE (&mut self)

  • Cấu trúc:
fn <tên hàm> (&mut self, ...) {
    ... 
    }
  • Ví dụ
impl MyContract {
 
    #[ink(message)]
    pub fn my_setter(&mut self, new_value: u32) {
        self.my_number = new_value;
    }
}

Hàm READ (&self)

  • Cấu trúc:
fn <tên hàm> (&self, ...) {
    ... 
    }
  • Ví dụ
impl MyContract {
 
    #[ink(message)]
    pub fn my_setter(&mut self, new_value: u32) {
        self.my_number = new_value;
    }
}

Events

  • Định nghĩa event
#[ink(event)]
pub struct Released {
    value: Balance,
    to: AccountId,
}
  • Emit event
#[ink(message)]
pub fn release(&mut self) -> Result<(), Error> {
    ...
 
    self.env().emit_event(Released {
        value: releasable,
        to: self.beneficiary,
    });
 
    Ok(())
}

Errors

  • Định nghĩa Errors
#[derive(Debug, PartialEq, Eq)]
#[ink::scale_derive(Encode, Decode, TypeInfo)]
pub enum Error {
    InvalidBeneficiary,
    ZeroReleasableBalance,
}
  • Return errors
#[ink(message)]
pub fn release(&mut self) -> Result<(), Error> {
    let releasable = self.releasable_balance();
    if releasable == 0 {
        return Err(Error::ZeroReleasableBalance)
    }
    ...
    Ok(())
}

Gas trong ink!

Gas là tài nguyên sử dụng khi thực hiện tương tác với smart contract Bao gồm:

  • không gian lưu trữ proof (for storing data in the contract's storage)
  • thời gian tính toán (for executing the contract and its logic)

-> Trong Substrate: Gas = (refTime, proofSize)

-> Gas -> người thực hiện sẽ trả 1 lượng phí (phí lưu trữ)

refTime

Lượng thời gian tính toán có thể được sử dụng cho việc thực thi, tính bằng picogiây

proofSize

  • proofSize is the size of the proof that individual parachains send to the Polkadot or Kusama relay chain to allow re-executing their block for validation (this is called Proof of Validity).
  • Phrased differently: Layer-1 chains send a proof of validity to a Layer-0 chain to validate the block. This Proof of Validity contains everything necessary to execute the block -- the code of each contract that is executed plus the storage each contract reads and writes