Skip to content

Commit

Permalink
Merge pull request #57 from CosmWasm/aw/core-conventions
Browse files Browse the repository at this point in the history
Documentation about conventions
  • Loading branch information
aumetra authored Jun 21, 2024
2 parents fb035bf + 3704540 commit 2cb191c
Show file tree
Hide file tree
Showing 15 changed files with 190 additions and 37 deletions.
1 change: 1 addition & 0 deletions src/pages/core/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"entrypoints": "Entrypoints",
"architecture": "Architecture",
"standard-library": "Standard Library",
"conventions": "Conventions",
"advanced": "Advanced",
"specification": "Specification"
}
6 changes: 4 additions & 2 deletions src/pages/core/advanced/measuring-time.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ struct contains the field `block`. The struct contained in this field has a
bunch of different information about the current state of the blockchain you are
running on.

> The documentation about the `BlockInfo` struct can be
> [found here](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.BlockInfo.html)
> The documentation about the `BlockInfo` struct can be [found here]
The timestamp contained in this struct can be safely used in your program as the
source of the current time. Well, kinda. It won't be 100% matching the current
Expand All @@ -29,3 +28,6 @@ But you can rely on this timestamp to have the following properties:

- Consistent across the chain (every validator on the chain has the same info)
- Monotonic (it will ever only increase or stay the same; never decrease)

[found here]:
https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.BlockInfo.html
23 changes: 16 additions & 7 deletions src/pages/core/architecture/actor-model.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import { Callout } from "nextra/components";

