Smart Contract Layout

Structure of NEAR smart contract

Simple Counter Contract

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::near_bindgen;

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, Default)]
pub struct Counter {
    value: u64,
}

#[near_bindgen]
impl Counter {
    pub fn increment(&mut self) {
        self.value += 1;
    }

    pub fn get_count(&self) -> u64 {
        self.value
    }
}

#[near_bindgen]

  • tells the program generate any necessary boilerplate to expose the necessary functions.

  • Any pub functions will be callable externally from any account/contract.

  • self can be used in multiple ways to control the mutability of the contract:

    • Functions that take &self or self will be read-only and do not write the updated state to storage

    • Functions that take &mut self allow for mutating state, and state will always be written back at the end of the function call

  • Exposed functions can omit reading and writing to state if self is not included in the function params

    • This can be useful for some static functionality or returning data embedded in the contract code

  • If the function has a return value, it will be serialized and attached as a result through env::value_return

Initialisation

  • By default, the Default::default() implementation of a contract will be used to initialize a contract. There can be a custom initialization function which takes parameters or performs custom logic using the #[init] annotation.

#[near_bindgen]
impl Counter {
    #[init]
    pub fn new(value: u64) -> Self {
        log!("Custom counter initialization!");
        Self { value }
    }
}

  • All contracts are expected to implement Default. If you would like to prohibit the default implementation from being used, the PanicOnDefault derive macro can be used:

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct Counter {
    // ...
}

More on Rust’s procedural macros:

Last updated