Interact via the CLI
Upload
In this section, you will upload a WASM contract to the blockchain. This involves using the
wasmd tx wasm store
command to upload the contract file, and then querying the blockchain to
obtain the unique code ID for the uploaded contract.
Upload code
You can upload your contract by running the command: wasmd tx wasm store
. In the following
example, we upload the hackatom.wasm
contract:
wasmd tx wasm store "./x/wasm/keeper/testdata/hackatom.wasm" \
--from alice \
--gas 1500000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test
./x/wasm/keeper/testdata/hackatom.wasm
is the path to the WASM file to upload--from alice
specifies the sender's account, in this case,alice
--gas 1500000
sets the gas limit for the transaction-y
automatically accepts the transaction--chain-id=docs-chain-1
specifies the chain ID of the blockchain-o json
outputs the result in JSON format--keyring-backend=test
specifies the keyring backend to use
The output looks like:
{
"height": "0",
"txhash": "57514909E7654EE7A1F90036ABDBDFF0B411C43ECC32315CD7759894337B6C4F",
"codespace": "",
"code": 0,
"data": "",
"raw_log": "",
"logs": [],
"info": "",
"gas_wanted": "0",
"gas_used": "0",
"tx": null,
"timestamp": "",
"events": []
}
From this output, we can get the transaction hash txhash
. Using this hash, we can fetch the code
ID.
wasmd q tx 2C19314D369E7EF3C77CBD1B33E02DB0401619B5C8E1B1E5BD15AB46C3704E96 -o json
The command will return a JSON object similar to the following:
{
...
"events": [
...
{
"type": "store_code",
"attributes": [
{
"key": "code_checksum",
"value": "3f4cd47c39c57fe1733fb41ed176eebd9d5c67baf5df8a1eeda1455e758f8514",
"index": true
},
{
"key": "code_id",
"value": "1",
"index": true
},
{
"key": "msg_index",
"value": "0",
"index": true
}
]
}
]
}
Inside the store_code
event, you can find the code_id
. To extract it, you can use the following
command:
RESP=$(wasmd q tx 2C19314D369E7EF3C77CBD1B33E02DB0401619B5C8E1B1E5BD15AB46C3704E96 -o json)
echo "$RESP" | jq -r '.events[]| select(.type=="store_code").attributes[]| select(.key=="code_id").value'
Below is the full script that uploads the code and fetches the code ID:
# Upload the contract
RESP=$(wasmd tx wasm store "./x/wasm/keeper/testdata/hackatom.wasm" \
--from alice \
--gas 1500000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test)
# Wait for the transaction to be processed
sleep 6
# Fetch the transaction details
RESP=$(wasmd q tx $(echo "$RESP"| jq -r '.txhash') -o json)
# Extract the code ID
CODE_ID=$(echo "$RESP" | jq -r '.events[]| select(.type=="store_code").attributes[]| select(.key=="code_id").value')
# Print code id
echo "* Code id: $CODE_ID"
Query Code ID Metadata
To query the metadata of a specific code ID, use the following command:
wasmd q wasm code-info $CODE_ID -o json
The command will return a JSON object similar to the following:
{
"code_id": "1",
"creator": "wasm1zxevglcy90hq49x8vvdckfrgd9ffndxf70ut0z",
"data_hash": "3F4CD47C39C57FE1733FB41ED176EEBD9D5C67BAF5DF8A1EEDA1455E758F8514",
"instantiate_permission": {
"permission": "Everybody",
"addresses": []
}
}
"code_id"
is the reference to the stored WASM code"creator"
is the address of the account that uploaded the code"data_hash"
is the checksum of the stored WASM code"instantiate_permission"
is the instantiate permission configuration. It is optional, and the default value isEverybody
, which means everybody can create an instance of the uploaded WASM code
Download code
You can download the code associated with a specific code ID by running the following command:
wasmd q wasm code $CODE_ID downloaded_code.wasm
This command retrieves the WASM code from the blockchain and saves it to a file named
downloaded_code.wasm
.
Instantiation
In this section, you will create a new instance of the uploaded WASM contract. This involves using
the wasmd tx wasm instantiate
command to instantiate the contract, and then querying the
blockchain to obtain the contract's address.
Create a new contract instance
First, set up the addresses for the accounts involved in the contract using wasmd keys show
command:
# Retrieve the address of Alice's account
ALICE_ADDR=$(wasmd keys show alice -a --keyring-backend=test)
# Retrieve the address of Bob's account
BOB_ADDR=$(wasmd keys show bob -a --keyring-backend=test)
# Define init parameters fo the contract
INIT="{\"verifier\":\"$ALICE_ADDR\", \"beneficiary\":\"$BOB_ADDR\"}"
Run the following command to instantiate the contract:
wasmd tx wasm instantiate "$CODE_ID" "$INIT" \
--admin="$ALICE_ADDR" \
--from alice \
--amount="100stake" \
--label "local0.1.0" \
--gas 1000000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test
wasmd tx wasm instantiate "$CODE_ID" "$INIT"
instantiates the contract using the specified code ID and initial parameters--admin="$ALICE_ADDR"
specifies Alice as the admin who can later update the contract--from alice
specifies Alice as the sender of the transaction--amount="100stake"
: Sends100 stake
to the contract upon instantiation--label "local0.1.0"
assigns a label to this contract instance for easy identification--gas 1000000
sets the gas limit for the transaction-y
automatically accepts the transaction without prompting for confirmation--chain-id=docs-chain-1
specifies the chain ID of the blockchain-o json
outputs the result in JSON format--keyring-backend=test
specifies the keyring backend to use
Query the Contract Address
To retrieve the address of the newly instantiated contract you can use
wasmd query wasm list-contract-by-code
command:
wasmd query wasm list-contract-by-code "$CODE_ID" -o json
The output lists all contracts instantiated from the specified code ID:
{
"contracts": ["wasm1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrss5maay"],
"pagination": {
"next_key": null,
"total": "0"
}
}
Below is the full script that combines all the steps:
# Set up addresses
ALICE_ADDR=$(wasmd keys show alice -a --keyring-backend=test)
BOB_ADDR=$(wasmd keys show bob -a --keyring-backend=test)
INIT="{\"verifier\":\"$ALICE_ADDR\", \"beneficiary\":\"$BOB_ADDR\"}"
# Instantiate the contract
RESP=$(wasmd tx wasm instantiate "$CODE_ID" "$INIT" \
--admin="$ALICE_ADDR" \
--from alice \
--amount="100stake" \
--label "local0.1.0" \
--gas 1000000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test)
# Wait for the transaction to be processed
sleep 6
# Query the contract address
CONTRACT=$(wasmd query wasm list-contract-by-code "$CODE_ID" -o json | jq -r '.contracts[-1]')
# Print the contract address
echo "* Contract address: $CONTRACT"
Query Contract Metadata
To query the metadata of a specific contract, use the following command:
wasmd q wasm contract $CONTRACT -o json
The command will return a JSON object similar to the following:
{
"address": "wasm14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s0phg4d",
"contract_info": {
"code_id": "1",
"creator": "wasm1zxevglcy90hq49x8vvdckfrgd9ffndxf70ut0z",
"admin": "wasm1zxevglcy90hq49x8vvdckfrgd9ffndxf70ut0z",
"label": "local0.1.0",
"created": {
"block_height": "787",
"tx_index": "0"
},
"ibc_port_id": "",
"extension": null
}
}
"address"
is the address of the contract on the blockchain. It uniquely identifies the contract and is used for interacting with it."code_id"
is the reference to the stored WASM code from which the contract was instantiated."creator"
is the blockchain address of the account that initially instantiated the contract. It indicates who created the contract instance."admin"
is the address of the account that has administrative privileges over the contract, such as the ability to execute migrations. This field is optional and can be set during instantiation."label"
is an optional field used to give a human-readable label to the contract. It helps in identifying the contract instance, especially when multiple instances of the same code are deployed."created"
section provides details about the transaction in which the contract was instantiated, including the block height at which the contract was created and the index of the transaction within the block."ibc_port_id"
is the Port ID for Inter-Blockchain Communication IBC. If the contract is set up to interact with other blockchains via IBC, this field will contain the relevant port ID."extension"
is is an extension point to store custom metadata within the persistence model
Instantiation with Predictable Address
Instantiation with a predictable address refers to the process of deploying a smart contract on a blockchain such that the resulting contract address can be determined in advance. This is particularly useful in scenarios where you need to know the contract address before its actual deployment for purposes like pre-configuring other contracts or systems to interact with it.
Create a new contract instance with predictable address
First, we need to define a salt value. The salt is a unique value that, when combined with the contract's code ID and initialization parameters, helps derive a unique and predictable contract address. This ensures that even if the same contract code and initialization parameters are used, different salt values will result in different contract addresses.
SALT=10
Run the following command to instantiate the contract with predicatable address:
wasmd tx wasm instantiate2 "$CODE_ID" "$INIT" "$SALT" \
--admin="$ALICE_ADDR" \
--from alice \
--amount="100stake" \
--label "local0.1.0" \
--gas 1000000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test
wasmd tx wasm instantiate2 "$CODE_ID" "$INIT" "$SALT"
instantiates a new contract instance with the specified code ID, initialization parameters, and the salt value--admin="$ALICE_ADDR"
specifies Alice as the admin who can later update the contract--from alice
specifies Alice as the sender of the transaction--amount="100stake"
: Sends100 stake
to the contract upon instantiation--label "local0.1.0"
assigns a label to this contract instance for easy identification--gas 1000000
sets the gas limit for the transaction-y
automatically accepts the transaction without prompting for confirmation--chain-id=docs-chain-1
specifies the chain ID of the blockchain-o json
outputs the result in JSON format--keyring-backend=test
specifies the keyring backend to use
Query contracts by code id
To get a list of contracts instantiated from a specific Code ID, you can use the following command. This will query the blockchain and return a JSON object containing the addresses of the contracts associated with the given Code ID.
wasmd q wasm list-contract-by-code $CODE_ID -o json
The command will return a JSON object similar to the following:
{
"contracts": [
"wasm1wug8sewp6cedgkmrmvhl3lf3tulagm9hnvy8p0rppz9yjw0g4wtqhs9hr8",
"wasm19ph090ka8tzrd2wrp8gnn7lachwt7r2npvf6rdnd3ha3jv5n5gqquzcpd0"
],
"pagination": {
"next_key": null,
"total": "0"
}
}
In this example, there are two contracts associated with the Code ID.
Query contracts by creator
To get a list of contracts instantiated by a specific creator, you can use the following command. This will query the blockchain and return a JSON object containing the addresses of the contracts associated with the given creator's address.
wasmd q wasm list-contracts-by-creator $BOB_ADDR -o json
The command will return a JSON object similar to the following:
{
"contract_addresses": [],
"pagination": {
"next_key": null,
"total": "0"
}
}
In this example, there are no contract addresses associated with Bob's address.
Execution
Executing a command on a WASM contract involves sending a message to the contract.
Execute a command on a wasm contract
First, we have to define the message to send to the contract. In this example we want to call the release function of the contract:
MSG='{"release":{}}'
Run the following command to execute the message on the contract:
wasmd tx wasm execute "$CONTRACT" "$MSG" \
--from alice \
--gas 1000000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test
"$CONTRACT"
specifies the address of the contract"$MSG"
specifies the message to execute--from alice
specifies Alice as the sender of the transaction--gas 1000000
sets the gas limit for the transaction-y
automatically accepts the transaction without prompting for confirmation--chain-id=docs-chain-1
specifies the chain ID of the blockchain-o json
outputs the result in JSON format--keyring-backend=test
specifies the keyring backend to use
By querying the transaction using the txhash
, we can check the events emitted by the contract. The
output will look similar to the following:
{
...
"events": [
...
{
"type": "message",
"attributes": [
{
"key": "action",
"value": "/cosmwasm.wasm.v1.MsgExecuteContract",
"index": true
},
{
"key": "sender",
"value": "wasm1hvgm6p76gccgg4dl4caa8a7v03dsqww6r9sk4g",
"index": true
},
{
"key": "module",
"value": "wasm",
"index": true
},
{
"key": "msg_index",
"value": "0",
"index": true
}
]
},
{
"type": "execute",
"attributes": [
{
"key": "_contract_address",
"value": "wasm1wug8sewp6cedgkmrmvhl3lf3tulagm9hnvy8p0rppz9yjw0g4wtqhs9hr8",
"index": true
},
{
"key": "msg_index",
"value": "0",
"index": true
}
]
},
]
}
"events"
are logs emitted by the contract during its execution, providing detailed information
about the actions performed and the resulting state changes.
Below is the full script that combines all the steps for executing a command on a WASM contract and querying the events:
# Define the message to send to the contract, in this case a "release" command
MSG='{"release":{}}'
# Execute the contract with the specified message
RESP=$(wasmd tx wasm execute "$CONTRACT" "$MSG" \
--from alice \
--gas 1000000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test)
# Wait for the transaction to be processed
sleep 6
# Query the transaction using its hash to check the events emitted by the contract
wasmd q tx $(echo "$RESP" | jq -r '.txhash') -o json | jq
Query contract state
To query the state of a WASM contract, you can use the following command.
wasmd query wasm contract-state all "$CONTRACT" -o json
The output will look similar to this:
{
"models": [
{
"key": "636F6E666967",
"value": "eyJ2ZXJpZmllciI6Indhc20xaHZnbTZwNzZnY2NnZzRkbDRjYWE4YTd2MDNkc3F3dzZyOXNrNGciLCJiZW5lZmljaWFyeSI6Indhc20xcGEyOWxhYzVzODVrZ2o3cG45ejZnYzB0NHNxZ3psbGNndWhmMjQiLCJmdW5kZXIiOiJ3YXNtMWh2Z202cDc2Z2NjZ2c0ZGw0Y2FhOGE3djAzZHNxd3c2cjlzazRnIn0="
}
],
"pagination": {
"next_key": null,
"total": "0"
}
}
Models
are key-value pairs representing the state data of the contract base64-encoded.
We can decode the contract state using the following command:
wasmd query wasm contract-state all "$CONTRACT" -o json | jq -r '.models[0].value' | base64 -d
The output will be similar to the following:
{
"verifier": "wasm1hvgm6p76gccgg4dl4caa8a7v03dsqww6r9sk4g",
"beneficiary": "wasm1pa29lac5s85kgj7pn9z6gc0t4sqgzllcguhf24",
"funder": "wasm1hvgm6p76gccgg4dl4caa8a7v03dsqww6r9sk4g"
}
Migration
Migration is the process of upgrading an existing contract to a new version without changing its address or losing its state. This ensures that the contract can evolve over time while preserving the data of the original contract.
Migrate a wasm contract to a new code version
First, upload the new contract code to the blockchain:
RESP=$(wasmd tx wasm store "./x/wasm/keeper/testdata/burner.wasm" \
--from alice \
--gas 1100000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test)
Query the transaction to get the code ID of the newly uploaded code:
RESP=$(wasmd q tx $(echo "$RESP" | jq -r '.txhash') -o json)
BURNER_CODE_ID=$(echo "$RESP" | jq -r '.events[] | select(.type=="store_code").attributes[] | select(.key=="code_id").value')
Set up the migration message that will be used during the migration process.
DEST_ACCOUNT=$(wasmd keys show bob -a --keyring-backend=test)
MIGRATION_MSG="{\"payout\": \"$DEST_ACCOUNT\"}"
Next, migrate the existing contract to use the new code ID.
RESP=$(wasmd tx wasm migrate "$CONTRACT" "$BURNER_CODE_ID" "$MIGRATION_MSG" \
--from alice \
--chain-id=docs-chain-1 \
-y \
-o json \
--keyring-backend=test)
Finally, query the transaction to check its status and view the results
wasmd q tx $(echo "$RESP" | jq -r '.txhash') -o json
The output will be similar to the following:
{
...
"events": [
...
{
"type": "migrate",
"attributes": [
{
"key": "code_id",
"value": "3",
"index": true
},
{
"key": "_contract_address",
"value": "wasm1wug8sewp6cedgkmrmvhl3lf3tulagm9hnvy8p0rppz9yjw0g4wtqhs9hr8",
"index": true
},
{
"key": "msg_index",
"value": "0",
"index": true
}
]
},
]
}
In this case, the contract was migrated to use code ID 3.
Below is the full script that combines all the steps for a wasm contract to a new code version
# Upload the new contract code
RESP=$(wasmd tx wasm store "./x/wasm/keeper/testdata/burner.wasm" \
--from alice \
--gas 1100000 \
-y \
--chain-id=docs-chain-1 \
-o json \
--keyring-backend=test)
# Wait for the transaction to be processed
sleep 6
# Query the transaction to get the code ID
RESP=$(wasmd q tx $(echo "$RESP" | jq -r '.txhash') -o json)
BURNER_CODE_ID=$(echo "$RESP" | jq -r '.events[] | select(.type=="store_code").attributes[] | select(.key=="code_id").value')
# Get the destination account address
DEST_ACCOUNT=$(wasmd keys show bob -a --keyring-backend=test)
# Define the migration message
MIGRATION_MSG="{\"payout\": \"$DEST_ACCOUNT\"}"
# Migrate the contract to the new code ID
RESP=$(wasmd tx wasm migrate "$CONTRACT" "$BURNER_CODE_ID" "$MIGRATION_MSG" \
--from alice \
--chain-id=docs-chain-1 \
-y \
-o json \
--keyring-backend=test)
# Wait for the transaction to be processed
sleep 6
# Query the migration transaction
wasmd q tx $(echo "$RESP" | jq -r '.txhash') -o json | jq
Query contract history
You can query the history entries for a contract by running the following command:
wasmd q wasm contract-history $CONTRACT -o json
This command retrieves the history of changes made to the specified contract, including initial instantiation and subsequent migrations. The command will return a JSON object similar to the following:
{
"entries": [
{
"operation": "CONTRACT_CODE_HISTORY_OPERATION_TYPE_INIT",
"code_id": "1",
"updated": {
"block_height": "787",
"tx_index": "0"
},
"msg": {
"verifier": "wasm1zxevglcy90hq49x8vvdckfrgd9ffndxf70ut0z",
"beneficiary": "wasm1xxt02kmatpk5gwhmkrnpql02mfe0h4zcqvqeg0"
}
},
{
"operation": "CONTRACT_CODE_HISTORY_OPERATION_TYPE_MIGRATE",
"code_id": "2",
"updated": {
"block_height": "1718",
"tx_index": "0"
},
"msg": {
"payout": "wasm1xxt02kmatpk5gwhmkrnpql02mfe0h4zcqvqeg0"
}
}
],
"pagination": {
"next_key": null,
"total": "0"
}
}
Each entry
provides details about a specific operation performed on the contract. Entry Fields:
"operation"
is the type of operation performed, such as initialization or migration."code_id"
is the code ID associated with the operation."updated"
contains information about when the operation was performed."msg"
is the message payload associated with the operation.
Set contract admin
The admin is the only address that can migrate a contract. The admin can be updated by the current admin with the following command:
wasmd tx wasm set-contract-admin \
"$CONTRACT" \
"$BOB_ADDR" \
--from alice \
--keyring-backend=test \
--chain-id=docs-chain-1 \
-y
After running this command, Bob will be the new admin of the contract, and only he will have the authority to migrate the contract to a new code version or further update the admin role.
Clear contract admin
Clearing the admin address from a WASM contract removes the ability to migrate the contract to a new code version. This action effectively locks the contract, preventing any further migrations.
Run the following command to clear the contract admin:
wasmd tx wasm clear-contract-admin \
"$CONTRACT" \
--from bob \
--keyring-backend=test \
--chain-id=docs-chain-1 \
-y
After running this command, the contract will no longer have an admin, and no one will be able to migrate the contract to a new code version.