Skip to content

fix(token): check the contract a swap installs - #334

Open
hpmaxi wants to merge 2 commits into
fix/compliance-ttl-on-creationfrom
fix/332-check-token-swaps
Open

hpmaxi wants to merge 2 commits into
fix/compliance-ttl-on-creationfrom
fix/332-check-token-swaps

Conversation

@hpmaxi

@hpmaxi hpmaxi commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #332

After setup, a compliance or verifier swap on the share token waited for the timelock, but nothing checked the new contract. A compliance contract that did not list the token stopped every mint, transfer and burn. A verifier that did not answer made every holder look delisted.

The token now checks the new contract when the swap is proposed and again when it applies, as the vault does for a new oracle feed.

Changes

  • A compliance swap needs a contract that names the token's vault, has its setup closed and lists the token (ComplianceNotBound, 7017).
  • A verifier swap needs a verifier that accepts the vault's address (VerifierRefusesVault, 7018).
  • A missing or failing contract counts as a refusal.
  • The test that pinned an unbound swap landing now expects the refusal.

Deviations

  • Timelock tests that used a swap to a random address as filler now use a role grant.
  • The vault's silent-verifier test now sets the verifier in storage, since a swap refuses it.
  • The network guard that checks the compliance account cannot propose a token change named the compliance contract as the new verifier. That contract now fails the check in simulation, before the signature, so the guard proposes the deployed verifier instead.

Acceptance criteria

  • A compliance swap is refused unless the new contract names this token's vault, has finished its setup, and has this token bound
  • An identity-verifier swap is refused unless the new verifier answers and accepts the vault's address
  • Both checks run when the change is proposed and again when it applies, and a contract that does not answer fails them
  • Tests cover each refusal and a valid swap, and the docs list the checks

Test plan

Automated tests

  1. Run SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 cargo test --locked. Expect 728 passed, 0 failed (721 before: 7 new tests, 2 updated).
  2. Run cargo clippy --locked --all-targets -- -D warnings. Expect no warnings.
  3. Run cargo fmt --all -- --check. Expect no output.
  4. Run stellar contract build --package share-token. Expect 56,531 bytes optimized (55,315 before).
  5. Build the Wasm as the CI step "Run the Wasm upgrade tests" does, then run SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 cargo test --locked -p async-vault -p nav-oracle --features upgrade_wasm with_wasm. Expect 7 passed, including the_token_upgrades_under_live_balances_and_open_requests.
  6. On a local network started from the CI image, run in scripts/harness with HARNESS_NETWORK=local: npm run deploy, npm run test:happy-path, npm run test:guards, then build the vault with CARGO_TARGET_DIR=target/short-wind-down stellar contract build --package async-vault --features short_wind_down and run npm run test:wind-down. Expect 24, 50 and 6 passed.

Manual verification

None.

Breaking changes

After setup, a compliance swap to a contract that does not answer VaultBinding is refused, though finish_setup accepts such an external module. The design doc now says so. Generated clients gain two error variants.

Checklist

  • Self-reviewed my own diff
  • Tests added or updated
  • Docs updated (if applicable)
  • No unrelated changes bundled in

Screenshots

None.

After setup, a Compliance or IdentityVerifier change waited for the
vault's timelock, but nothing checked the new contract. Rules that did
not list the token, or ran on another vault's clock, landed and stopped
every mint, transfer and burn. A verifier that refused the vault or did
not answer made holders look delisted.

propose_change and apply_change now refuse such a swap. New rules must
name the token's vault with their setup closed and list the token in
linked_tokens (ComplianceNotBound, 7017). A new verifier must accept
the vault's address (VerifierRefusesVault, 7018). The calls go through
try_ clients, so a contract that is missing or fails counts as a
refusal instead of aborting the call.

The vault test that pinned an unbound swap landing now expects the
refusal. The design notes, the kit spec, the authorization matrix and
the test map list the checks.
@vercel

vercel Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
strata-vault-kit-app Ready Ready Preview Oct 22, 2026 7:04pm UTC

Request Review

The guard that checks the compliance account cannot propose a token
change named the compliance contract as the new identity verifier. The
token now refuses a verifier that does not accept the vault, so the
call failed in simulation instead of on the missing signature. Propose
the deployed verifier, so the signature is the only reason left.

This branch was successfully deployed

1 active deployment
Preview — 74023040 Deployed Oct 22, 2026 by vercel[bot]
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.

1 participant