Skip to content
This repository was archived by the owner on Dec 12, 2025. It is now read-only.

Commit 7ff5a96

Browse files
committed
Sylvia tutorial first message
1 parent 0672542 commit 7ff5a96

File tree

4 files changed

+171
-2
lines changed

4 files changed

+171
-2
lines changed

src/pages/sylvia/macros/generated-types/message-types.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ be called depending on the enum variant. This is described in the example below
2121

2222
The following code:
2323

24-
```rust, template="sylvia-empty"
24+
```rust template="sylvia-empty"
2525
#[cw_serde]
2626
pub struct SomeResponse;
2727

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"contract-creation": "Contract creation"
2+
"contract-creation": "Contract creation",
3+
"first-messages": "First messages"
34
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Entry points
2+
3+
Typical Rust application starts with the `fn main()` function called by the operating system. Smart
4+
contracts are not significantly different. When the message is sent to the contract, a function
5+
called "entry point" is executed. Unlike native applications, which have only a single `main` entry
6+
point, smart contracts have a couple of them, each corresponding to different message type:
7+
`instantiate`, `execute`, `query`, `sudo`, `migrate` and more.
8+
9+
To start, we will go with three basic entry points:
10+
11+
- **`instantiate`** is called once per smart contract lifetime; you can think about it as a
12+
constructor or initializer of a contract.
13+
- **`execute`** for handling messages which can modify contract state; they are used to perform some
14+
actual actions.
15+
- **`query`** for handling messages requesting some information from a contract; unlike
16+
**`execute`**, they can never alter any contract state, and are used in a similar manner to
17+
database queries.
18+
19+
## Generate entry points
20+
21+
^Sylvia provides an attribute macro named
22+
[`entry_points`](https://docs.rs/sylvia/latest/sylvia/attr.entry_points.html). In most cases, your
23+
entry point will just dispatch received messages to the handler, so it's not necessary to manually
24+
create them, and we can rely on a macro to do that for us.
25+
26+
Let's add the **`entry_points`** attribute macro to our contract:
27+
28+
```rust,noplayground
29+
use cosmwasm_std::{Response, StdResult};
30+
use sylvia::types::InstantiateCtx;
31+
use sylvia::{contract, entry_points};
32+
33+
pub struct CounterContract;
34+
35+
#[entry_points]
36+
#[contract]
37+
impl CounterContract {
38+
pub const fn new() -> Self {
39+
Self
40+
}
41+
42+
#[sv::msg(instantiate)]
43+
pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult<Response> {
44+
Ok(Response::default())
45+
}
46+
}
47+
```
48+
49+
Note that **`#[entry_points]`** is added above the **`#[contract]`**. It is because
50+
**`#[contract]`** removes attributes like **`#[sv::msg(...)]`** on which both these macros rely.
51+
52+
Always remember to place **`#[entry_points]`** first.
53+
54+
^Sylvia generates entry points with
55+
[`#[entry_point]`](https://docs.rs/cosmwasm-std/1.3.1/cosmwasm_std/attr.entry_point.html) attribute
56+
macro. Its purpose is to wrap the whole entry point to the form the Wasm runtime understands. The
57+
proper Wasm entry points can use only basic types supported natively by Wasm specification, and Rust
58+
structures and enums are not in this set. Working with such entry points would be overcomplicated,
59+
so CosmWasm creators delivered the `entry_point` macro. It creates the raw Wasm entry point, calling
60+
the decorated function internally and doing all the magic required to build our high-level Rust
61+
arguments from arguments passed by Wasm runtime.
62+
63+
Now, when our contract has a proper entry point, let's build it and check if it's correctly defined:
64+
65+
```shell
66+
contract $ cargo build --release --target wasm32-unknown-unknown --lib
67+
Finished release [optimized] target(s) in 0.03s
68+
69+
contract $ cosmwasm-check target/wasm32-unknown-unknown/release/contract.wasm
70+
Available capabilities: {"stargate", "cosmwasm_1_3", "cosmwasm_1_1", "cosmwasm_1_2", "staking", "iterator"}
71+
72+
target/wasm32-unknown-unknown/release/contract.wasm: pass
73+
74+
All contracts (1) passed checks!
75+
```
76+
77+
## Next step
78+
79+
Well done! We have now a proper `CosmWasm` contract. Let's add some state to it, so it will actually
80+
be able to do something.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Generating first messages
2+
3+
We have set up our dependencies. Now let's use them to create simple messages.
4+
5+
## Creating an instantiation message
6+
7+
For this step we will create a new file:
8+
9+
- `src/contract.rs` - here, we will define our messages and behavior of the contract upon receiving
10+
them
11+
12+
Add this module to `src/lib.rs`. You want it to be public, as users might want to get access to
13+
types stored inside your contract.
14+
15+
```rust copy filename="src/lib.rs"
16+
pub mod contract;
17+
```
18+
19+
Now let's create an `instantiate` method for our contract. In `src/contract.rs`
20+
21+
```rust copy filename="src/contract.rs" template="sylvia/empty"
22+
use sylvia::cw_std::{Response, StdResult};
23+
use sylvia::contract;
24+
use sylvia::ctx::InstantiateCtx;
25+
26+
pub struct CounterContract;
27+
28+
#[contract]
29+
impl CounterContract {
30+
pub const fn new() -> Self {
31+
Self
32+
}
33+
34+
#[sv::msg(instantiate)]
35+
pub fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult<Response> {
36+
Ok(Response::default())
37+
}
38+
}
39+
```
40+
41+
So what is going on here? First, we define the `CounterContract` struct. It is empty right now but
42+
later when we learn about states, we will use its fields to store them. We mark the `impl` block
43+
with [`contract`](../../sylvia/macros/contract) attribute macro. It will parse every method inside
44+
the `impl` block marked with the [`sv::msg(...)`](../../sylvia/macros/attributes/msg) attribute and
45+
create proper messages and utilities like
46+
[MultiTest helpers](../../sylvia/macros/generated-types/multitest) for them. More on them later.
47+
48+
CosmWasm contract requires only the [instantiate](../../core/entrypoints/instantiate) entry point,
49+
and it is mandatory to specify it for the [`contract`](../../sylvia/macros/contract) macro. We have
50+
to provide it with the proper context type
51+
[`InstantiateCtx`](https://docs.rs/sylvia/latest/sylvia/ctx/struct.InstantiateCtx.html).
52+
53+
Context gives us access to the blockchain state, information about our contract, and the sender of
54+
the message. We return the
55+
[`StdResult`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/type.StdResult.html) which uses
56+
standard CosmWasm error
57+
[`StdError`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.StdError.html). It's generic over
58+
[`Response`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.Response.html). For now, we
59+
will return the `default` value of it.
60+
61+
I recommend expanding the macro now and seeing what Sylvia generates. It might be overwhelming, as
62+
there will be a lot of things generated that seem not relevant to our code, so for the bare minimum
63+
check the [`InstantiateMsg`](../../sylvia/macros/generated-types/message-types#contract-messages)
64+
and its `impl` block.
65+
66+
## Next step
67+
68+
If we build our contract with command:
69+
70+
```shell copy filename="TERMINAL"
71+
cargo build --release --target wasm32-unknown-unknown --lib
72+
```
73+
74+
and then run:
75+
76+
```shell copy filename="TERMINAL"
77+
cosmwasm-check target/wasm32-unknown-unknown/release/contract.wasm
78+
```
79+
80+
The output should look like this:
81+
82+
```shell filename="TERMINAL"
83+
Available capabilities: {"stargate", "staking", "cosmwasm_1_3", "cosmwasm_2_0", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_4", "iterator"}
84+
85+
target/wasm32-unknown-unknown/release/contract.wasm: pass
86+
87+
All contracts (1) passed checks!
88+
```

0 commit comments

Comments
 (0)