Skip to content

fix(registry): fail on missing governance entries and fix splitter/batch sender rows - #201

Merged
truthixify merged 2 commits into
wraith-protocol:developfrom
izzetemredemir:fix/182-splitter-batch-sender-governance
Oct 18, 2026
Merged

truthixify merged 2 commits into
wraith-protocol:developfrom
izzetemredemir:fix/182-splitter-batch-sender-governance

Conversation

@izzetemredemir

@izzetemredemir izzetemredemir commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Closes #182

The governance entries this check needs landed in wraith-protocol/contracts#255 (merged as affc51c), and the registry is pinned to that commit.

Problem

check-contract-registry.mjs only warned when a mainnet contract had no governance entry in the pinned contracts manifest. stealth-splitter and stealth-batch-sender had none, so their upgradeable: true rows were never checked. Neither contract has an upgrade path.

Upgrade model, checked against the contracts source

Contract Upgrade path Authority
stealth-splitter None: no function calls update_current_contract_wasm No admin, no pause. init stores the announcer once.
stealth-batch-sender None A pause admin, set once by init and never changed after; it can only pause and unpause batch_send. A signer multisig, set once by init_multisig, can only rotate its own signers, behind a 7-day timelock.

Sources: stellar/stealth-splitter/src/lib.rs and stellar/stealth-batch-sender/src/{lib.rs,multisig.rs} on contracts develop 66273f2. This matches AUTHORIZATION_MATRIX.md there. contracts#255 records both in audit-prep/DEPLOYMENT_MANIFEST.md:

  • the splitter under "Frozen Contracts (No Admin)";
  • the batch sender under a new "Non-Upgradeable Contracts (Pause Admin)" section, because it has a pause admin.

Changes

  • scripts/contract-registry.json

    • Both contracts are now upgradeable: false in the testnet and mainnet rows.
    • The pin is moved, and verifiedAt is updated (the full verification was re-run).
  • reference/contract-registry.mdx: two rows added to the "Governance and upgradeability" table.

  • scripts/check-contract-registry.mjs

    • A missing governance entry is a failure, for a contract listed on any network.
    • A pin whose manifest returns 404 is a failure. Transient network errors are still warnings.
    • The parser reads the new "Non-Upgradeable Contracts" section as upgradeable: false.
    • upgradeable must be a boolean, and the same contract version must have the same flag on every network. Only mainnet rows are compared with the manifest, and the testnet rows had the same wrong true.
    • The pure checks are exported. main() only runs when the file is executed directly, comparing real paths so a symlinked checkout still runs.
  • scripts/check-contract-registry.test.mjs (new): 8 node:test cases covering:

    • section parsing, with only line-start entries counted;
    • a missing entry fails, on mainnet and for a testnet-only contract;
    • a flag that disagrees with the manifest fails;
    • matching entries pass;
    • a cross-network mismatch for the same version fails, while different versions may differ;
    • a non-boolean upgradeable fails.

    check:contract-registry runs them before the network checks, so CI covers them without a workflow change. test:contract-registry runs them alone.

Pin

pinnedContractsRepoCommit is affc51c, the merge commit of contracts#255 on develop. It was moved from the PR head in a separate commit. The branch is rebased on the current develop, and the full checks pass again (with network verification and no warnings).

Testing

  • pnpm test passes: snippets, nav coverage, the 8 new tests, the full registry check with network verification (no warnings), the compatibility matrix, and the redirects tests. check:placeholders and check:redirects-and-anchors pass as well.
  • Negative checks:
    • With the old pin 7bc1c6c, the check exits 1 and names both contracts.
    • With a pin that does not exist, it exits 1 with the 404 message.
    • With mainnet stealth-batch-sender set back to true, it fails on both the manifest mismatch and the cross-network mismatch.
    • Run through a symlinked checkout, it still checks the registry.
    • Removing the missing-entry failure, or the line anchor in the entry regex, makes the new tests fail.

Noticed, not changed

The registry page and the manifest also list stealth-sender and wraith-names as upgradeable, but neither has an upgrade entry point on contracts develop. The page also says wraith-names has no pause, while the contract has pause/unpause. I left both alone: they need a decision on the intended model (see the note in contracts#255).

@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

@izzetemredemir Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@truthixify truthixify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stricter registry governance validation passes all focused and offline registry checks. Approved; leaving the draft unmerged.

…tch sender rows

The contract registry check only warned when a mainnet contract had no
governance entry in the pinned contracts manifest. That is how
stealth-splitter and stealth-batch-sender stayed unverified while the
registry listed both as upgradeable, although neither contract has an
upgrade entrypoint.

Registry and page:
- Record both contracts as non-upgradeable in the testnet and mainnet
  rows and in the governance table on the registry page.
- Re-pin pinnedContractsRepoCommit to the contracts commit that adds
  their governance entries.

Check script:
- A missing governance entry is a failure. This applies to a contract
  listed on any network, not only mainnet.
- A pinned manifest that returns 404 is a failure. Network errors are
  still warnings.
- Parse the manifest's new "Non-Upgradeable Contracts" section. It holds
  contracts with immutable code and a pause admin.
- `upgradeable` must be a boolean, and the same contract version must
  have the same flag on every network.
- main() runs when the script is invoked through a symlinked path.

Tests:
- Export the pure checks and add node:test coverage.
- check:contract-registry runs the tests before the network checks, so
  CI runs them without workflow changes.

Closes #182
wraith-protocol/contracts#255 merged as affc51c. Pin it instead of the
PR head so the registry is checked against the manifest on develop.
@izzetemredemir
izzetemredemir force-pushed the fix/182-splitter-batch-sender-governance branch from 6e1e2e7 to 6d2de9f Compare October 17, 2026 15:40
@izzetemredemir
izzetemredemir marked this pull request as ready for review October 17, 2026 15:40

@truthixify truthixify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The branch is ready after rebasing onto the merged governance source. All eight focused registry tests pass, the pin now targets the contracts #255 merge commit, and the required documentation checks are green.

@truthixify
truthixify merged commit 0a582c1 into wraith-protocol:develop Oct 18, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Wave 10] Complete governance metadata for splitter and batch sender

2 participants