# Develop Contract
First test if the starter works, and get your eyes used to rust test results:
All good.
src/lib.rs (opens new window) file contains wasm bindings. Wraps smart contract (handle, init, query) functions around rust functions. If you are not doing advanced wasm tweaking, don't touch it.
# Messages
Development begins in src/msg.rs (opens new window) which contains the input data structures of the smart contract.
# InitMsg
We will begin with InitMsg
(opens new window). This struct has the initial values that initializes smart contract from the code and feeds in the data required for logic setup.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
implements specified traits for this structure using macros. More read Rust docs / Derive (opens new window)
- Owner, creator and collateral comes from message transaction context, meaning owner and creator is the address signed the tx and collateral is funds sent along the message.
- counter_offer is strike price (opens new window).
# HandleMsg
Contract execution is branched using HandleMsg
enum. Each field defines a message and content of that message.
Canonical and Human Addresses Canonical Addresses represent binary format of crypto addresses. Human Addresses on the other hand are great for the UI. They are always a subset of ascii text, and often contain security checks - such as chain-prefix in Bech32, e.g. cosmos1h57760w793q6vh06jsppnqdkc4ejcuyrrjxnke
canonicalize(humanize(canonical_addr)) == canonical_addr
For more details: Names and Addresses (opens new window)
# QueryMsg
Smart contract state querying is branched using QueryEnum
. We will implement smart contract Config
query later.
# State
State (opens new window) handles state of the database where smart contract data is stored and accessed.
You have two options when modeling state:
- Singleton: contract saves only one instance of the structure using unique db key. We will use this in this tutorial.
- Structured store: models can be structured and stored dynamically. You can form one-to-one, one-to-many and many-to-many relations with indexing and lookup functionality.
# Contract Handlers
Lego bricks msgs, handler and state are defined. Now we need to bind them together in contract.rs (opens new window).
# Init
The init function will be called exactly once, before the contract is executed. It is a "privileged" function in that it can set configuration that can never be modified by any other method call. the first line parses the input from raw bytes into our contract-defined message. We then check if option is expired, then create the initial state. If expired, we return a generic contract error, otherwise, we store the state and return a success code:
The function is simple as it looks. Option expiration date check, save the state, and return response.
You will see this signature all over CosmWasm handler functions. Execution context passed in to handler using Deps, which contains Storage, API and Querier functions; Env, which contains block, message and contract info; and msg, well, no explanation needed.
Result<T, ContractError>
is a type that represents either success ([Ok
]) or failure ([Err
]). If the execution is successful returns T
type otherwise returns ContractError
. Useful.
# Handle
handle
method routes messages to functions. It is similar to Cosmos SDK handler design.
# Transfer
# Execute
You will see handle_execute
in plus and example smart contracts, but actually it is just a naming, nothing special.
Most of the function is same with transfer
. Just two new things: message fund check and sdk messages in return context.
# Query
This contracts query method is very simple, only configuration query. For more complex queries check cosmwasm-plus (opens new window) contracts. If you are starting to learn from zero, now you have 20 minutes of cosmwasm experience. Go ahead skim plus contracts to see the simplicity.
# Build
To simply build the code and see if it works:
# Tooling
It is good to keep the same coding style across smart contracts for readability and lint it for high code quality:
Normally Rust compiler does its job great, leads you to the solution for the errors, shows warnings etc. But it is always good to run linter on the code.
# Compile
This section compiles key commands from Compiling Contract (opens new window) doc. For more detailed read proceed to the documentation.
Basic compilation:
Optimized compilation:
Reproducible and optimized compilation:
You want to use the command above before deploying to the chain.
# Schema
We can also generate JSON Schemas that serve as a guide for anyone trying to use the contract. This is mainly for documentation purposes, but if you click on "Open TypeScript definitions" in the code explorer, you can see how we use those to generate TypeScript bindings.
You can see the generated schemas under simple-option/schema (opens new window)
Go ahead and explore schemas.