Know SVM Upgrade V0.0.4

in SVM - EVM on STEEM19 days ago (edited)

Hi everyone,

This post serves as the comprehensive technical deep-dive into what the v0.0.4 upgrade actually does, why it is urgent, and exactly how validators must execute it.

If you are running an SVM validator, please read this document carefully. This is a state-breaking, coordinated upgrade. It is not safe to update ad-hoc or at your own pace.

Grok Images Prompt : A wide, cinematic 3D render of a highly secure, futuristic blockchain network upgrade. In the center, a glowing, impenetrable digital shield protects a core network of interconnected, glowing cyan and deep blue nodes, representing validator consensus. Sleek, abstract cryptographic geometry and data streams flow smoothly around the shield. The aesthetic is professional, enterprise-grade cybersecurity, with a dark navy and metallic silver color palette accented by bright cyan light. High detail, Unreal Engine 5 style, volumetric lighting, wide aspect ratio 16:9, suitable for a professional tech blog header. No text.


What This Upgrade Is and Why It Is Urgent

Recently, Cosmos Labs disclosed a critical vulnerability: chains running cosmos/evm older than v0.6.2 or v0.7.2 must upgrade immediately.

The bug is a balance underflow in the EVM StateDB.SubBalance. If a transaction attempts to subtract more than an account's balance, it silently wraps around to ~2^256 instead of erroring. This has already been exploited to drain funds on MANTRA, TAC, and KiiChain (Aug 20–22, 2026) via a crafted vesting-account contract calling a balance-modifying precompile. Because the shared cmn.BalanceHandler code path is used by every precompile that touches account balances (staking, distribution, bank, ics20, gov, and SVM's own steembridge BridgeOut), this is exploitable by any user via a crafted transaction. No malicious validator is required.

SVM was pinned to the vulnerable cosmos/evm v0.7.1. This upgrade bundles three critical changes into one coordinated event to secure the network:

  1. cosmos/evm v0.7.1 → v0.7.2: Applies the underflow fix (SubBalance now panics on underflow instead of wrapping), a ParseAmount fix, a feemarket gas-overflow clamp, and mirrors the ProcessProposal handler into app/evm.go.
  2. cosmos-sdk v0.54.3 → v0.54.4: A separate, upstream security release. Cosmos Labs recommends all chains upgrade via a coordinated event. We are bundling this here to avoid a second, separate upgrade event.
  3. Withdrawal-Payout Hardening: Previously, MsgAttestWithdrawalPayout only cross-checked (steem_txid, op_index) across validators. It never verified the actual amount or asset paid out on Steem. A validator manually relaying a payout who sent the wrong asset or amount could have that payout confirmed as valid anyway. Now, the keeper independently compares the validator-reported amount_millisteem and asset against the withdrawal record. A mismatch is rejected (benign no-op, no confirmation recorded, audit event emitted) rather than silently trusted.

What Changed (For Code Reviewers)

For anyone reviewing the diff, here is a breakdown of the specific modifications:

  • go.mod / go.sum: The two version bumps mentioned above.
  • app/upgrades.go: New UpgradeNameV004 = "v0.0.4" handler, additive alongside the existing (dormant) v0.0.3 one. No store migrations are required, as neither dependency bump nor the payout change adds a new store key.
  • app/evm.go: SetProcessProposal wired in alongside the existing SetPrepareProposal.
  • app/ante_steembridge.go: Re-diffed against upstream ante/cosmos.go at v0.7.2. Confirmed no changes needed.
  • Makefile: VERSION changed from v0.0.3-Beta-2 to 0.0.4 (dropped the leading v). This fixes a latent, previously-unexercised bug: docker-entrypoint.sh stages the cosmovisor upgrade binary at cosmovisor/upgrades/v$(steemvmd version)/bin/, prepending its own v. A VERSION value that already started with v produced a double-v directory that could never match an on-chain Plan.Name. Verified via a real throwaway-container devnet boot that steemvmd version now prints 0.0.4 and stages correctly at cosmovisor/upgrades/v0.0.4/bin/steemvmd.
  • precompiles/steembridge/steembridge.go: Doc comment added noting BridgeOut's shared exposure to the patched code path.
  • proto/steemvm/steembridge/v1/tx.proto & x/oracle/bridge/types/tx.pb.go: New amount_millisteem (field 7) and asset (field 8) fields on MsgAttestWithdrawalPayout.
  • x/oracle/bridge/keeper/msg_server_attest_withdrawal_payout.go: The new amount/asset validation, mirrored into the fee-exemption ante-decorator acceptance check.
  • Event Updates: New asset attribute on withdrawal/deposit created/minted/burned events, and a new withdrawal_payout_asset_mismatch audit event.
  • Oracle Clients (oracle/go/, oracle/python/, oracle/js/): All three oracle client implementations updated in lockstep. The payout-detection logic now parses the actually observed amount/asset from the Steem transfer operation and reports it. It never echoes back the expected value, as that would defeat the on-chain check. (See oracle/PROTOCOL.md §5 for the spec).

