diff --git a/src/pages/core/_meta.json b/src/pages/core/_meta.json index 081cf08d..8d9ea4f0 100644 --- a/src/pages/core/_meta.json +++ b/src/pages/core/_meta.json @@ -3,6 +3,7 @@ "entrypoints": "Entrypoints", "architecture": "Architecture", "standard-library": "Standard Library", + "conventions": "Conventions", "advanced": "Advanced", "specification": "Specification" } diff --git a/src/pages/core/advanced/measuring-time.mdx b/src/pages/core/advanced/measuring-time.mdx index 2144d36b..8413bebb 100644 --- a/src/pages/core/advanced/measuring-time.mdx +++ b/src/pages/core/advanced/measuring-time.mdx @@ -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 @@ -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 diff --git a/src/pages/core/architecture/actor-model.mdx b/src/pages/core/architecture/actor-model.mdx index 856243b7..798cfa5d 100644 --- a/src/pages/core/architecture/actor-model.mdx +++ b/src/pages/core/architecture/actor-model.mdx @@ -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. If you are already familiar with the actor model through, for example, @@ -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. + + 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. + + 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 diff --git a/src/pages/core/architecture/events.mdx b/src/pages/core/architecture/events.mdx index cd7c2922..088a2966 100644 --- a/src/pages/core/architecture/events.mdx +++ b/src/pages/core/architecture/events.mdx @@ -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. @@ -46,3 +45,5 @@ let event = Event::new("custom_event") let response: Response = Response::new() .add_event(event); ``` + +[Cosmos Events]: https://docs.cosmos.network/v0.50/learn/advanced/events diff --git a/src/pages/core/conventions.mdx b/src/pages/core/conventions.mdx new file mode 100644 index 00000000..750747b9 --- /dev/null +++ b/src/pages/core/conventions.mdx @@ -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. diff --git a/src/pages/core/conventions/_meta.json b/src/pages/core/conventions/_meta.json new file mode 100644 index 00000000..54a882a0 --- /dev/null +++ b/src/pages/core/conventions/_meta.json @@ -0,0 +1,4 @@ +{ + "library-feature": "Library feature", + "enum-dispatch": "Enum dispatch" +} diff --git a/src/pages/core/conventions/enum-dispatch.mdx b/src/pages/core/conventions/enum-dispatch.mdx new file mode 100644 index 00000000..5cc4098a --- /dev/null +++ b/src/pages/core/conventions/enum-dispatch.mdx @@ -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. + + + 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). + + + +```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 { + match msg { + ExecuteMsg::Add { value } => { + // TODO: Add operation + } + ExecuteMsg::Subtract { value } => { + // TODO: Subtract operation + } + } + + Ok(Response::new()) +} +``` diff --git a/src/pages/core/conventions/library-feature.mdx b/src/pages/core/conventions/library-feature.mdx new file mode 100644 index 00000000..db7d53c0 --- /dev/null +++ b/src/pages/core/conventions/library-feature.mdx @@ -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 { + 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 { + Ok(Response::new()) +} +``` + + + You can see this in action in the [`cw-plus` contracts]. Here is an example in + the [`cw4-stake` contract]. + + +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 diff --git a/src/pages/core/entrypoints/query.mdx b/src/pages/core/entrypoints/query.mdx index 37fdbaee..ac939fb3 100644 --- a/src/pages/core/entrypoints/query.mdx +++ b/src/pages/core/entrypoints/query.mdx @@ -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. @@ -24,3 +24,5 @@ pub fn query( Ok(QueryResponse::default()) } ``` + +[`execute` endpoint]: ./execute.mdx diff --git a/src/pages/core/entrypoints/reply.mdx b/src/pages/core/entrypoints/reply.mdx index 690e0bea..623409c1 100644 --- a/src/pages/core/entrypoints/reply.mdx +++ b/src/pages/core/entrypoints/reply.mdx @@ -13,7 +13,7 @@ and interact with them. 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]. This endpoint gets invoked when you receive a response to a message you sent out @@ -71,4 +71,5 @@ pub fn reply(deps: DepsMut, env: Env, msg: cosmwasm_std::Reply) -> StdResult - 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. - For production builds you probably also want to install - [Docker](https://www.docker.com/), too. -
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. +
This is because we offer the [CosmWasm Optimizing Compiler], which uses + a Docker image to build the smallest contract possible in a deterministic fashion.
After installing Rust, you need to add the WebAssembly target. This is needed so @@ -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 diff --git a/src/pages/core/standard-library.mdx b/src/pages/core/standard-library.mdx index 7c34891c..46ddf38f 100644 --- a/src/pages/core/standard-library.mdx +++ b/src/pages/core/standard-library.mdx @@ -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 diff --git a/src/pages/core/standard-library/cryptography.mdx b/src/pages/core/standard-library/cryptography.mdx index 32c22a6e..02ef2e7e 100644 --- a/src/pages/core/standard-library/cryptography.mdx +++ b/src/pages/core/standard-library/cryptography.mdx @@ -20,8 +20,7 @@ documentation about them. 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]. ### secp256k1 @@ -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 @@ -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 diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx index b1eebc21..7125a154 100644 --- a/src/pages/core/standard-library/cryptography/bls12-381.mdx +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -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 @@ -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. TODO: Add example as soon as BLS12-381 is properly released + +[drand]: https://drand.love/ diff --git a/src/pages/core/standard-library/cryptography/ed25519.mdx b/src/pages/core/standard-library/cryptography/ed25519.mdx index 927762ad..ff25952d 100644 --- a/src/pages/core/standard-library/cryptography/ed25519.mdx +++ b/src/pages/core/standard-library/cryptography/ed25519.mdx @@ -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 @@ -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