Restrict CosmWasm Code Upload

TL;DR

Terra Classic currently lets any account upload arbitrary CosmWasm bytecode (code_upload_access = Everybody). As a precautionary security-hardening measure, and in line with current CosmWasm ecosystem best practice, this proposal changes that parameter to Nobody, so that only governance can add new contract code.

  • Existing contracts and all contract execution/instantiation are unaffected.
  • CosmWasm is not removed — new code can still be added via a governance proposal.
  • The change is fully reversible and privileges no individual address.

Feedback is requested before this goes to an on-chain vote.

Background & rationale

By default, wasmd (the CosmWasm module) ships with code_upload_access = Everybody. Terra Classic has never changed this, so today any account can store arbitrary contract bytecode on-chain via MsgStoreCode.

Uploading bytecode is the most powerful and lowest-trust action a chain can expose: the uploaded code is processed by the on-chain VM on every validator. As the CosmWasm stack continues to evolve, a growing number of chains are moving upload behind governance as a standard, precautionary reduction of attack surface. This proposal brings Terra Classic in line with that practice.

The goal is deliberately conservative: privilege no one, keep the door fully open for the community to authorize specific deployers later, and change nothing about how existing contracts run.

What changes

x/wasm module parameters:

Parameter Before After
code_upload_access.permission Everybody Nobody
code_upload_access.addresses [] []
instantiate_default_permission Everybody Everybody (unchanged)

What this does not change

  • Existing contracts keep working. Instantiation and execution of already-stored code are untouched (instantiate_default_permission stays Everybody).
  • CosmWasm stays enabled. New code can still be uploaded — through a governance proposal.
  • No lock-in. Every parameter here can be changed again by a future governance vote.
  • No address is favored. The allow-list is empty; nobody gets a special upload privilege.

Future allow-listing

Starting at Nobody forecloses nothing. Should the community later wish to permit specific, vetted deployers (teams, a deployer multisig, etc.), a subsequent governance proposal can simply set code_upload_access to AnyOfAddresses with the chosen addresses. The mechanism to add uploaders via proposal is always available — this proposal just declines to privilege anyone today.

(Note: AnyOfAddresses requires at least one address to be valid; an “empty allow-list” is expressed as Nobody. The two are equivalent in effect, and either can be changed into the other by governance at any time.)

Impact on builders

  • Teams that need to deploy new contracts will, while this is in effect, do so via a governance proposal (or via an allow-list added by a later proposal, if the community approves one).
  • Already-deployed contracts, their users, and all existing dApp activity are unaffected.
  • If you are a builder who expects to deploy soon, please comment below so the community can weigh an AnyOfAddresses allow-list alongside or after this change.

Technical detail — the on-chain message

The vote will execute a single MsgUpdateParams against the x/wasm module:

{
  "messages": [
    {
      "@type": "/cosmwasm.wasm.v1.MsgUpdateParams",
      "authority": "<gov module account address>",
      "params": {
        "code_upload_access": { "permission": "Nobody", "addresses": [] },
        "instantiate_default_permission": "Everybody"
      }
    }
  ],
  "metadata": "",
  "deposit": "<min deposit>uluna",
  "title": "Restrict CosmWasm code upload to governance",
  "summary": "Change code_upload_access from Everybody to Nobody as a precautionary security hardening. Existing contracts and instantiation are unaffected; reversible by future governance."
}

The authority is the governance module account (terrad q auth module-account gov). Current params can be verified by anyone with terrad q wasm params (or the public LCD endpoint /cosmwasm/wasm/v1/codes/params).

Discussion questions

  1. Do you support moving contract upload behind governance as a precautionary measure?
  2. Should we pair this with (or quickly follow it by) an AnyOfAddresses allow-list for known, trusted deployers — and if so, which addresses?
  3. Any objections from active builders who have near-term deployment plans?

Please share feedback here before this is submitted on-chain.