Verification: go build, go vet, and go test ./... are all clean. A real devnet boot produced blocks with zero panics. All three oracle clients build, type-check, and pass their test suites.


Pending Verification

Not yet done, and blocking before this should be considered fully verified: A live exploit-replay test. We need to deploy a vesting-account contract via EVM, trigger the underflow through a precompile, and confirm it is cleanly rejected post-upgrade without crashing the node. This requires real EVM/Solidity tooling that is currently being set up. The upgrade is proceeding based on the upstream Cosmos Labs patch validation, but this local replay test will follow shortly.


Validator Upgrade Instructions

Path A: Docker Compose + Cosmovisor (Recommended Default)

Cosmovisor auto-swaps the binary at the exact upgrade height, but only if the new binary is already staged before that height arrives.

CRITICAL WARNING: Do NOT run docker compose down and docker compose up -d --build on your already-running validator before the upgrade height actually arrives. The docker-entrypoint.sh refreshes cosmovisor/genesis/bin/ on every container start whenever cosmovisor/current still points at genesis. Restarting your live container on the v0.0.4 image early would silently promote v0.0.4 to genesis/bin, and cosmovisor would start running it immediately, ahead of every other validator. This is an AppHash-divergence risk, not a safe pre-stage.

Instead, pre-stage the binary with a one-off service that never touches your running container:

  1. Pull this branch to get the compose file's stage-v0.0.4 service (you do NOT need to rebuild or restart your live node for this step):

    git pull && git checkout release/v0.0.4-security-upgrade
    docker compose --profile stage run --rm stage-v0.0.4
    

    This pulls the published image, copies its binary straight into cosmovisor/upgrades/v0.0.4/bin/steemvmd, and exits. It never touches cosmovisor/genesis/bin and never runs cosmovisor, so your live node keeps running exactly what it is running now, completely undisturbed.

  2. Confirm the binary staged correctly in the steemvm-node container:

    docker exec steemvm-node ls /root/.steemvm/cosmovisor/upgrades/v0.0.4/bin/
    

    MUST show: steemvmd

    docker exec steemvm-node /root/.steemvm/cosmovisor/upgrades/v0.0.4/bin/steemvmd version
    

    MUST print: 0.0.4

    Do this well before the target height. If the binary is not staged when the chain reaches the upgrade height, your node will halt until you stage it and restart.

  3. At the upgrade height, cosmovisor halts the old process, swaps current to point at cosmovisor/upgrades/v0.0.4/, and restarts automatically. Watch your logs (docker compose logs -f steemvm-node) around the target height to confirm the swap and continued block production.

  4. Note on Backups: No automatic backup is taken (docker-compose.yml sets UNSAFE_SKIP_BACKUP: "true"). If you want a rollback point, snapshot your node's data directory manually before the upgrade height.

  5. Only after the swap is confirmed is it safe to update your live steemvm service onto the published image for future restarts. At that point, cosmovisor/current points at upgrades/v0.0.4, not genesis, so the genesis-refresh no longer applies:

    docker compose pull steemvm-node && docker compose up -d steemvm-node
    

Path B: Bare steemvmd Binary (No Docker)

