Entry points
Typical Rust application starts with the fn main()
function called by the operating system.
Smart contracts are not significantly different. When the message is sent to the contract, a
function called "entry point" is called. Unlike native applications, which have only a single
main
entry point, smart contracts have a couple corresponding to different message types:
instantiate
, execute
, query
, sudo
, migrate
and more.
To start, we will go with three basic entry points:
instantiate
is called once per smart contract lifetime - you can think about it as a constructor or initializer of a contract.execute
for handling messages which can modify contract state - they are used to perform some actual actions.query
for handling messages requesting some information from a contract; unlikeexecute
, they can never affect any contract state, and are used just like database queries.
Go to your src/lib.rs
file, and start with an instantiate
entry point:
use cosmwasm_std::{entry_point, DepsMut, Empty, Env, MessageInfo, Response, StdResult};
#[entry_point]
pub fn instantiate(
_deps: DepsMut,
_env: Env,
_info: MessageInfo,
_msg: Empty,
) -> StdResult<Response> {
Ok(Response::new())
}
In fact, instantiate
is the only entry point required for a smart contract to be valid. It is not
very useful in this form, but it is a start. Let's take a closer look at the entry point structure.
First, we import a couple of types for more consistent usage. Then we define our
entry point. The instantiate
takes four arguments:
deps: DepsMut
is an utility type for communicating with the outer world - it allows querying, updating the contract state, querying other contracts state, and giving access to anApi
object with a couple of helper functions for dealing with CW addresses.env: Env
is an object representing the blockchains state when executing the message - the chain height and id, current timestamp, and the called contract address.info: MessageInfo
contains metainformation about the message which triggered an execution - an address that sends the message, and chain native tokens sent with the message.msg: Empty
is the message triggering execution itself - for now, it isEmpty
type that represents{}
JSON, but the type of this argument can be anything that is deserializable, and we will pass more complex types here in the future.
If you are new to the blockchain, those arguments may not have much sense to you, but while progressing through this book I will explain their usage one by one.
Notice an essential attribute decorating our entry point
#[entry_point]
. Its
purpose is to wrap the whole entry point to the form Wasm runtime understands. The proper Wasm entry
points can use only basic types supported natively by Wasm specification, and Rust structures and
enums are not in this set. Working with such entry points would be rather overcomplicated, so
CosmWasm creators delivered the entry_point
macro. It creates the raw Wasm entry point, calling
the decorated function internally and doing all the magic required to build our high-level Rust
arguments from arguments passed by Wasm runtime.
The next thing to look at is the return type. I used
StdResult<Response>
for
this simple example, which is an alias for Result<Response, StdError>
. The return entry point
type would always be a Result
type, with
some error type implementing ToString
trait and a well-defined type for success case. For most entry points, an "Ok" case would be the
Response
type that allows
fitting the contract into our actor model, which we will discuss very soon.
The body of the entry point is as simple as it could be - it always succeeds with a trivial empty response.