# Jing v3 peer review: governance footguns and reproducibility results

Reviewer: Turbo Ivo  
Date: 2026-06-04  
Repository: https://github.com/Rapha-btc/jing-contracts-v3

## Executive summary

I manually reviewed the core registry/admin and vault authorization paths, ran the
published Vitest suite, and attempted the published Rendezvous workflow. I did
not reproduce the previously reported rolled-cycle, dust, or intent-hash
findings. I found one low-severity governance footgun and one informational
event/state issue.

## L-01: Single-step owner transfer can permanently brick protocol administration

Severity: Low

Location: `contracts/jing-core.clar:339-343`

`set-contract-owner` immediately writes any supplied principal as the new
owner. There is no pending-owner state, acceptance transaction, recovery path,
or event. A typo, wrong multisig principal, inaccessible contract principal, or
operational signing mistake permanently removes the only authority able to:

- pause or unpause the protocol;
- approve verified contract templates; and
- rotate ownership again.

The risk is amplified because verified templates are intentionally one-way and
the protocol-level response to a flawed template is documented as `pause`.

Suggested fix: implement a two-step `propose-owner` / `accept-owner` flow,
allow cancellation by the current owner before acceptance, and emit events for
both transitions.

## I-01: `unpause` succeeds when the protocol was never paused

Severity: Informational

Location: `contracts/jing-core.clar:324-336`

`paused-at` initializes to `u0`, and `unpause` does not assert that `paused` is
currently true. Once burn height is at least `TIMELOCK_BURN_BLOCKS`, the owner
can call `unpause` on an already-open protocol and emit an `unpaused` event.
This does not directly move funds, but it can create misleading governance and
monitoring history.

Suggested fix: add `(asserts! (var-get paused) ERR_NOT_PAUSED)` before the
timelock assertion.

## Test and fuzz results

### Published Vitest suite

Command:

```text
npm ci
npm test
```

Result:

```text
Test Files  6 failed | 1 passed | 1 skipped (8)
Tests       49 failed | 100 passed | 12 skipped (161)
Duration    77.62s
```

Many failures originate in fixture funding calls returning `(err u1)`.
Several vault authorization tests also received `(err u6001)` where the test
expected later validation errors such as `(err u6002)` or `(err u6004)`.
Because these failures occur on the repository's published suite without
contract modifications, they reduce confidence that a fresh reviewer can
reproduce the documented green baseline.

### Rendezvous property fuzz attempt

Attempted the documented market target with 100 runs. RV exited before running
properties because the required generated target was absent:

```text
ENOENT: no such file or directory, open
tests/rv/.build/markets-sbtc-usdcx-jing.clar
```

The documented build helper is a Bash script, which was not runnable in this
Windows environment. No invariant violation is claimed from this failed run.

### stxer simulations

The published stxer flow could not be executed from this environment without
the external mainnet-fork runtime. No fabricated simulation link or result is
included.

## Manual review coverage

- `jing-core.clar`: owner/admin functions, verified template registration,
  pause gates, unified registry, and equity credit/debit helpers.
- `jing-vault-auth.clar`: SIP-018 domain and intent tuple construction.
- `vault-sbtc-usdcx.clar` and `vault-sbtc-stx.clar`: replay, expiry, signer,
  and intent-consumption paths.

## Limitations

This is an early peer review, not a formal audit. The report intentionally
separates reproducible findings from tooling failures and does not claim that
the full suite failure count represents 49 contract vulnerabilities.