You do not need Docker to get cosmovisor's auto-swap. Installing cosmovisor as a sibling binary and running under it is the recommended path, as it avoids manual timing risks.

  1. Install cosmovisor once:
    GOTOOLCHAIN=go1.25.10 go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@v1.7.0
    
  2. Set the environment variables cosmovisor needs (put these in your shell profile or systemd unit's Environment= lines):
    export DAEMON_HOME=<your existing --home, e.g. $HOME/.steemvm>
    export DAEMON_NAME=steemvmd
    export DAEMON_RESTART_AFTER_UPGRADE=true
    export DAEMON_ALLOW_DOWNLOAD_BINARIES=false
    export UNSAFE_SKIP_BACKUP=true
    
  3. Point cosmovisor's genesis/bin at your CURRENT (already-running, pre-upgrade) binary. If you initialize cosmovisor with the new v0.0.4 binary here, it becomes what cosmovisor runs on its very next start, ahead of the coordinated height.
    which steemvmd
    cosmovisor init /path/to/your/CURRENTLY-RUNNING/steemvmd
    
  4. Build the new binary into a separate checkout or temp location so it does not overwrite the binary you just pointed genesis/bin at, then stage it into cosmovisor's upgrade slot directly:
    git pull && git checkout release/v0.0.4-security-upgrade
    make install
    NEWBIN="$(go env GOBIN)"; [ -z "$NEWBIN" ] && NEWBIN="$(go env GOPATH)/bin"
    "$NEWBIN/steemvmd" version   # confirm: 0.0.4
    mkdir -p "$DAEMON_HOME/cosmovisor/upgrades/v0.0.4/bin"
    cp "$NEWBIN/steemvmd" "$DAEMON_HOME/cosmovisor/upgrades/v0.0.4/bin/steemvmd"
    
  5. Switch whatever supervises your node (systemd ExecStart=, a screen/tmux command, etc.) from steemvmd start ... to cosmovisor run start ... (with the same flags), then restart once. This restart is a no-op in terms of behavior; cosmovisor's current still points at genesis, so it launches the exact same binary you were already running, just supervised by cosmovisor now.
  6. At the coordinated height, cosmovisor halts the old process, swaps to the staged v0.0.4 binary, and restarts automatically.

(Alternative: If you genuinely refuse to use cosmovisor, you must build the new binary ahead of time, watch the block height, and manually stop the old process and replace the binary at the exact halt height. This is highly discouraged due to timing risks.)


Governance Proposal: Action Required

This follows the standard cosmos-sdk software-upgrade governance flow. The proposal embeds an x/upgrade Plan with name = "v0.0.4" and a target height.

Proposal 2 is currently LIVE and open for voting. Because this is a critical security patch, timely voting by all operators is essential.

Vote on Proposal 2 Here: SoftwareUpgrade

How to Vote (Docker / Cosmovisor)

Run the following command to cast your Yes vote. Make sure to replace upex with your actual validator moniker/wallet name.

docker exec steemvm-node /root/go/bin/steemvmd tx gov vote 2 yes \
  --from <your_moniker> \
  --home /root/.steemvm \
  --chain-id steemvm \
  --gas auto \
  --gas-adjustment 1.5 \
  --gas-prices 1000000000asteem \
  -y

(Example: If your moniker is blaze.apps, replace <your_moniker> with blaze.apps)


Sanity Checks After the Upgrade (All Operators)

Once the upgrade height has passed, run these checks to confirm success:

# 1. Ensure the node is synced and not catching up
docker exec steemvm-node /root/go/bin/steemvmd status | grep catching_up   
# Should return: false

# 2. Verify the upgrade was applied at the correct height
docker exec steemvm-node /root/go/bin/steemvmd query upgrade applied v0.0.4 --home /root/.steemvm
# Should show the exact block height it applied at

Thank you to all validators for your swift attention to this critical security maintenance. Your diligence ensures the SVM ecosystem remains robust, secure, and ready for the future.

If you value proactive engineering, transparent development, and rigorous security standards for the STEEM ecosystem, please consider supporting my witness: blaze.apps

Vote for blaze.apps Witness

Sort:  
 19 days ago 

👍❤️