CosmWasm, at its core, is built around the actor model. This prevents some
common pitfalls which, for example, Ethereum smart contracts had to fix over the
years. The issues mostly revolved around
[reentrancy issues](https://ethereum.org/en/developers/docs/smart-contracts/security/#reentrancy)
where we could, for example, call out to another contract before finishing the
current execution.
years. The issues mostly revolved around [reentrancy issues] where we could, for
example, call out to another contract before finishing the current execution.

<Callout>
If you are already familiar with the actor model through, for example,
Expand Down Expand Up @@ -52,11 +50,22 @@ As you can see in the simple graphic above, they simply exchange messages
addressed to each other, and the messages reference previous messages if need
be.

<Callout>
In CosmWasm you can only pass a single message type to a contract endpoint. If
you are wondering how to handle multiple message types, check out the [enum
dispatch] page.
</Callout>

But how does that fix reentrancy? In CosmWasm, you can only send out messages at
the end of a contract execution as part of the response. This ensures you have
already written everything to the state, meaning the state can't suddenly change
mid-execution and make your contract exhibit buggy behaviour.

CosmWasm effectively forces you to follow the
[CEI pattern (Checks, Effects, Interactions)](https://fravoll.github.io/solidity-patterns/checks_effects_interactions.html)
while other similar systems only have this as a "best practice".
CosmWasm effectively forces you to follow the [CEI pattern (Checks, Effects,
Interactions)] while other similar systems only have this as a "best practice".

[reentrancy issues]:
https://ethereum.org/en/developers/docs/smart-contracts/security/#reentrancy
[enum dispatch]: ../conventions/enum-dispatch
[CEI pattern (Checks, Effects, Interactions)]:
https://fravoll.github.io/solidity-patterns/checks_effects_interactions.html
9 changes: 5 additions & 4 deletions src/pages/core/architecture/events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import { Callout } from "nextra/components";

# Events

CosmWasm can emit
[Cosmos Events](https://docs.cosmos.network/v0.50/learn/advanced/events). These
events are stored in the block as metadata, allowing the contract to attach
metadata to what exactly happened during execution.
CosmWasm can emit [Cosmos Events]. These events are stored in the block as
metadata, allowing the contract to attach metadata to what exactly happened
during execution.

<Callout>

Expand Down Expand Up @@ -46,3 +45,5 @@ let event = Event::new("custom_event")
let response: Response<Empty> = Response::new()
.add_event(event);
```

[Cosmos Events]: https://docs.cosmos.network/v0.50/learn/advanced/events
15 changes: 15 additions & 0 deletions src/pages/core/conventions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
tags: ["core", "conventions"]
---

import { Callout } from "nextra/components";

# Conventions

Just like with any platform, there are certain conventions on how to write
contracts for CosmWasm. This section will give you a quick overview over the
different conventions set in the CosmWasm ecosystem.

These conventions are about recommended programming patterns, and
recommendations on how you should structure your contract to make it fit into
the existing CosmWasm ecosystem better.
4 changes: 4 additions & 0 deletions src/pages/core/conventions/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"library-feature": "Library feature",
"enum-dispatch": "Enum dispatch"
}
49 changes: 49 additions & 0 deletions src/pages/core/conventions/enum-dispatch.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
tags: ["core", "conventions"]
---

import { Callout } from "nextra/components";

# Enum dispatch

In most production contracts you want to handle multiple message types in a
single contract. Unfortunately you can't create multiple endpoints of the same
type in a single contract, so you need to dispatch based on the message type.

The most common way to do this is to use an enum to represent the different
message types and then match on that enum in the endpoint.

<Callout>
If this sounds like something you don't want to do manually, we got you covered!
The `sylvia` crate provides a procedural macro to generate the boilerplate code for you.

You can find the documentation of the `sylvia` crate [here](../../sylvia.mdx).

</Callout>

```rust filename="contract.rs" template="core"
#[cw_serde]
enum ExecuteMsg {
Add { value: i32 },
Subtract { value: i32 },
}

#[entry_point]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> StdResult<Response> {
match msg {
ExecuteMsg::Add { value } => {
// TODO: Add operation
}
ExecuteMsg::Subtract { value } => {
// TODO: Subtract operation
}
}

Ok(Response::new())
}
```
58 changes: 58 additions & 0 deletions src/pages/core/conventions/library-feature.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
tags: ["core", "conventions"]
---

import { Callout } from "nextra/components";

# Library feature

In the ecosystem, there is the convention to gate the entrypoints of your
contract behind a compile-time feature. The feature is conventionally called
`library`.

So instead of doing this:

```rust filename="contract.rs" template="core"
#[entry_point]
pub fn instantiate(
_deps: DepsMut,
_env: Env,
_info: MessageInfo,
_msg: InstantiateMsg,
) -> StdResult<Response> {
Ok(Response::new())
}
```

You should do this:

```rust filename="contract.rs" template="core"
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
_deps: DepsMut,
_env: Env,
_info: MessageInfo,
_msg: InstantiateMsg,
) -> StdResult<Response> {
Ok(Response::new())
}
```

<Callout>
You can see this in action in the [`cw-plus` contracts]. Here is an example in
the [`cw4-stake` contract].
</Callout>

The rationale behind this is that currently using `#[entry_point]` exports
special symbols from the binary, and these symbols **must** be unique.

That means if you have two `instantiate` endpoints annotated with
`#[entry_point]` _somewhere_ in your project (that includes all your
dependencies!), your contract will fail to compile.

Using this library feature will enable developers to use your contract as a
dependency and reuse your code.

[`cw-plus` contracts]: https://github.com/CosmWasm/cw-plus
[`cw4-stake` contract]:
https://github.com/CosmWasm/cw-plus/blob/48bec694521655d5b3e688c51e4185f740ea4640/contracts/cw4-stake/Cargo.toml#L22-L24
8 changes: 5 additions & 3 deletions src/pages/core/entrypoints/query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { Callout } from "nextra/components";

# Query

In the previous section we talked about the [`execute` endpoint](./execute.mdx).
The `query` endpoint is actually pretty similar to its sibling `execute`, but
with one key difference: The storage is only accessible immutably.
In the previous section we talked about the [`execute` endpoint]. The `query`
endpoint is actually pretty similar to its sibling `execute`, but with one key
difference: The storage is only accessible immutably.

This means you can only _read_ from the storage but not _write_ to it.

Expand All @@ -24,3 +24,5 @@ pub fn query(
Ok(QueryResponse::default())
}
```

[`execute` endpoint]: ./execute.mdx
3 changes: 2 additions & 1 deletion src/pages/core/entrypoints/reply.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and interact with them.

<Callout>
If you are not familiar with the actor model, you can find out more about it
on [its own page](../architecture/actor-model).
on [its own page].
</Callout>

This endpoint gets invoked when you receive a response to a message you sent out
Expand Down Expand Up @@ -71,4 +71,5 @@ pub fn reply(deps: DepsMut, env: Env, msg: cosmwasm_std::Reply) -> StdResult<Res
}
```

[its own page]: ../architecture/actor-model
[transactions]: ../architecture/transactions
18 changes: 10 additions & 8 deletions src/pages/core/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,15 @@ Our only external dependency is Rust, which you need to install for your
platform.

<Callout>
We recommend installing Rust using the official [rustup
installer](https://rustup.rs). This makes it easy to stay on the most recent
Rust version and to install compiler targets.
We recommend installing Rust using the official [rustup installer]. This makes
it easy to stay on the most recent Rust version and to install compiler
targets.
</Callout>

<Callout>
For production builds you probably also want to install
[Docker](https://www.docker.com/), too.
<br /> This is because we offer the [CosmWasm Optimizing Compiler](https://github.com/CosmWasm/optimizer),
which uses a Docker image to build the smallest contract possible in a deterministic
fashion.
For production builds you probably also want to install [Docker], too.
<br /> This is because we offer the [CosmWasm Optimizing Compiler], which uses
a Docker image to build the smallest contract possible in a deterministic fashion.
</Callout>

After installing Rust, you need to add the WebAssembly target. This is needed so
Expand Down Expand Up @@ -70,3 +68,7 @@ cargo generate --git https://github.com/CosmWasm/cw-template.git --name PROJECT_

Now you should have a ready contract project in a new folder called
`PROJECT_NAME` (or whatever you changed it to).

[rustup installer]: https://rustup.rs
[Docker]: https://www.docker.com/
[CosmWasm Optimizing Compiler]: https://github.com/CosmWasm/optimizer
6 changes: 4 additions & 2 deletions src/pages/core/standard-library.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ CosmWasm offers a standard library providing a bunch of different components to
write smart contracts. In this section we will go over some components and
functionality the standard library offers.

A full list of all components along with documentation can be found
[on docs.rs](https://docs.rs/cosmwasm-std).
A full list of all components along with documentation can be found [on
docs.rs].

[on docs.rs]: https://docs.rs/cosmwasm-std
11 changes: 7 additions & 4 deletions src/pages/core/standard-library/cryptography.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ documentation about them.

<Callout>
Note that these values are in CosmWasm Gas (which is very much different from
Cosmos SDK Gas). For more info on gas, [check this
document](https://github.com/CosmWasm/cosmwasm/blob/main/docs/GAS.md).
Cosmos SDK Gas). For more info on gas, [check this document].
</Callout>

### secp256k1
Expand Down Expand Up @@ -58,8 +57,7 @@ documentation about them.
- Base: 2_112_000_000 gas
- Per item: 163_000_000 gas

You can also check these numbers in the
[source code](https://github.com/CosmWasm/cosmwasm/blob/main/packages/vm/src/environment.rs#L62-L101).
You can also check these numbers in the [source code].

## Note on hash functions

Expand All @@ -80,3 +78,8 @@ functions, and we intend to keep it that way. The reasoning for that is:
Keep in mind that, thanks to Wasm being our execution environment, contract
execution is quite fast. In most cases the perceived need to move hashing into a
host function is premature optimization and not actually needed.

[check this document]:
https://github.com/CosmWasm/cosmwasm/blob/main/docs/GAS.md
[source code]:
https://github.com/CosmWasm/cosmwasm/blob/main/packages/vm/src/environment.rs#L62-L101
4 changes: 3 additions & 1 deletion src/pages/core/standard-library/cryptography/bls12-381.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ for fun things such as aggregated signatures. At the moment, CosmWasm only
supports signature verifications. In the future we might add support for
zero-knowledge proofs on this curve.

Common examples where this curve is used are Ethereum block-headers and [drand](https://drand.love/)
Common examples where this curve is used are Ethereum block-headers and [drand]
randomness beacons.

## Example
Expand All @@ -21,3 +21,5 @@ doesn't care whether the public key is part of the G1 or G2 group (same for the
other components). They just have to somehow fit together.

<Callout>TODO: Add example as soon as BLS12-381 is properly released</Callout>

[drand]: https://drand.love/
12 changes: 7 additions & 5 deletions src/pages/core/standard-library/cryptography/ed25519.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ CosmWasm offers an API to verify and batch verify Ed25519 signatures. This is
powerful, especially since batch verifications require a random component which
is impossible to implement in contract code.

Ed25519 is known to
[have issues with inconsistent validation criteria](https://hdevalence.ca/blog/2020-10-04-its-25519am),
the API we offer follows [ZIP215](https://zips.z.cash/zip-0215). This means you
will have no issues with signatures being valid in one place and invalid in
another.
Ed25519 is known to [have issues with inconsistent validation criteria], the API
we offer follows [ZIP215]. This means you will have no issues with signatures
being valid in one place and invalid in another.

## Example

Expand All @@ -36,3 +34,7 @@ pub fn query(
Ok(QueryResponse::new(response.into_bytes()))
}
```

[have issues with inconsistent validation criteria]:
https://hdevalence.ca/blog/2020-10-04-its-25519am
[ZIP215]: https://zips.z.cash/zip-0215

0 comments on commit 2cb191c

Please sign in to comment.