Anti-DAO, Pre-DAO, DAOless — ICRC-137 Veto-Based Governance

TL;DR

  • ICDevs just shipped its first ICRC-137 “veto-governed” canisters: a Veto Canister and a Veto Lifeline—both wired through ICRC-120 orchestration.
  • Admins(DAP developers keep control but every sensitive(configured) call (upgrades, configs, token transfers, etc.) is subject to a DAO veto*. *The DAO can be a SNS, NNS, or other Item that returns proposal status in the same format as the NNS. For these canisters, that DAO is the NNS.
  • Lifeline ⟷ Veto: each can upgrade/configure the other via ICRC-120, so there’s a safety line if one fails.
  • Alpha has a backdoor (for safety); backdoor is removed at beta.
  • ICRC-120 orchestrator will be the next canister governed under ICRC-137.
  • This pattern is for Anti-DAOs, Pre-DAOs, and the DAOless who want accountability without having to establish a new DAO and who want to ‘inherit’ the security of the NNS.
  • Links: Veto-Lifeline akiyk-waaaa-aaaai-atlca-cai, Veto anj66-3yaaa-aaaai-atlcq-cai, ICRC-120 Orchestrator a7pjh-xiaaa-aaaai-atlbq-cai (block logs available).

Anti-DAO, Pre-DAO, DAOless — ICRC-137 Veto-Based Governance

What we shipped

  • ICRC-137 Veto Canister and Veto Lifeline (subject to NNS veto).

  • Mutual upgrades via ICRC-120:

    • Veto can upgrade the Lifeline through ICRC-120, config through self call.
    • Lifeline can upgrade the Veto through ICRC-120, config through self call.
  • Roadmap: the ICRC-120 Orchestrator itself will go under ICRC-137 governance next.

Canisters

Field note: the Lifeline already executed a command against the ICRC-120 to upgrade the Veto canister to v0.0.4. We shortened the timeline to test; it failed at first, then succeeded after enabling orthogonal persistence flags.

You can explore calls/behavior in the ICRC-3 block logs for each canister.

Here is the command status for the successful icrc120_upgrade_to call:

[
  [
    {
      "id": 1,
      "status": {
        "executed": "1759947563809335170"
      },
      "result": [
        {
          "Ok": "4449444c036d016b02bc8a017dc5fed201026b04efd1c6af057ff7b3b29d0871d4b4c59a097fecce99d4097f0100010007"
        }
      ],
      "request": {
        "scheduled_time": [],
        "method": "icrc120_upgrade_to",
        "metadata": [
          [
            "icrc137_upgrade_type",
            {
              "Text": "veto_canister_upgrade"
            }
          ],
          [
            "icrc137_description",
            {
              "Text": "Upgrade veto_canister through prod-orchestrator"
            }
          ],
          [
            "icrc137_target_canister",
            {
              "Text": "anj66-3yaaa-aaaai-atlcq-cai"
            }
          ],
          [
            "icrc137_wasm_hash",
            {
              "Text": "63f25d37647113c89eb65c8d3f02b13add3451cf3c7fb373e2348be768970d41"
            }
          ]
        ],
        "memo": [
          "757067726164652d31373539393437343833353633"
        ],
        "requested_at": [
          "1759947483563000064"
        ],
        "cycles": [],
        "best_effort_timeout": [],
        "method_args": [
          "4449444c0d6d7b6b0285a19bb8047fb490a1d90a7f6e016e7e6c02dceaaefa0202c0a09bde05036e046b03c8bb8a707f9ce9c69906059baaebec087f6c006c02007101076d086e096c09c4b0d08d027edd9ad2830400cedfa0a80400e3a683c3040682e0efe2047eb3c4b1f20468aafdfa8b050acf8f97d5067ea1b5dcc70d7d6d0b010c0100314449444c076c006e006c02dbb7017d8d98f3e7047d6d026e036c0381a99a4001fdbdbbb90504e780c0b107016e050106002063f25d37647113c89eb65c8d3f02b13add3451cf3c7fb373e2348be768970d41010101000001010a0000000001009ac50101000180f092cbdd08"
        ],
        "canister": "a7pjh-xiaaa-aaaai-atlbq-cai"
      },
      "scheduled_for": "1759947563044796132",
      "veto": [],
      "created_at": "1759947503044796132"
    }
  ],
  1
]

How it works (in one screen)

  • ICRC-137 lets an admin make any IC call (e.g., upgrade/config/transfer), but requires subjecting each call to a veto window by a chosen DAO (here: NNS).
  • On-chain: only the Veto Canister (and certain closed systems like the 120 Orchestrator) can perform protected actions on your target system; it is set as sole controller/admin for those functions.
  • Off-chain: community discovers pending commands and can organize a veto motion. We’re building a discovery dashboard in Astroflora; bots/feeds are viable too.

Alpha → Beta

  • Alpha: we maintain a backdoor (recovery).
  • Beta: we remove the backdoor.

Why this design?

Coin-voting DAOs are unresolved at best, broken at worst (collusion, plutocracy, capture):

At the same time, the NNS has “secured” >$2B for ~4+ years, while some SNS offspring have seen capture risks. We want operational clarity + last-resort accountability without pretending coin-vote solves everything today(and the expenses that come along with an SNS).

ICRC-137 requires a commitment to this ethos:

  1. Open source the code.
  2. Clear-communication about upcoming upgrades and/or service affecting actions.
  3. Honor the timeline - Announce publicly, wait 4 days, call command, wait 4 days, execution or veto.

This creates explicit power with explicit guardrails, not the murky implicit control that often accompanies governance theater.

Who this is for

  • Anti-DAO: You don’t want to give up control, but you want credible accountability (including protection against coercion). ICRC-137 gives you a safety net when pressure mounts.
  • Pre-DAO: You want to grow into decentralization. ICRC-137 sets rational limits and provides on-chain trust while you iterate toward a durable model.
  • DAOless utilities: Mostly “black-hole,” but want a measured upgrade path for rare protocol changes. ICRC-137 makes that straightforward.

Consider your application is successful and you find yourself holding the keys(literally) to a service that has US $100m of users’ funds held by accounts on your back-end canister. On a Tuesday night, a man shows up at your door with a gun and kindly suggests that you install his crafted wasm that will extract all the tokens your canister owns into his account. What do you do? If your canister is under ICRC-137 governance, this scenario becomes much less possible because upgrades take, at the least, 4 days, and an unannounced upgrade that does not have code associated with it will likely be vetoed.

Practicalities

On-chain (easy)

  • Propose the call via ICRC-137 → it enters a pending window.
  • If no veto within the window → it executes automatically.

Off-chain (harder)

  • People need to care and have information. We’ll surface pending requests in an Astroflora dashboard; third-party bots can help.
  • The governing DAO (here, NNS) must also care. Expect to write clear proposals and rally quorum (>~3% on some NNS topics). Example style:

“DAOZZZ proposes upgrading to WASM XXXXXX. The new build adds a withdrawal function enabling DAOZZZ to remove user funds at discretion. This violates stated protocol guarantees and is unsafe. We request the NNS to veto this upgrade. Commit: https://github.com/yyyyyyyy.”

The unstated subtext to the above proposed veto is that it is highly likely tha the THREAT of veto will cause the upgrade to not be issued in the first place and thus resolving the situation off chain.

Abuse & trolling

  • A sufficiently funded actor can repeatedly file veto motions to stall you. There’s no silver bullet yet; economic costs and social norms help.
  • ICRC-137 can plug into any governance system with a governance-canister-like interface; boards/councils are possible if NNS isn’t the right venue.

Security/operability notes

  • Only the Veto Canister (and selected closed systems like the 120 Orchestrator) should be controller/admin for functions guarded by 137.
  • Keep trivial stuff out of NNS governance; reserve veto for big promises and safety.
  • Emergency stops, can be issued by a developer that controls a 137 canister if they provide a pre-determined fee/deposit as a part of the standard. This allows vulnerabilities to be taken offline immediately, and then the fee/deposit is refunded after a new wasm is deployed. This provides at least SOME ‘delete the canister’ protection.

FAQ

Q: Can I read the code?
A: Not yet. We’re running a few experiments first and figuring out funding. We applied for a grant; it’s in limbo as it’s not seen as driving immediate network metrics. We’ll keep pushing—infra/public goods aren’t flashy, but they’re essential. Got ideas? Donations, naming rights, even playful things like “buy-a-line-as-an-NFT” have been floated. We’ll open-source at release with better docs and self-service onboarding.

Q: Can I use it today?
A: If you have a clear use case and would like to participate in the Alpha/Beta, please reach out.


Next steps

  • Run more experiments, including vetoing one of our own upgrades end-to-end to prove the loop.
  • Remove the alpha backdoor.
  • Open-source the code, document the spec, and package deployment tooling.
  • Release the Astroflora dashboard for ICRC-137 discovery (pending-commands feed).

If you’re building an Anti-DAO, Pre-DAO, or DAOless service and want to ship with accountability—without pretending coin-vote is “solved”—ICRC-137 is for you.

You can currently launch your own ICRC-137 canister via the AstroFlora dashboard at https://muwct-xiaaa-aaaaj-a2ffq-cai.icp0.io/ if you create an empty canister and make a7pjh-xiaaa-aaaai-atlbq-cai a controller.

11 Likes
ICRC Title Author Discussions Status Type Category Created
137 Vetoable Command and Governance Service Specification Austin Fatheree Vetoable Upgrades · Issue #137 · dfinity/ICRC · GitHub Draft Standards Track 2025-10-08

ICRC-137: Vetoable Upgrade and Governance Service

1. Scope

ICRC-137 defines a standard interface for the management of canister upgrades with integrated veto, cancellation, and emergency stop mechanisms. Designed to work with upgrade orchestrators (e.g., ICRC-120), this service provides robust, auditable workflows for risk-managed upgrades, suitable for DAOs, utilities, and enterprises operating on the Internet Computer.

This standard covers:

  • Submitting, reviewing, and executing upgrade commands

  • Vetoable pending state with payment and burn logic

  • Emergency stop (with suggested economic guardrails)

  • Querying governance and command metadata

  • Compatibility with ICRC-120 orchestration and canister snapshots

Out of Scope

  • Low-level wasm install or execution procedures (see ICRC-120)

  • SNS-style voting extensions (can be layered atop this standard)


2. Purpose and Reasoning

Many Internet Computer services and utilities lack the resources—or the maturity—to run their own SNS or fall outside the remit of the NNS. Yet, those that hold or manage value must safeguard user funds and maintain developer agility and physical and financial safety while the ecosystem and its protocols evolve. ICRC-137 fills this gap by offering a “governance of last resort”: teams retain operational control of their canisters, but any proposed upgrade or installation is subject to a vetoable governance check.

Key extensions introduced by ICRC-137:

  • Pending windows. Every proposed command enters a configurable delay period before execution, giving stakeholders time to review changes.

  • Veto, cancellation, and emergency blocks. Authorized parties can halt a pending command—subject to implementation-defined deposit, burn, or delay rules.

  • Role-based controls. Fine‑grained permissions let projects define which principals may propose, veto, cancel, or stop operations (details left to each instance).

  • Deduplication. Commands are uniquely identified and de‑duplicated within a time window, preventing accidental replays and aiding recovery.

These features suit scenarios such as decentralized utilities, compliance‑aware dapps, and managed‑upgrade frameworks, where transparency and risk management are paramount.

Governance “Safety Net”

ICRC-137 is intentionally positioned as a fallback governance layer for services that:

  1. Serve the public but aren’t yet ready for—or don’t require—the full SNS/NNS voting apparatus.

  2. Need a simple, predictable upgrade process with the option for emergency intervention.

Teams give control of their canisters to open-sourced ICRC-137 “orchestration canister,” maintain day‑to‑day control, and pledge to follow a pre‑committed upgrade workflow. A designated SNS, NNS, or other designated DAO can trigger a veto motion against that workflow if concerns arise.

Suggested Upgrade Workflow

  1. Open‑source code. All canister logic must be publicly auditable.

  2. Advance notice. Publish code and announce any planned upgrade at least 4 days before submission.

  3. Scheduled execution. Submit the upgrade command to execute 8 days after announcement.

  • During the first 4 days, the team and community can discuss and, if necessary, cancel the command and propose a revised version.

  • If unresolved, anyone posting the required deposit may file a veto motion. A successful veto blocks the original command; the team must then submit a new proposal.

Note: Tokenomics for veto deposits, burns, and rewards are intentionally left open. Each deployment may define its own economic parameters in accordance with its governance policies.


3. Terminology and Definitions

  • Command: An action (typically an upgrade, install, or governance operation) proposed on a canister.

  • Veto: The ability to block/stop a pending command during its defined window, after which it executes automatically.

  • Emergency Stop: A mechanism for an admin to instantaneously halt a canister or operation, with possible fee/deposit requirements.

  • Deduplication: Ensuring only one instance of a transaction is accepted within a window for resilience against network failure.

  • Governance Canister: An associated canister responsible for reviewing, vetting, or executing commands for the governed canister.

  • ICRC-16 Map: Flexible metadata annotation as defined by ICRC-16.

  • Proposal Format: Each ICRC-137 service should publish the valid motion proposal format and any stipulations that must be in place to tie the veto to a particular command proposal. The proposal SHOULD contain a Representational Independent Hash of ICRC-137 Principal as Blob | Target Canister Principal as Blob | Command Id as Nat as well as a clear and intentional text explaining the reason for the veto and why governance participants should adopt the veto.


4. Service Function Specifications

Please review ICRC7 - Generally-Applicable Specification for general details on batch update methods and batch query methods.

4.1. icrc137_get_command_info

Purpose:

Query the currently pending (and historical) command information for one or more canisters or command IDs. Allows applications or DAOs to inspect waiting upgrades and associated governance/veto data.

Function Signature:


icrc137_get_command_info: query (prev: ?Nat, take: ?Nat, filter: vec CommandInfoFilter) -> record{ vec opt CommandInfo; nat};

Parameters:

  • prev, take: For pagination

  • filter: Filter by id, canister, requester, or status

Returns:

  • CommandInfo records and a count of number of records

CommandInfoFilter Type


type CommandStatusFilter = variant {

pending;

executed;

canceled;

vetoed;

stopped;

any;

};

type CommandInfoFilter = variant {

by_id: Nat;

by_canister: Principal;

by_requestor: Principal;

by_status: CommandStatusFilter;

};

CommandInfo Type


type CommandInfo = record {

id: Nat;

request: CommandProposalRequest;

status: CommandStatus;

scheduled_for: Nat;

veto: opt VetoRequest;

cycles: opt nat;

best_effort_timeout: opt nat32;

created_at: Nat;

};


4.2. icrc137_get_emergency_stop_info

Purpose:

Query the currently pending (and historical) emergency stop information for one or more canisters or emergency stop IDs. Allows applications or DAOs to inspect waiting upgrades and associated governance/veto data.

Function Signature:


icrc137_get_emergency_stop_info: query (prev: ?Nat, take: ?Nat, filter: vec EmergencyStopInfoFilter) -> record{vec opt EmergencyStopInfo, nat};

Parameters:

  • prev, take: For pagination

  • filter: Filter by id, canister, requester, or status

Returns:

  • Vector of Optional EmergencyStopInfo records and the count of total records (see below)

CommandInfoFilter Type


type EmergencyStopStatus = variant {

pending;

active: nat;

resolved: nat;

expired: nat;

failed: text;

};

type EmergencyStopStatusFilter = variant {

pending;

active;

resolved;

expired;

failed;

any;

};

type EmergencyStopInfoFilter = variant {

by_id: Nat;

by_canister: Principal;

by_stopper: Principal;

by_status: EmergencyStopStatusFilter;

};

EmergencyStopInfo Type


type EmergencyStopInfo = record {

id: Nat;

canister: Principal;

stopper: Principal;

token: Principal;

amount: Nat;

escrow_subaccount: Blob;

requested_at: Nat;

stopped_at: opt Nat;

collateral_paid: Bool;

status: EmergencyStopStatus;

memo: opt Blob;

metadata: ICRC16Map;

penalty_deadline: Nat;

};


4.2. icrc137_get_veto_hash

Purpose:

Query the representational independent hash required for ICRC-137 veto motion proposals. This hash uniquely identifies a command for governance veto purposes and should be included in motion proposal text.

Function Signature:


icrc137_get_veto_hash: query (Nat) -> opt [Nat8];

Parameters:

  • command_id: The ID of the command to generate the veto hash for

Returns:

  • Optionally an array of Nat8 representing the hash, or null if command not found

Hash Format:

The hash is generated using Representational Independent Hashing of:

ICRC-137 Principal as Blob | Target Canister Principal as Blob | Command Id as Nat

This hash should be included in NNS motion proposal text to tie the veto to the specific ICRC-137 command.


4.3. icrc137_request_command

Purpose:

Admin requests a command (such as an upgrade) for a canister. The admin must have prior rights (not defined in this standard; refer to implementation).

Function Signature:


icrc137_request_command: ([CommandProposalRequest]) -> [CommandProposalResponse];

CommandProposalRequest Example:


type CommandProposalRequest = record {

memo: opt Blob;

canister: Principal;

method: Text;

method_args: opt Blob;

metadata: ICRC16Map;

scheduled_time: opt Nat;

requested_at: opt Nat;

};

Operation:

  1. Verify the requester is authorized by governance rules

  2. Apply deduplication (see below)

  3. Create a pending command record (status: pending)

  4. If duplicate or invalid, return relevant error variant

CommandProposalResponse Type:


variant {

Ok: Nat; // command id

Err: CommandProposalError;

}


4.4. icrc137_check_and_resolve_emergency_stops

Purpose:

Check and resolve all emergency stops that can be resolved for a given canister. This function allows those who have posted collateral deposits to manually resolve their emergency stops once the underlying issues have been addressed (e.g., after a successful upgrade). It also enables others to trigger resolution if stoppers fail to resolve within the penalty deadline, potentially burning their deposits.

Function Signature:


icrc137_check_and_resolve_emergency_stops: (resolvableCanisterId: Principal) -> [(Nat, Result<Nat, Text>)];

Parameters:

  • resolvableCanisterId: The Principal of the canister for which to check and resolve emergency stops

Returns:

  • Array of tuples containing:

  • Nat: Emergency stop ID that was processed

  • Result<Nat, Text>: Either the block number of the successful refund transaction (Ok) or an error message (Err)

Behavior:

  • Checks all active emergency stops for the specified canister

  • Attempts to resolve stops where the canister is now running (indicating successful remediation)

  • Processes collateral refunds for resolved stops

  • Returns results for each stop that was processed

  • Only processes stops that are eligible for resolution based on current canister status


4.5. icrc137_request_veto

Purpose:

Request a veto on a pending command, typically within a configured window. Payment (burn/deposit) may be required and is implementation-defined.

Function Signature:


icrc137_request_veto: ([VetoRequest]) -> [VetoResponse];

VetoRequest Example:


type VetoRequest = record {

motion_id: Nat;

governance_canister: Principal;

command_id: Nat;

metadata: ICRC16Map;

requested_at: opt Nat;

memo: opt Blob;

};

VetoResponse:


variant {

Ok: Nat; // command id

Err: VetoError;

}

Operation:

  1. Check if the veto request is within the veto window for the command

  2. Confirm with the governance canister that the motion exists, is of the correct topic, is open for voting, was created within the window and contains the proper format for a veto proposal.

  3. Enforce payment requirement (e.g., burn if veto fails)

  4. Register the veto and update status

  5. Deny if late, duplicate, invalid, or not found


4.6. icrc137_emergency_stop

Purpose:

Let an administrator halt a target canister. Service suggests a hefty deposit, only returned if the stop leads to a successful upgrade (final implementation left to instance policy).

Function Signature:


icrc137_emergency_stop: ([EmergencyStopRequest]) -> [EmergencyStopResponse];

Request/Response Types:


type EmergencyStopRequest = record {

canister: Principal;

memo: opt Blob;

metadata: ICRC16Map;

requested_at: opt Nat;

};

type EmergencyStopResponse = variant {

Ok: Nat;

Err: EmergencyStopError;

};

Metadata Management

This specification does not dictate how collateral for emergency stops should be managed. The implementor SHOULD provide a method for the stopper to recover their funds after a successful deployment and the system SHOULD burn the collateral if the stopper does not provide a fix in a timely manner.


4.7. icrc137_cancel_command

Purpose:

Cancel a pending command by id. Must be performed by an authorized administrator.

Function Signature:


icrc137_cancel_command: ([Nat]) -> [CancelCommandResponse];

CancelCommandResponse Example:


variant {

Ok: Nat;

Err: CancelCommandError;

}


4.8. icrc137_canister_metadata

Purpose:

Retrieve registry/governance metadata about a canister (such as governance canister, payment requirements, etc).

Function Signature:


icrc137_canister_metadata: query ([Principal]) -> [ICRC16Map];

Suggested Metadata Value:

  • icrc137_veto_fee_amount: Nat; - amount of the veto fee in the designated token

  • icrc137_veto_fee_ledger: Principal; - ledger of the designated token

  • icrc137_veto_fee_fee: Nat; - fee on transactions

  • icrc137_veto_fee_symbol: Text; - symbol of the designated token

  • icrc137_veto_fee_decimals: Nat; - decimals in the token

  • icrc137_veto_fee_account: Array[Blob, Blob]; - account the veto fee should be approved to using ICRC-2

  • icrc137_stop_fee_amount: Nat; - amount of the stop fee in the designated token

  • icrc137_stop_fee_ledger: Principal; - ledger of the designated token

  • icrc137_stop_fee_fee: Nat; - fee on transactions

  • icrc137_stop_fee_symbol: Text; - symbol of the designated token

  • icrc137_stop_fee_decimals: Nat; - number of decimals

  • icrc137_stop_fee_account: Array[Blob, Blob]; - account the stop fee should be approved to using ICRC-2

  • icrc137_default_veto_window: Nat; - default veto window (in nanoseconds) for commands that don’t have method-specific windows

  • icrc137_veto_window_{method}: Nat; - amount of time to wait for veto before a command with that method is run

Metadata Security

The specification does not define management functions for metadata, amounts, and specified tokens. The canister should limit any updates for these values to come from the managed canister as a security measure. By doing this management for the fees comes under the same work flow and must be at least silently approved by an upgrade being invoked without a veto.


5. Deduplication and Transaction Safety

To promote error recovery for agents (e.g., sudden disconnects), ICRC-137-compliant services SHOULD deduplicate incoming transactions within a fixed time window (TX_WINDOW, e.g., last 24 hours). Use memo and requested_at fields to detect/reject duplicates. Requests with explicit requested_at may be exempt from deduplication.


6. Recommendations, Security and Payments

  • Veto payments: Implementers are strongly advised to require a payment (which may be burned) to request a veto; this discourages spurious vetoes.

  • Emergency stop deposits: It is RECOMMENDED that emergency stop require a deposit only returned if a subsequent upgrade is successful.

  • Role-based controls: Rights for proposing commands, vetoing, or cancelling should be strictly enforced. The standard does not mandate a specific admin framework.

  • ICRC-120 Integration: For safe upgrades, it is recommended that ICRC-137 services rely on or invoke an ICRC-120-compatible orchestrator for actual module installs, rollbacks, and snapshotting.

  • Canister snapshot: Before an upgrade, orchestrators should snapshot the canister state to support reversion upon failure.

  • Chain of trust: Use of related standards like ICRC-121 (blocks), ICRC-105 (wasm chain), and ICRC-126 (wasm verification) is recommended but not required.

  • Security: Implementers should review security considerations outlined in ICRC-7 before deployment.


7. ICRC‑137 Block Schemas

Every block is an ICRC‑3 record with a header:

  • btype: the block type identifier

  • ts: timestamp of record creation

  • tx: a record carrying event‑specific fields

7.1. 137new_command

Purpose:

Records that a new command (e.g., upgrade/install) has been proposed and entered the pending window.

tx Fields:

  • requester: Blob

Principal initiating the command.

  • canister: Principal as Blob

Target canister of the command.

  • method: Text

Method name to be invoked (e.g., "upgrade", "install").

  • method_args: Optional Blob

Serialized arguments for the method.

  • scheduled_for: Nat

Epoch timestamp when the command is slated to execute.

  • metadata: ICRC16Map

Arbitrary governance settings or parameters.

  • memo: Optional Blob

Free‑form user memo.

  • requested_at: Optional Nat

Client‑provided or service‑assigned submission time.

Block Header:

  • btype: "137new\_command"

  • ts: Timestamp of proposal


7.2. 137command_cancel

Purpose:

Records cancellation of a pending command by an authorized party.

tx Fields:

  • canceller: Blob

Principal requesting cancellation.

  • command_id: Nat

Identifier of the command being canceled.

  • reason: Optional Text

Human‑readable reason for cancellation.

  • requested_at: OPtional Nat

Block Header:

  • btype: "137command_cancel"

  • ts: Timestamp of cancellation


7.3. 137veto_request

Purpose:

Logs that a veto motion has been filed against a pending command (with deposit logic handled separately).

tx Fields:

  • veto_requester: Blob

Principal filing the veto.

  • command_id: Nat

ID of the command under veto.

  • motion_id: Nat

Governance‑canister motion identifier.

  • governance_canister: Principal as Blob

Canister adjudicating the motion.

  • metadata: ICRC16Map

Veto‑specific metadata (e.g., fee parameters).

  • memo: Optional Blob

  • requested_at: Optional Nat

Block Header:

  • btype: "137veto_request"

  • ts: Timestamp of veto filing


7.4. 137command_executed

Purpose:

Marks that a pending command has successfully executed (post‑veto window).

tx Fields:

  • executor: Blob

Principal or system actor that ran the command.

  • command_id: Nat

  • canister: Principal as Blob

  • method: Text

  • result_hash: Optional Value

Post‑execution state or response.

  • requested_at: Optional Nat

Block Header:

  • btype: "137command_executed"

  • ts: Execution timestamp


7.5. 137command_vetoed

Purpose:

Indicates a command was vetoed (and any associated fee refund processed).

tx Fields:

  • veto_resolver: Blob

Governance canister or system actor confirming veto outcome.

  • command_id: Nat

  • veto_motion_id: Nat

  • veto_approve: Nat VP used to approve

  • veto_reject: Nat VP used to reject

  • fee_amount: Nat

Amount deposited for veto.

  • fee_refunded: Nat

Amount returned or burned (implementation‑defined).

  • timestamp: Nat

Block Header:

  • btype: "137command_vetoed"

  • ts: Timestamp of veto resolution


7.6. 137emergency_stop

Purpose:

Logs that an immediate halt request was issued against a canister.

tx Fields:

  • stop_requester: Principal as Blob

  • canister: Principal as Blob

  • deposit_amount: Nat

Deposit held pending outcome.

  • metadata: ICRC16Map

  • memo: Optional Blob

  • requested_at: Optional Nat

Block Header:

  • btype: "137emergency_stop"

  • ts: Timestamp of stop request


7.7. 137emergency_stop_refund

Purpose:

Records refund or burn of the emergency‑stop deposit after resolution.

tx Fields:

  • resolver: Principal as Blob

  • canister: Principal as Blob

  • stop_request_id: Nat

Links back to the original stop request (e.g., same command\_id space).

  • refund_amount: Nat

  • timestamp: Nat

Block Header:

  • btype: "137emergency_stop_refund"

  • ts: Timestamp of refund/burn processing


7.8. 137metadata_update

Purpose:

Captures any on‑chain update to governance or fee metadata for this service.

tx Fields:

  • updater: Principal as Blob

  • canister: Principal as Blob

  • changed_keys: Array

List of metadata keys modified.

  • new_values: Array

  • timestamp: Nat

Block Header:

  • btype: "137metadata_update"

  • ts: Timestamp of metadata change

8.0 Integrations

ICRC-10

An implementation of ICRC-137 Registry MUST also support the method icrc10_supported_standards (per ICRC-10), and include the following entries in its response:


record { name = "ICRC-10"; url = "https://github.com/dfinity/ICRC/ICRCs/ICRC-10"; }

record { name = "ICRC-137"; url = "https://github.com/dfinity/ICRC/ICRCs/ICRC-137"; }

8. References


9. Annotations

Reserved for future updates, configuration, and parameterization of timeouts, payment requirements, or extension fields.

6 Likes

ICDevs will be making a motion proposal to the NNS asking for voters to ratify a veto of our veto_lifeline canister to hash 4bd36cc937213607a8a7c6214e91cb19f9ae093fae3426f2b3012e69747cc9ae.

This is an experiment. We are asking voters to vote ACCEPT to test that the motion will block the upgrade via our ICRC-137 interface.

Proposal link - Please Accept for testing: Network Nervous System

The veto has been filed with the 137 canister and now we await the results.

6 Likes

I voted to adopt. Out of interest, what text in the motion is used to identify it as a veto proposal by your upgrade system?

I gather the idea is that anyone in the future could submit a motion like this to block an upgrade that the’re unhappy with?

You can retrieve a hash from the icrc-137 canister that needs to be in the motion proposal text. The canister checks for that hash when you file the veto. Each command call gets a unique hash. Anyone can grab the hash and make the nns proposal, and then you file motion with the the 137 canister and it moves the command timer until after the veto vote ends.

Looks like the vote is going to be pretty close, which is odd for an alpha vote motion. It is going to be interesting to break down what that might mean.

Could you elaborate please (so that there’s sufficient instruction to actually carry out those steps)? For example, which canister and endpoint would I use?

Here’s the ICRC-137 canister mentioned in the proposal. There are numerous controlling principals and numerous endpoints. Does it need to be this complicated?

As a side note, when I see ICRC-N as the name for a canister, it doesn’t really mean very much to me. I suspect that’s the case for most people. It might be helpful for canisters such as this to have a more self-explanatory name.

As a side note, who is the authority for the ICRC namespace, and/or how are available numbers determined? Who can issue these RCs and how do they determine the appropriate number?

1 Like

It’s a bit strange that you call it Anti-DAO and ask the NNS DAO to vote. I agree SNSes aren’t superbly decentralized, but they still take more risks when voting - their reputation is on the line. If they vote badly, nobody will want to hold their coins. Behind every decision, there is a lot of value at stake.

If people don’t want to participate and only reject, then it will require good actors to have much more voting power than a malicious actor. The system is using the NNS like a near-free dispute resolution system, which hasn’t opted in to governing something explicitly. If a veto passes, the jury has made 0$ in fees. For a Kleros court with up to 31 randomly picked out of 600 jury members, the fees are ~900$. These jury members are also not responsible for anything, but if they vote maliciously, then the Kleros price will fall, since it’s not doing what it is supposed to do.
If we say the developer/admin is not taking responsibility for what happens with these services, the NNS neurons didn’t opt in to take the responsibility, then where does it go? I doubt it just vanishes. If it vanishes, how is it inheriting the security of the NNS.
Things may be different for a service that grows to be very important for every NNS neuron and serves them all, and they have probably all accepted a motion opting in to vetoing malicious upgrades.
Before that, you can’t call it NNS anything. It would be pretty bad if people launched these and claimed the NNS is securing their services.
You could just use a dispute resolution system and pay juries to vote, until the NNS accepts taking care of these services explicitly, with a near-unanimous vote.

cpbhu-5iaaa-aaaad-aalta-cai is the cycleOps black hole.

a7pjh-xiaaa-aaaai-atlbq-cai Is an ICRC-120 wasm orchestrator. It is used to install upgrades, stop canisters, take snapshots, start, etc. Under ICRC-137 governance, this will be the only controller that isn’t a black hole.

akiyk-waaaa-aaaai-atlca-cai - This is the Veto Lifeline canister…it will be a controller of the main 137 veto canister and the 137 veto canister will be the controller of the lifeline canister. This is a similar setup to the NNSRoot/NNSLifeline - https://dashboard.internetcomputer.org/canister/rno2w-sqaaa-aaaaa-aaacq-cai. Basically, if something goes horribly wrong, these canisters can upgrade each other to get them back online. It isn’t necessary to have this setup, but it is safer.

These two:
ufef3-ic2bp-enpmy-5ezyw-z4p5q-mzgsv-w24y3-2v2b6-ktjpk-cjik4-kae,
mctz3-uvscw-rbtha-zdzis-q46vd-vzbza-bxjk5-mleuf-jml6g-s2hq3-vqe

Are ICDevs controllers and will be removed when it exits alpha.

So if you want to deploy your own 137 governance system, you want to minimize controllers, then you really only need an orchestrator canister as your only controller. CycleOps and lifelines are optional. It would be nice if the canister were only its own controller, but you’d get stuck if you ever stopped it and upgrading would take a lot longer or have workflow issues if the stop, snapshot, upgrade, start got out of order because of vetos or voting. Using ICRC-120 makes it a single command icrc120_upgrade_to.

If you want to read more about ICRC-120 - Canister Orchestration, you can do that at ICRC-120 - Canister Wasm Orchestration Service Specification · Issue #120 · dfinity/ICRC · GitHub or ICRC-120 – Canister Wasm Orchestration Service

As a side note, who is the authority for the ICRC namespace, and/or how are available numbers determined?

It is fairly permissionless…just create an issue at GitHub · Where software is built and then write a draft.

Let’s check the following scenario if there is no unanimous opt-in.

9% vote accept (veto this)
9% vote reject (malicious actors)
14% vote reject (didn’t opt-in governing this)
2% vote reject (auto reject - pro immutability)

The veto fails and malicious upgrade passes. The good actors who want to stop a malicious upgrade are burneded with 16% who didn’t opt in to govern at all. So control is in the hands of developers.

Without unanimous opt-in - If a DEX or a bridge stamps a badge on their site “NNS governed” using this system and then nobody can stop a hack (or cares enough to look at their upgrades) then the community has been decieved that something is NNS governed. Which is much worse than having an SNS that depends on 3 entities. In such a case - it’s three not one and also it’s not pretending to be governed by the NNS.

Anti-DAO

Anti-DAO, not in the philosophical stance of anti-dao, but in the organizational structure of anti-dao. We’ve had a history here on the IC of people promising to become a dao or saying they’ll add some kind of user protection in the future, but they really never open source their code an never remove their controllers. They are just businesses. They never actually intend to become DAOs an no one really ever holds their feet to the fire. If they at least do this 137 system then users know that if their canisters become big/important enough, there is some kind of user protection.

I agree SNSes aren’t superbly decentralized, but they still take more risks when voting - their reputation is on the line. If they vote badly, nobody will want to hold their coins. Behind every decision, there is a lot of value at stake.

But also, if the NNS votes badly and/or becomes corrupted, no one will hold their coin as the NNS can install/any wasm on the network.

If people don’t want to participate and only reject, then it will require good actors to have much more voting power than a malicious actor. The system is using the NNS like a near-free dispute resolution system, which hasn’t opted in to governing something explicitly.

You make a great point here about explicit governance. If I ask the NNS if I should rob a bank or not then I’m clearly outside of anything that the NNS has any kind of social contract to govern and that would be silly. Given that the NNS already has explicit protocol-level access to install any wasm on any canister that can make any call on the IC, all the 137 pattern has done is rearrange protocol-level rights into the software layer. The function of these proposals are completely inside the circle of existing NNS governance coverage.

Is it a good situation for the NNS if we have 30,000 mini-SNS all with low market caps and subject to attacker capture? I would argue this would be very bad for the NNS to constantly have SNS being spun up only to crash and burn the instant they gain any traction. 137 is “quiet” in that it is only called upon when 1. something goes haywire and 2. Someone cares enough to raise the question. (right now with default configs that is 35ICP worth of caring… no clue if the number is right, but the system bakes in the ability for the administrating entity to manipulate the 137 part of the equation(10 ICP currently).

Before that, you can’t call it NNS anything. It would be pretty bad if people launched these and claimed the NNS is securing their services.

I’ll go out on a limb and say I very much disagree with this position. Anything installed on the IC has explicit governance by the NNS in the social contract. Because the NNS can, at any time, overwrite your canister, then it has taken the government responsibility on it. If it does not govern well, ICP will fall. If an underage porn site takes off on the IC and the NNS does nothing, then it is a significant threat to the value of ICP and if the NNS chooses to do nothing, then it will pay the consequences.

Of course, it is all relative. If an admin tries to upgrade a canister under 137 governance to a wasm that steals $1,000 from its users, perhaps not enough people on the NNS will care. Will $1,000 theft really make that much of a difference? Likely not. But if it is done 10x…or someone is trying to steal $1 million? At some point, the threshold is tripped, and all of a sudden, the NNS cares.

Is 137 wishy washy like that? Yes. As devs do we want all Ts crossed and Is dotted? We do, but the world, and historical governance doesn’t work that way AT ALL. What gets governed is what gets attention.

Everyone wants to pretend that this NNS governance over canister wasms doesn’t exist, but it most certainly does. It is FAR more real than SNS theater and hand-wavy diatribes about tokenomics when, if the NNS is captured (via an attacker, a meme, good sense, legal trouble avoidance), any substructure you have put in place is just obliterated by the InstallCode proposal.

Could you use some other jury or mechanism? Sure…but you have to have people care in those too…and you need funds. 137’s power is that it is permissionless and not relevant until enough people care to enforce it. It lets a dapp dev make a fairly straightforward choice and then build their dapp without worrying about governance until they have an audience that worries about governance.

1 Like

decieved that something is NNS governed

Again…any thing installed on the IC is NNS governed. Making this claim is just reality. Yes if you slap “137 governed” on you dapp and no one every convey’s what that means or if you slap it on and are lying, then someone has to care enough to do something about it.

14% vote reject (didn’t opt-in to governing this)

These people are making a very odd choice if they just no-op vote because they don’t “wanna”. If it is on the IC it affects ICP price. They are just being lazy.

As an aside, implicit to the game theory is that it should very, very rarely ever get to an actual veto vote. Threats of a veto and raising the profile of shinanagans should eliminate mis-alignment in most cases(or if it doesn’t this this won’t work… that’s why we do the experiment).

The unstated presupposition of 137:

  1. Open source your code
  2. Announce upgrades with enough time to review
  3. Put yourself subject to veto for enough time to review.

…are just good governance for anyone wanting to build a currently private-potentially public service anyway.

I think this is an interesting experiment, and the problem it tries to address is important and worth experimentation :+1:

Personally, I think a better solution to the problem is to instead find 15 or so relatively well known individuals in the IC ecosystem from diverse places (DFINITY, hubs, governance participants, ecosystem devs etc.) and give them shared threshold control over an important canister along with a clear mandate - e.g. the canister should not be updated other than to patch breaking API changes. This is the approach that’s being taken for ALPHA-Vote. I’d be interested to know what you consider the tradeoffs to be with this alternative strategy.

The NNS holds a stance of not interfering with user canisters. Nobody expects the NNS to monitor every canister and codebase and take actions to prevent malicious intent. In fact when you involve time in the equation, a developer can update a canister much faster than the NNS can react. 137 is adding a bit more control by extending the window. But then if an SNS delays execution of proposals, you could also say they are gaining the same added NNS security, because the NNS can make a proposal to change the SNS and stop the proposal from executing.

As long as there is no promotion like “NNS secured/governed, better than the SNSes” I am fine with it. You can only say something like that if there was unanimous vote accepting to govern the service.

Just hoping you aren’t going to go deploying bridges and claim NNS secured, when at this point and rough calculations it looks like any developer paired with @wpb 's neurons will be gaining full control of 137 services, since only developers can propose upgrades and the NNS without Dfinity likely won`t be able to govern/veto them even if something malicious or self-serving was detected.

Again, I think the tech is cool, just hope these services wont be promoting themselves as something better than SNSes and claiming NNS security/governance, since there wont be one. These promotions will just make false claims and hurt other DAOs on the IC.

137 is in no way a ‘best’ or ‘better solution’. If you can pull off 15 well-known and trustworthy people(who are willing to pay attention and participate), then you likely don’t need 137. Our community is currently stuck together with popsicle sticks and glue. 137 is for builders that want to make it ways down the road before they have to talk to any of us jaded a-holes. 137 is basically a self-elected no-op until it organically bootstraps into something worth paying attention to, and then at that point, you do likely have other options you’ll want to start looking toward for maturity(oversight councils, SNSs, etc).

I’m not so sure that SNSs have much of a leg to stand on. They’ve got a pretty awful track record at this point. They may be good at some things, but are terrible at others. 137 is likely far better than an SNS for certain applications and far worse for others. For example, if you have no use for a token, an SNS is quite possibly the worst form of organization that you could select. The only thing you gain by doing one is giving an attacker a way to take over your utility. Both SNS and 137 are completely worthless under certain NNS configurations.

The NNS holds a stance of not interfering with user canisters.

I Dont Believe You Will Ferrell GIF

There are any number of black swan events where the NNS will 100% insta-interfere and I don’t think you have to be even a bit creative to come up with one. It is only a matter of time.


Certainly, having a mal-configured NNS is not great for 137. But also probably not great for SNSs. We have a long way to go to get to sufficient decentralization for the NNS, but it has also kinda worked for a bit. I’ll be the first to admit that it can go badly and 137 could stop being even possible.

1 Like

These veto proposals go thru people who are : caring; self-serving; misinformed; malicious; don’t care; auto-reject;
Devs only propose things they want. When you sum all these up, you end up with services which may benefit only a very small NNS neuron minority. So what’s left for the rest? They are going to be reviewing proposals, code and spend energy just to attempt to stop a service upgrade they can’t get anything from?
Just an idea: make it veto if 10% of the voting power used in the proposal has voted accept. Then these services will have to make the whole NNS happy with what they are doing. EDIT: Also make a proposal that agrees the NNS can change their canisters at any point.

Otherwise…

:open_book: Matthew 27:24

When Pilate saw that he was getting nowhere, but that instead an uproar was starting,
he took water and washed his hands in front of the crowd.

“I am innocent of this man’s blood,” he said. “It is your responsibility!”

no i summarized it and hid the responses so that it doesnt clutter the discussion. again, you are not the target demographic. I provided no 2 cents… I’m not qualified to have an opinion on this.

2 Likes

auto-reject

This is an interesting assumption. Why do you think that the default position would be auto-reject? I can only speak to my own assumptions and thinking about this, but it is my assumption that the frequency of these proposals will be ultra-rare. The self-imposed restrictions of the framework lead most differences to be resolved before it ever gets to a veto point. The signal-to-noise ratio should be very high. Unless someone with too much money to burn starts just spamming it to be a troll(something I haven’t quite figured out how to deal with just yet, but then again, I’m not sure that anyone has). The burden is on the vetoer to also amplify the signal. If you can convince Dom that the malfesence is bad enough that it will have a negative impact on the public view of the IC and the type of activity that is hosted on the network, and get him to make the veto proposal, I’d say the signal will be very high and the chance of people being disinterested would be very small. Of course, the signal degrades as you move down the trust chain, where a small user who feels they are going to lose just a few hundred dollars…even then, the signal can be very high if they make a clear case and people want the IC to be a place that is trusted. This ignores the fact that it would be irrational for a dev who wanted to pull off a scam to submit themselves to this scheme. It slows you down, makes you increase your transparency, and puts you at risk of having to play a very long con with a significant chance of no payoff. There are many faster and cheaper ways to rip people off.

When you sum all these up, you end up with services that may benefit only a very small NNS neuron minority.

I don’t really understand this comment, and you keep bringing it up…maybe you can help me understand? From a strictly utilitarian approach, it makes no sense.

For an NNS neuron holder, there is no irrelevant activity on the IC. Any negative utility or negative value activity makes your holding worth less. If crime is being committed on the IC and/or scams and/or shady practices and/or deceitful expectations…these all blow back on NNS Neuron value in the long run.

By developing on the IC you’re giving the NNS significant power over your application, and the fact that the NNS has that governance is likely the only long-term driver of value for ICP. The more value we put under NNS governance, the more demand for governance power there will be. This will ultimately dwarf any value contribution contributed by burning cycles. If we have valuable services built on the NNS and people who depend on them want to secure them, they have to buy governance power.

I’ll loop back again to the argument that 137 governance is a circle inside the circle of existing NNS governance power. It just makes it easier to do what is already possible. It is just a formalization of the software workflow. It is much safer than ‘trust me bro’. It likely isn’t as safe as many other options, but it is highly unintrusive for most happy path scenarios except for the dev who slows their rate of upgrade and makes them be more thoughtful and deliberate(likely +utility anyway).

Just an idea: make it veto if 10% of the voting power used in the proposal has voted accept.

There may be different thresholds and there may be different thresholds needed during different NNS universes over time as the makeup and decentralization change. This is an easy lever to put in the system so that developers can adjust the threshold to the level of trust they want to set. 137 already does this with the deposit amount for the veto, we can easily add it for the threshold. I think 50% is fine for starting the experiment, but maybe that needs to be adjusted. We’ll see.

I’ll add a todo to update the canister metadata params to include a threshold and update the code to check more than just pass/fail.

EDIT: Also make a proposal that agrees the NNS can change their canisters at any point.

This makes no sense to me. We already have the InstallCode proposal. It can be motioned by anyone on the NNS at any time. It will likely fail in most cases, but it is already available. Unless you’re implying that 10% should be able to change your canister at any time…but I think that is overaggressive.

“I am innocent of this man’s blood,” he said. “It is your responsibility!”

Human nature is very interesting and sometimes(most of the time) people don’t act the way I think they’ll act. The last 12 years have been one giant head-scratching moment for me. In this case, you seem to be implying that people simultaneously will 1. Lock money into the NNS 2. Not care about the kind of activity the NNS permits to occur. Perhaps you are right, and that noble ideal that the NNS will allow web3 ideals to flow unmolested for all times ever, but my gut tells me that the money locked it will 100% make that not the case. My assumption is the opposite: given a clear chance to provide positive utility and preserve value, the NNS will engage at any opportunity presented with a clear signal to act toward value.

There are many 137 vetos that do not have a clear signal, but submitting one is likely -ev in game theory terms for the submitter.

The high signal 137 vetos will likely be +ev for the NNS and thus I don’t think they will be ignored.

I’m assuming that you’re hung up on the chance that a Dev will present themselves as trustworthy with the label and then act in a manner that is not in line with that trust and get away with it.

Maybe let’s play that out?

137 should create a very high signal. For example, as an SNS you generally have to open source all the canisters that will be a part of your DAO and under SNS control(otherwise, how will they govern). We all generally agree this is a good idea, right? The SNS is a strong signal that you’re submitting to the prerequisite of open sourcing. The few times I’ve seen when an SNS didn’t want to do this, the signal of ‘not a valid SNS’ was certainly pretty strong. They either never got off the ground or were voted down.(note…there is nothing keeping a SNS from keeping everything it does post-launch closed source and outside of governance if it isn’t sufficiently decentralized…and possibly…given the desire to maintain token value, there may be an incentive to keep things closed and under a tight control of insiders as you can move faster and have to share less value…tokenizing has opportunities, but also burdens). If an SNS starts going off the rails, then it is the community’s responsibility to call it out and make it very clear that it isn’t a decentralized SNS and any buyers should beware that they are investing in the action of an individual group and not a ‘classic DAO’. I think this has generally happened. They still get listed under SNSs, though, even when we all know they are not a DAOish DAOs anymore. If your concerns about labels and safety are correct, why haven’t we done anything about this clear misrepresentation on dashboards and in the NNS dapp? (I’ll answer the question: Because a majority of the NNS VP is held by people who either benefit or don’t want to admit failure)

137 should also form a signal. The governed canister needs to be open-sourced. Devs need to announce upgrades/command calls with plenty of time to review. If a dev doesn’t do these things, the community should not let them get away with saying they have real 137 governance.

It is a “trust” thing. Is it annoying as a blockchain dev that this trust factor isn’t on-chain? Yes. It is very disappointing. In fact, it feels like admitting defeat, and that much of this experiment we’ve been trying has been a failure to date. I don’t want to depend on off-chain trust. I don’t want the signal to have to percolate through meat-space. I want it all on chain. But in reality, the on-chain experiments have generally failed and been a hindrance to growth. Maybe we’ll find the answer tomorrow, but until then, I’d like to get on with development and make some progress. If I have to depend on off-chain meat-trust until I have enough capital to afford launching a sufficiently decentralized DAO with troll-capture protections(note: currently this doesn’t seem to exist), then so be it. I think 137 has some nice step-ups and assurances from ‘trust me bro’. But only experiments will bear that out. A properly functioning SNS is almost certainly better when that is possible(when there is a token), but there are no good stepping stones to get there right now. I think 137 may end up being a good stepping stone.

Alpha Update

Good News: The proposal passed!

Bad News: A timing bug means that we won’t know if it worked for a couple days. Ooops.

Good News: I fixed the bug! Basically, when the veto was submitted, we added 4 day(the voting time) to the current execution time instead of the current time…so we’re waiting around for a timer.

Bad News: We have to wait 4 days for these upgrades to roll out(but that is the whole point…feel free to veto them if you’d like)(please don’t :grinning_face:)

I’ve also added a 137 dashboard to AstroFlora that shows the commands pending for the veto and veto life line canister. As more 137 canisters come online, I can add them easily. This is just a quick and dirty page and will get unwieldy once there are too many records.

3 Likes