Entrypoints

Entrypoints

Entrypoints are where your contract can be called from the outside world. You can equate that to your main function in C, Rust, Java, etc. However, there is one small difference: In CosmWasm, you have multiple of these entrypoints, each one different from the last.

In this section we want to give you a quick overview over all the entrypoints and when they are called.

💡

In our examples, we will always refer to StdResult as the return type (and therefore StdError as the error type). This is just for convenience since every type that implements the ToString type can be used as an error type!

Meaning, as long as it implements ToString, nothing is stopping you from defining Result<Response, MyError>. This can reduce your code complexity, especially if you want to use the try operator.

Defining entrypoints

While you will learn all about entrypoints in the next sections, we want to give you an idea on how to define an entrypoint in the first place.

CosmWasm defines the handy #[entry_point] attribute macro. You simply annotate a function with it, and it automatically generates code that communicates to the VM: "Hey! This is an entrypoint, please use it when needed!"

💡

When defining an entrypoint, it is important to use the correct types for the parameters and return type. Incorrect types will cause errors when trying to call the contract.
In the following sections we will take a look at all possible entrypoints, including the correct function signature.

💡

Even though the sections will show you to use #[entry_point], it is recommended to define your endpoints as #[cfg_attr(not(feature = "library"), entry_point)].
The reason behind that is that it allows you to reuse your contract as a library.

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    msg: InstantiateMsg,
) -> StdResult<Response> {
    // Do some logic here
    Ok(Response::default())
}

Entrypoint parameters

Entrypoints have a few parameters (as you can see above), some of them are predefined by cosmwasm-std, others are defined by the user themselves.

Here we go over the different predefined types the standard library provides, and how you can define your own types.

Predefined types

Deps/DepsMut

These structs provide you access to the:

  • Storage
  • VM API
  • Querier

The big difference is that DepsMut gives you mutable access to the storage. This design is deliberate since you, for example, can't mutate the state in the query endpoint. Instead of relying on runtime errors, this is made irrepresentable through Rust's type system.

Env

This struct provides you with some information of the current state of the environment your contract is executed in.

The information provided is, for example, the block height, chain ID, transaction info, etc. Basically anything you'd ever want to know about the current state of the execution environment!

MessageInfo

This struct isn't provided to every endpoint, only to a select few.

It provides you with some information that might be crucial to you, depending on the operation you want to perform. It contains the sender of the message you just received, and the funds that were transferred along with it to your contract.

Defining your own messages

In our examples, you might have seen messages such as InstantiateMsg. These messages are actually user-defined, meaning each contract developer has to define them themselves.

To make this easier our cosmwasm-schema crate provides the cw_serde attribute macro, to define an instantiate message, you simply write this:

instantiate.rs
#[cw_serde]
struct CustomInstantiateMsg {
  initial_admins: Vec<Addr>,
}
💡

This macro actually just expands into a bunch of derive attributes. We provide this simply for your convenience, otherwise you'd have to keep track of all of these derives yourself.

Without #[cw_serde]
instantiate.rs
#[derive(
  serde::Serialize,
  serde::Deserialize,
  Clone,
  Debug,
  PartialEq,
  schemars::JsonSchema
)]
struct CustomInstantiateMsg {
  initial_admins: Vec<Addr>,
}