Skip to main content
Version: 3.x

#[ink(message)]

Applicable to methods.

Flags a method for the ink! storage struct as message making it available to the API for calling the contract.

Note that all public functions must use the #[ink(message)] attribute

There must be at least one #[ink(message)] defined method.

Methods flagged with #[ink(message)] are special in that they are dispatchable upon contract invocation. The set of ink! messages defined for an ink! smart contract define its API surface with which users are allowed to interact.

An ink! smart contract can have multiple such ink! messages defined.

An ink! message with a &self receiver may only read state whereas an ink! message with a &mut self receiver may mutate the contract's storage.

#[ink(message)]
pub fn purely_reading(&self, from: AccountId) {
// actual implementation
}

#[ink(message)]
pub fn mutates_storage(&mut self, from: AccountId) {
// actual implementation
}

Messages Return Value

The return value of a message needs to implement scale::Encode.

It is notable that the collections under ink_storage ‒ such as e.g. Vec or HashMap ‒ don't implement scale::Encode. This means you can't just return a Vec from an ink! message. This restriction is intentional ‒ returning a complete data structure with a potentially unbounded content is an anti-pattern for smart contracts. Just think about the unpredictable gas costs.

If you really really need to return a data structure in its entirety then use the ones from ink_prelude (e.g. ink_prelude::vec::Vec). Those implement scale::Encode.

Example

Given the Flipper contract definition above we add some #[ink(message)] definitions as follows:

use ink_lang as ink;

#[ink::contract]
mod flipper {
#[ink(storage)]
pub struct Flipper {
value: bool,
}

impl Flipper {

#[ink(constructor)]
pub fn new(initial_value: bool) -> Self {
Flipper { value: false }
}

/// Flips the current value.
#[ink(message)]
pub fn flip(&mut self) {
self.value = !self.value;
}

/// Returns the current value.
#[ink(message)]
pub fn get(&self) -> bool {
self.value
}
}
}