Executing smart contracts
Once you've deployed a smart contract from your DAO you'll then likely want to start using it. The way to modify the state of a contract or tell it to perform an action on cosmwasm is to execute a message on it. Here we'll walk through the process of executing a message on a DAO's staking contract to update its unstaking duration and in the process learn about controlling smart contracts from a DAO DAO DAO.
Background
With CosmWasm there are a number of message types that can be executed by the chain. These message types can do things like stake tokens with validators, send tokens to addresses, and manage smart contracts. The message types are enumerated here. A "custom" message on a DAO DAO proposal can cause any of these message types to be executed.
In order to execute one of those message types it needs to be converted into JSON. JSON allows us to manually type out messages in a human readable format that the computer can convert into the Rust data structures you can see in the aforementioned enum.
JSON conversion
Under the hood a Rust library called Serde JSON is used to do this conversion from human readable JSON to computer readable data. You can see the linked docs for all the details about how this conversion happens. Here's an example to build some intuition:
Lets say we have a Rust enum that looks something like this:
pub enum Msg {
House(HouseMsg),
Bar {
baz: String,
},
BluBla {}
}
pub struct HouseMsg {
width: Uint128,
height: Decimal,
depth: u64,
}
Lets see what the variants of this Rust enum look like in JSON,
starting with House
.
House
Say I want to write a House
with a width
of 100
and a height of
0.12
and a depth of 12
. The JSON for that would look like this:
{
"house": {
"width": "100",
"height": "0.12",
"depth": 12
}
}
In CosmWasm Uint128
values are large integer values and to write one
in JSON form you surround the number with quotes. The same applies to
the Decimal
type. For regular Rust integer types like u64
we can
just write those out as normal.
Bar
Writing a Bar
is really similar to a Foo. Even though for the Foo
the data is in a separate struct
the serialized version looks the
same. Here's what a Bar
with a baz
of "zoop"
looks like:
{
"bar": {
"baz": "zoop"
}
}
For comparason, here's how you'd construct that same Bar
in Rust:
Msg::Bar { baz: "zoop".to_string() }
Blu
A BluBla
is just like a Bar
or a Foo
but it doesn't have any data:
{
"blu_bla": {}
}
Notice that the BluBla
gets converted from camel case to snake case
during serialization. This is not a hard rule for CosmWasm contracts,
but most will do this.
Executing a contract
Now that we understand how messages are put together, let's try writing a custom message to update the unstaking duration for a DAO. We'll start by collecting the relevant addresses for our message. For our purposes we'll need the DAO address and the staking contract address. Those can be found in under the "Staking" and "DAO" addresses in the "Addresses" section of your DAO page.
For this walk through we'll use <DAO>
and <STAKING>
as placeholders
for those addresses. When you're writing your message you'll want to
replace those with the addresses you're using.
We can start with a basic WASM execute message:
{
"wasm": {
"execute": {
"contract_addr": "",
"msg": {},
"funds": []
}
}
}
Let's fill in this basic message with the address of our staking contract. The staking contract will be the contract we want to execute this message on as we want to tell it to change the unstaking duration.
{
"wasm": {
"execute": {
"contract_addr": "<STAKING>",
"msg": {},
"funds": []
}
}
}
If you look at the type of the msg
field on in the docs you'll see
it is a Binary
type. The Binary
type in CosmWasm is a base64
encoded JSON message. From your terminal you can create one by running:
echo '<JSON you'd like to encode>' | base64
Happily, the DAO DAO UI will automatically do that conversion for you
so we can just put the JSON for the message we want to execute in that
field. We can find the format of the message we'd like to execute by
looking at the UpdateConfig
message
in the DAO DAO staking contract.
We see that the message variant we want is UpdateConfig
so in JSON
that becomes update_config
. Likewise, the admin field is a string so
we call it admin
. Inspecting the Duration
type we see that it has
a Height
and Time
variant. We select the Time
variant and
following our rules of enum serialzation the duration
field becomes
{ "time": <VALUE> }
As for the actual values, lets leave the admin as the DAO and update
the unstaking duration to ten seconds. Our msg
field will then look
like this:
{
"update_config": {
"admin": "<DAO>",
"duration": {
"time": 10
}
}
}
The last field on the WASM message is the funds
field. We could use
this field to send some native tokens (for example, Juno) along with
our message. We don't want to send money to our staking contract so
we'll leave that empty.
This makes our final WASM message:
{
"wasm": {
"execute": {
"contract_addr": "<STAKING>",
"msg": {
"update_config": {
"admin": "<DAO>",
"duration": {
"time": 10
}
}
},
"funds": []
}
}
}
If we throw this into a custom message on a DAO DAO DAO proposal and execute it it'll change the unstaking duration.