Juno Network Halt Analysis

secdao
3 min readApr 7, 2022

At 4am PST, 4/5/2022 the Juno network (juno-1) halted at block 2578097 which was proposed by the ‘Chorus One’ validator. ‘Chorus One’ wasn’t involved, but simply had the poor luck of submitting the bad block.

Several theories were posited:

  1. Some of the validators did not have the Moneta patch applied allowing Juno to be exploited. The Moneta patch prevented a single validator from halting the Juno network under certain conditions available in an earlier binary
  2. The Lupercalia upgrade went awry with the incorrect binary being presented to Cosmovisor on some of the validators.
  3. >⅓ of validators upgraded too early and hit the ⅓ threshold of validators unavailable, halting the Juno network.
  4. A smart contract was used to maliciously trigger a 0-day exploit that stopped the chain.

All theories were actively investigated upon ideation and with action being taken for future improvements.

At ~3.30pm PST, 4/5/2022 it was established that a malicious mart contract had caused the halt. Our friends over at strangelove-ventures managed to reproduce the issue. Take a look at https://github.com/strangelove-ventures/ibc-test-framework/pull/7 .

Failed Block #2578097

Mintscan presents block 2578097 here.

Normal activities appear there, like some IBC events and ‘Fortis Oeconomia’ contracts but contract 184 ‘satoshi-test’ looks suspicious. It labels itself as crates.io:hello-world but was executed 474 times.

Reversing a Juno contract

First off lets list the contract on chain and take a look.

#  junod query wasm list-contracts-by-code 184 --node https://rpc-juno.nodes.guru:443 --chain-id juno-1contracts:- juno188lvtzkvjjhgzrakha6qdg3zlvps3fz6m0s984e0wrnulq4px9zqhnleyepagination:next_key: nulltotal: "0"next_key: null

That matches, let’s pull down the contract locally.

# junod query wasm code 184 satoshi_ONCHAIN.wasm --node https://rpc-juno.nodes.guru:443 --chain-id juno-1

To view the contract open up vscode and install the `dtsvet.vscode-wasm` plugin. This will let us view the contract as a .wat file. Right click on the satoshi_ONCHAIN.wasm file and select ‘Save as WebAssembly text file’.

Now we have a human readable version of the contract. At the bottom of the file the most easily grokked information can be found, though its still complex.

Comparing contracts

In order to compare the suspect contract we need an actual hello-world contract. A real ‘hello-world’ wasm contract can be found here https://github.com/InterWasm/cw-template . Following the same process we can obtain the cw_contract.wasm and from that create the cw_contract.wat.

Given the complexity of these wat files, it’s helpful to use a visualizing tool like octopus from fuzzing labs:

The result of running the tool against the 2 theoretically similar contracts reveals 2 very different structures to the call graph.

satoshi-test call graph
cw_template call graph

Similarly we can look at the cfg graphs and infer large differences in what they do..

cw_contract (left) satoshi_test (right)

--

--