Smart Contract Verification
Recently someone asked securityDAO, “How can I trust that a smart contract on-chain in Juno is the same as the version in Github?”.
This is different from the question of “Does the smart contract do what it’s supposed to do securely”. In this blog post we’re explaining how one can make sure that the contract published on git is the same as on chain. Evaluating the intent of a smart contract compared to its content is best answered by smart contract developers and security experts via an audit. Important smart contract projects should be audited by 3rd party experts, enjoy the remediation of issues discovered and the audit subsequently published.
All members of the Juno community should be able to verify that the on-chain CosmWasm smart contract matches the source code commits referenced in an audit when engaging with dApps and DeFi instruments in the Juno ecosystem.
Anyone can verify that source code matches bytecode if the source code is publicly available on Github.
This tutorial serves as a guide for how to do this.
The verification process can be broken into 4 steps:
- downloading cosmwasm .wasm file from on-chain using junod
- finding the most likely commit from the contract github repo and building into .wasm
watfiles or comparing hashes
- repeating steps 1–3 until a matching commit and compiler settings are found
Previous approaches focused on comparing hashes
Why not just hashes instead of WAT?
Hashes don’t provide insight into where differences in contracts lie, and may be affected by optimizations applied to the resulting compiled contract. WAT can guide you towards the commits in repo with dependency changes and other key signals to help understand why a hash may not be matching and where to check next.
- Docker https://www.docker.com/products/docker-desktop/
- Rust https://www.rust-lang.org/tools/
- git https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
- junod ( git clone https://github.com/CosmosContracts/juno && cd juno && make install ) or
This tutorial should work for macOS (not M1) and Linux (Ubuntu 20.04). Windows may need to change the path slash direction and escaping differently. Windows users should strongly consider using Ubuntu 20.04 WSL. macOS M1 arm processor laptops are not yet fully supported by the software stack so this tutorial may not work with arm chips now but that may change in the future.
Getting the contract on-chain
to get a contract on chain you can use an rpc query from the cosmos sdk equivalent for the chain you are using (wasmd, junod etc)
To identify smart contracts in Juno you will need to know the smart contract code.
Smart Contracts can be viewed using sdk commands or from mintscan
- find our contract of interest
- write down the id column of mintscan Id this is the wasm code , this code increments for every new contract so a new contact should have one of the largest codes
- write down the created timestamp
- write down Contract name field
- ensure that you know who the Creator address belongs to
using juno sdk
sdk can also be used but its more difficult to aggregate contract metadata
- junod query wasm list-code — node https://rpc-juno.nodes.guru:443 — chain-id juno-1
- use data hash data_hash: to get meta data
- junod query wasm list-contracts-by-code 42 — node https://rpc-juno.nodes.guru:443 — chain-id juno-1
- junod query wasm contract juno1lwyg9cj80ffrwedgtflcs5uc2g8kjj7kg8s740l3sp8sfz82e9gspqz6jm — node https://rpc-juno.nodes.guru:443 — chain-id juno-1
- junod query wasm contract-state all juno1lwyg9cj80ffrwedgtflcs5uc2g8kjj7kg8s740l3sp8sfz82e9gspqz6jm — node https://rpc-juno.nodes.guru:443 — chain-id juno-1
- junod query wasm contract-history juno1lwyg9cj80ffrwedgtflcs5uc2g8kjj7kg8s740l3sp8sfz82e9gspqz6jm — node https://rpc-juno.nodes.guru:443 — chain-id juno-1
Find the crates.io:cw3-multisig named WAGMI
Click on WAGMI
Note: the wasm code for the WAGMI contract (42)
For cosmos chains other than juno the rpc endpoint and command tree may be different:
- junod query wasm code 42 WAGMI_ONCHAIN.wasm — node https://rpc-juno.nodes.guru:443 — chain-id juno-1
Building wasm from repo
- find the code repo or be given access to the repo if its a private code repo
- follow the steps in https://docs.cosmwasm.com/docs/1.0/smart-contracts/compilation to produce wasm (summarized below )
- cd into the contract folder.
- run %sudo docker run — rm -v “(pwd)”:/code −−mounttype=volume,source=”(basename “$(pwd)”)_cache”,target=/code/target
— mount type=volume,source=registry_cache,target=/usr/local/cargo/registry
- cd into artifact folder in root of the github repo
- the compiled
.wasmfile should be within
- contract folders are often under
cargo.tomlshould be in the folder
- make sure you are in the right contract folder with the right commit if the project has multiple contracts
- if you build on a different commit than deployed you may see a different version built
- if the contract was deployed a long time a go try to determine the commit(possibly release) that was used when the contract was deployed.
- if the contract was deployed recently than the latest commit on the main repo branch is the likey one to use or the latest release if one is provided
- if the contract was built without an optimzer or different compiler settings than the files will not match completely
Verify Contract Matching
We have 3 options:
Check the hash
- check the hash (
sha-256) of the wasm files ( if the checksum matches we have a winner)
- check the creator address of the contract
- covert wasm to wat and look at the differences between the files (git diff)
- checking hash
- $HASHSOURCE = sha256sum WAGMI_SOURCE.wasm
- $HASHONCHAIN = sha256sum WAGMI_ONCHAIN.wasm
- diff <(echo “HASHSOURCE”)<(echo”HASHONCHAIN”)>
See cosmwasm docs: https://docs.cosmwasm.com/docs/1.0/smart-contracts/verify/
Check the creators address
Ask the following questions of the creator address to see if any red flags stand out:
- Does this address match previous uploads or other contracts?
- Are you familiar with the creator address?
- Have others used contracts from this creator address before?
Convert wasm to wat
- click upload
- select .wasm file
- copy and paste .wat output into new text file in editor and save as WAGMI_ONCHAIN.wat
OR use wasm2wat cli tool
- go to wabt repo https://github.com/WebAssembly/wabt
- follow installation instructions with make for your operating system
- run wasm2wat WAGMI_ONCHAIN.wasm -o WAGMI_ONCHAIN.wat
OR use vscode extension
Once installed you can now right or cmd click on a file and select save as Webassemby text file to save a wat file from wasm
Repeat the process for the source file but save new text file in editor as WAGMI_SOURCE.wat
You should now have 2 wat files one source and one from chain
Analyzing WAT Files
git diff --no-index --unified=0 WAGMI_ONCHAIN.wat WAGMI_SOURCE.wat
- if there is no output response than the files are the same , you can check the command against 2 paths to the same file to verify this
- if there is output you will see the highlighted difference and can exit the terminal by pressing esc and than q
If there is no git output then congrats you have verified this contracts source code without relying on anyone else.
Ultimately the goal is that there should be no differences between wat. With some differences you may not be sure as to what code is different.
Differences from the chain version can be due to
- different compiler optimization or flags
- upgrading dependencies
- difference in commit used for building the contract
- bad actor trying to slip in a dangerous update
Binary authorization and transparent builds
If you must be 100% sure the contract you are using is the correct one than you must prove that the CosmWasm contract source code matches the on chain wasm, and that it is indeed authored by the repo owner.
While many of the web2 concepts like binary authorization of builds is implicit in the contract ownership structure of CosmWasm, i.e. cryptographic identity of Junø wallets for the deployed artifacts is sufficient to establish upload-time identity. However, everything up until the upload step can and should be additionally secured the Verified committer process on GitHub — cryptographically signing the code at a specific commit hash;
An additional layer of transparency can be to gain access to the logs and resulting artifacts of the build itself in the build system used by the repo authors, e.g. GitHub Action, GitLab CI etc.
If you need help with smart contract audits, on-chain analytics for Cosmos / IBC, SecurityDAO can be reached through the means listed below.