Skip to main content

Verifying smart contracts

This is a vital step to ensure that the appropriate contract is being executed. Verifying any smart contract deployed on the blockchain is possible. Take a practical example where you have an active contract on the blockchain, and you wish to determine its code name and version.

Inspect code

We can query the contract information using the following command:

terpd q wasm contract-state raw terp1cug98emkqmj8n3n2tnm9d04e7q52r9lrjgaud9hecnqw6pth8fvse96uwj 636F6E74726163745F696E666F --node https://rpc.testnet.terp.network:443 --chain-id 90u-4 --output json | jq  -r .data | base64 -d | jq
{
"contract": "crates.io:terp5",
"version": "0.1.0"
}

What exactly is 636F6E74726163745F696E666F in the Query above?

The ContractInfo is stored under the contract_info key, which translates to 636F6E74726163745F696E666F in hex format, as documented here.

To obtain the required hash, we first need to find the corresponding code ID. Here is the process for obtaining it:

terpd q wasm contract terp1cug98emkqmj8n3n2tnm9d04e7q52r9lrjgaud9hecnqw6pth8fvse96uwj  --node https://rpc.testnet.terp.network:443 --output json  | jq
{
"address": "terp1cug98emkqmj8n3n2tnm9d04e7q52r9lrjgaud9hecnqw6pth8fvse96uwj",
"contract_info": {
"code_id": "00",
"creator": "terp1...",
"admin": "terp1...",
"label": "terp5 0.1.0",
"created": null,
"ibc_port_id": "",
"extension": null
}

We now have code_id along with creator and admin addresses. The following query will retrieve the hash:

terpd q wasm code 85 85_code.wasm --node https://rpc-testnet.terp.network:443 --chain-id 90u-4
Downloading wasm code to 85_code.wasm

Now retrieve the hash:

sha256sum 85_code.wasm
dc02d33e40511396a5895ac0b1c3b9d53803e115f605ad5cbfe8035a031bbd3f 85_code.wasm

Find the original code

The hashes for the cw-plus smart contracts are published alongside the contract code, which can be found at cw-plus inside a checksums.txt file. Here is an example:

fe34cfff1cbc24594740164abb953f87735afcdecbe8cf79a70310e36fc13aa0  cw1155_base.wasm
de49426e9deed6acf23d5e930a81241697b77b18131c9aea5c3ca800c028459e cw1_subkeys.wasm
c424b66e7f289cef69e1408ec18732e034b0604e4b22bfcca7546cc9d57875e3 cw1_whitelist.wasm
e462d44a086a936c681f3b3389d50b8404ce2152c8f0fb32b257064576210c03 cw1_whitelist_ng.wasm
0b2e5d5dc895f8f49f833b076a919774bb5b0d25bf72819e9a1cbdf70f9bf79b cw20_atomic_swap.wasm
6c1fa5872e1db821ee207b5043d679ad1f57c40032d2fd01834cd04d0f3dbafb cw20_base.wasm
f00759aa9a221efeb58b61a1a1d4cc4281cdce39d71ac4d8d78d234f03b3b0eb cw20_bonding.wasm
b6041789cc227472c801763c3fab57a81005fb0c30cf986185aba5e0b429d2e6 cw20_escrow.wasm
91b35168d761de9b0372668dd8fa8491f2c8faedf95da602647f4bade7cb9f57 cw20_ics20.wasm
d408a2195df29379b14c11277f785b5d3f57b71886b0f72e0c90b4e84c2baa4a cw20_merkle_airdrop.wasm
934ba53242e158910a2528eb6c6b82deb95fe866bbc32a8c9afa7b97cfcb9af4 cw20_staking.wasm
ac1f2327f3c80f897110f0fca0369c7022586e109f856016aef91f3cd1f417c1 cw3_fixed_multisig.wasm
785340c9eff28e0faeb77df8cca0fafee6b93a1fa033d41bda4074cd97600ec1 cw3_flex_multisig.wasm
87b3ad1dee979afc70e5c0f19e8510d9dcc8372c8ef49fc1da76725cad706975 cw4_group.wasm
4651e90405917897f48d929198278f238ec182ac018c414ee22f2a007a052c1e cw4_stake.wasm

Compile yourself

Instead of relying on pre-existing hashes, we can generate the hash for our contract ourselves. We can use rust-optimizer not only to create performant and compact code, but also to ensure that the output code is deterministic and can be compared accurately. In fact, the hashes provided in the previous example were all produced using rust-optimizer.

docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/workspace-optimizer:0.12.11

On Windows, you can use the following command instead:

docker run --rm -v ${pwd}:/code `
--mount type=volume,source="$("$(Split-Path -Path $pwd -Leaf)")_cache",target=/code/target `
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry `
cosmwasm/rust-optimizer:0.12.11

The hashes will be generated at ./artifacts/checksums.txt.

The hashes will be generated at ./artifacts/checksums.txt.

You can find the value and compare it to the value we obtained.

cat ./artifacts/checksums.txt | grep terp5.wasm
dc02d33e40511396a5895ac0b1c3b9d53803e115f605ad5cbfe8035a031bbd3f terp5.wasm
diff  <(echo "dc02d33e40511396a5895ac0b1c3b9d53803e115f605ad5cbfe8035a031bbd3f" ) <(echo "dc02d33e40511396a5895ac0b1c3b9d53803e115f605ad5cbfe8035a031bbd3f")

If the hashes do match, then the contract is verified.