Skip to main content

Storing a Value

The first thing we are going to do to the contract template is introduce some storage values.

Here is how you would store some simple values in storage:

#[ink(storage)]
pub struct MyContract {
// Store a bool
my_bool: bool,
// Store some number
my_number: u32,
}
/* --snip-- */

Supported Types

Contract may store types that are encodable and decodable with Parity Codec which includes the most common types such as bool, u{8,16,32,64,128}, i{8,16,32,64,128}, String, tuples, and arrays.

ink! provides smart contracts Substrate specific types like AccountId, Balance, and Hash as if they were primitive types. Also ink! provides storage types for more elaborate storage interactions through the storage module:

use ink_storage::collections::{Vec, HashMap, Stash, Bitvec};

Here is an example of how you would store an AccountId and Balance:

// We are importing the default ink! types
use ink_lang as ink;

#[ink::contract]
mod MyContract {

// Our struct will use those default ink! types
#[ink(storage)]
pub struct MyContract {
// Store some AccountId
my_account: AccountId,
// Store some Balance
my_balance: Balance,
}
/* --snip-- */
}

You can find all the supported Substrate types in crates/storage/src/lib.rs.

Contract Deployment

Every ink! smart contract must have a constructor which is run once when a contract is created. ink! smart contracts can have multiple constructors:

use ink_lang as ink;

#[ink::contract]
mod mycontract {

#[ink(storage)]
pub struct MyContract {
number: u32,
}

impl MyContract {
/// Constructor that initializes the `u32` value to the given `init_value`.
#[ink(constructor)]
pub fn new(init_value: u32) -> Self {
Self {
number: init_value,
}
}

/// Constructor that initializes the `u32` value to the `u32` default.
///
/// Constructors can delegate to other constructors.
#[ink(constructor)]
pub fn default() -> Self {
Self {
number: Default::default(),
}
}
/* --snip-- */
}
}

Your Turn!

Follow the ACTIONs in the template.

Remember to run cargo +nightly test to test your work.

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

use ink_lang as ink;

#[ink::contract]
mod incrementer {

#[ink(storage)]
pub struct Incrementer {
// ACTION: Create a storage value called `value` which holds a `i32`
}

impl Incrementer {
#[ink(constructor)]
pub fn new(init_value: i32) -> Self {
// ACTION: Create a new `Incrementer` and set its `value` to `init_value`
}

// ACTION: Create a second constructor function named `default`.
// It has no input, and creates a new `Incrementer` with its `value`
// set to `0`.

#[ink(message)]
pub fn get(&self) {
// Contract Message
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn default_works() {
Incrementer::default();
}
}
}