From 8dd02c43456574bbc4e1fa877bb04267ee4e0103 Mon Sep 17 00:00:00 2001 From: Hillaryhardy Date: Mon, 21 Sep 2026 10:44:47 +0300 Subject: [PATCH 1/2] =?UTF-8?q?docs(testnet):=20write=20the=20current-gen?= =?UTF-8?q?=20staging=20plan,=20prepare=20the=20=C2=A76a=20re-run?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flashstack-ajv.6.3, the two halves that need no key. deployments/testnet-current-gen-plan.yaml — the plan scripts/deploy-testnet.mjs executes, written down: contract set, order, fees, nonce discipline, arguments. Every value is read off that script with a per-field line reference (§7 says to derive them there, not invent them in prose), so a reviewer can diff the file against the script instead of trusting it. evidence: slots are empty on purpose. It is deliberately NOT a Clarinet plan and says so loudly. Clarinet publishes source verbatim; on testnet that broadcasts contracts still carrying mainnet principals and aborts at publish time (§5.1). Different shape from the default.*-plan.yaml files beside it so the two cannot be confused. .gitignore — deployments/testnet-*.yaml matched the exact filename the bead asks for, so the file would have been silently untracked. Negated the same way testnet-plan.yaml already is. docs/TESTNET_STAGING.md §6c — the §6a replacement, pre-written so new txids drop straight in, keeping the Proven / NOT proven split. Fenced so its placeholder checkboxes cannot be misread as evidence; it asserts nothing. Two things found while writing it, both for the owner: 1. The re-run is not executable today by either route. Steps 1-3 publish names that already exist at ST3XQ5DM..., and a name is consumed permanently there (CONTRACT_INVENTORY §3). Route A (admin steps only, 300k uSTX) needs a step flag or a purpose-built script, because deploy-testnet.mjs is linear — and it does not literally satisfy "a run of the current deploy-testnet.mjs". Route B (fresh -v3 line, 53.31 STX) is not a rename in the script: stx-test-receiver-v2.clar:16 calls .flashstack-stx-core-v2 statically, so a -v3 core needs a -v3 receiver source too. 2. §6a's two remaining checklist items are not equal. "Unapproved receiver is rejected" needs no new contract. "Non-repaying receiver reverts" has no contract to run against at all — none exists for this core. Live state read before writing (sender ST3XQ5DM...): get-admin = deployer, get-pending-admin = none, get-reserve-balance = u50005000, is-approved-receiver = true, nonce 12, balance 946490000 uSTX. §6b's restore held. §7 and §8 updated: the plan file now exists, and next-action 4 (TESTNET_EQUIVALENT) landed in #55 — verified against the commit, 7521791, not assumed. Docs and one gitignore line only; no contract, no test, no Clarinet.toml touched. Suite 221/221 across 20 files (discovery unchanged). clarinet check 3.23.2: 211 contracts, 0 errors — identical to the clean tree at 737c659 measured in the same session, which gave 211/0 with a different warning count. Co-Authored-By: Claude Opus 5 (1M context) --- .gitignore | 1 + deployments/testnet-current-gen-plan.yaml | 263 ++++++++++++++++++++++ docs/TESTNET_STAGING.md | 118 +++++++++- 3 files changed, 378 insertions(+), 4 deletions(-) create mode 100644 deployments/testnet-current-gen-plan.yaml diff --git a/.gitignore b/.gitignore index 1500b69..e6b835d 100644 --- a/.gitignore +++ b/.gitignore @@ -151,6 +151,7 @@ SNP_INTEGRATION_STEPS.md TESTNET_DEPLOYMENT.md deployments/testnet-*.yaml !deployments/testnet-plan.yaml +!deployments/testnet-current-gen-plan.yaml # ============================================ # Frontend (web/) diff --git a/deployments/testnet-current-gen-plan.yaml b/deployments/testnet-current-gen-plan.yaml new file mode 100644 index 0000000..1db8bc6 --- /dev/null +++ b/deployments/testnet-current-gen-plan.yaml @@ -0,0 +1,263 @@ +# FlashStack — current-generation testnet staging plan +# +# THIS IS NOT A CLARINET DEPLOYMENT PLAN. Do not run it with +# `clarinet deployments apply`. It has a deliberately different shape from the +# `default.*-plan.yaml` files beside it so the two cannot be confused: those are +# Clarinet-generated and publish source verbatim, which on testnet would broadcast +# contracts still carrying mainnet principals and abort at publish time +# (docs/TESTNET_STAGING.md §5.1). +# +# This file is the written form of what `scripts/deploy-testnet.mjs` executes: the +# contract set, the order, the fees, the nonce discipline and the arguments. Every +# number below is READ OFF THAT SCRIPT — none is estimated, and none has been +# invented in prose (docs/TESTNET_STAGING.md §7). Source line references are given +# per field so a reviewer can diff the file against the script rather than trust it. +# +# The `evidence:` blocks are empty on purpose. They are filled in from a run, and +# every value must be independently re-verified against the live testnet API — not +# copied from the script's console output (docs/TESTNET_STAGING.md §6a). + +schema: flashstack-testnet-staging-plan/v1 +generated: 2026-09-21 +derived-from: scripts/deploy-testnet.mjs # at 737c659 +executed-by: node scripts/deploy-testnet.mjs # requires TESTNET_MNEMONIC, operator only +network: testnet +stacks-node: https://api.testnet.hiro.so # deploy-testnet.mjs:70 +explorer: https://explorer.hiro.so/txid # deploy-testnet.mjs:71 + +# ───────────────────────────────────────────────────────────────────────────── +# Deployer +# ───────────────────────────────────────────────────────────────────────────── +# Derived at runtime from TESTNET_MNEMONIC (deploy-testnet.mjs:95-103); it is not +# and must never be committed. The address below is the one that executed §6a/§6b +# and currently holds admin on the deployed core — recorded so a re-run can be +# checked against it, NOT as configuration the script reads. +deployer: + address: ST3XQ5DMH4BRXVZWAHKJFBNND17CPCSAYMV4T0NFT + source: derived from TESTNET_MNEMONIC at runtime + preflight: + # deploy-testnet.mjs:249-257 + warn-below-microstx: 5000000000 # prints a funding warning, then continues + hard-stop-below-microstx: 500000000 + # NOTE: the warning text says "~3000 STX", but the transactions below require + # 53.31 STX in total (see totals:). The threshold is conservative, not wrong; + # it is recorded here as the script behaves, not as the plan needs. + +# ───────────────────────────────────────────────────────────────────────────── +# Source localization — applied to every published contract before broadcast +# ───────────────────────────────────────────────────────────────────────────── +localization: + module: scripts/lib/testnet-localize.mjs # deploy-testnet.mjs:58, 105-115 + rule: >- + Every OURS principal is rewritten to the testnet deployer; every + TESTNET_EQUIVALENT principal to its verified testnet counterpart; any + surviving mainnet principal aborts the run before broadcast + (assertFullyLocalized). + affects-this-plan: + # The only mainnet principal present in this contract set. + - SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ: >- + gen-1 deployer, referenced by flashstack-stx-core-v2.clar:23 (use-trait) + and stx-test-receiver-v2.clar:10 (impl-trait). Rewritten to the deployer, + which is why stx-flash-receiver-trait must publish first. + no-testnet-equivalent-needed: true # this line touches no sBTC contract + +# ───────────────────────────────────────────────────────────────────────────── +# Nonce discipline +# ───────────────────────────────────────────────────────────────────────────── +nonces: + # deploy-testnet.mjs:261 then `nonce++` at each broadcast site. + start: fetched from /v2/accounts/?proof=0 at run time + allocation: strictly sequential, +1 per transaction, one signer, no gaps + batching: >- + None. Every transaction waits for confirmation before the next is built + (waitForConfirm, deploy-testnet.mjs:132-151 — 8s poll, 80 attempts, ~10min + ceiling per tx). There are no parallel batches; a failure stops the run. + +# ───────────────────────────────────────────────────────────────────────────── +# Transactions, in execution order +# ───────────────────────────────────────────────────────────────────────────── +# fee is in microSTX and is fixed by the script — it is not estimated per-tx. +# nonce-offset is relative to the starting nonce. +transactions: + + - step: 1 + type: contract-publish + contract-name: stx-flash-receiver-trait + path: contracts/stx-flash-receiver-trait.clar + clarity-version: 3 # deploy-testnet.mjs:182 + post-condition-mode: allow # deploy-testnet.mjs:183 + fee: 500000 # deploy-testnet.mjs:185 + nonce-offset: 0 + why: Must publish first — both contracts below resolve their trait to it. + evidence: { txid: null, block-height: null, status: null } + + - step: 2 + type: contract-publish + contract-name: flashstack-stx-core-v2 + path: contracts/flashstack-stx-core-v2.clar + clarity-version: 3 + post-condition-mode: allow + fee: 500000 + nonce-offset: 1 + why: The BC1 two-step-admin successor this whole staging line exists to prove. + evidence: { txid: null, block-height: null, status: null } + + - step: 3 + type: contract-publish + contract-name: stx-test-receiver-v2 + path: contracts/stx-test-receiver-v2.clar + clarity-version: 3 + post-condition-mode: allow + fee: 500000 + nonce-offset: 2 + why: >- + Minimal borrow-and-repay receiver. Its contract-call? target is the STATIC + `.flashstack-stx-core-v2` (stx-test-receiver-v2.clar:16) — see + execution-decision below, this is what makes a renamed line non-trivial. + evidence: { txid: null, block-height: null, status: null } + + - step: 4 + type: contract-call + contract: .flashstack-stx-core-v2 + function: add-approved-receiver + args: [ "principal .stx-test-receiver-v2" ] + fee: 100000 # deploy-testnet.mjs:194 default + nonce-offset: 3 + evidence: { txid: null, block-height: null, status: null } + + - step: 5 + type: contract-call + contract: .flashstack-stx-core-v2 + function: deposit-reserve + args: [ "uint 50000000" ] # RESERVE_AMOUNT, deploy-testnet.mjs:75 + fee: 200000 # deploy-testnet.mjs:319 + nonce-offset: 4 + evidence: { txid: null, block-height: null, status: null } + + - step: 6 + type: stx-transfer + recipient: .stx-test-receiver-v2 + amount: 1000000 # RECEIVER_SEED_AMOUNT, deploy-testnet.mjs:80 + memo: seed receiver fee # deploy-testnet.mjs:222 + fee: 10000 # deploy-testnet.mjs:213 default + nonce-offset: 5 + why: >- + The receiver repays principal + fee from its OWN balance; a freshly + published receiver holds 0 STX and the flash loan reverts with (err u500). + evidence: { txid: null, block-height: null, status: null } + + - step: 7 + type: contract-call + contract: .flashstack-stx-core-v2 + function: flash-loan + args: [ "uint 10000000", "principal .stx-test-receiver-v2" ] + fee: 200000 # deploy-testnet.mjs:349 + nonce-offset: 6 + asserts: + # Not asserted by the script; verified on review in §6a and repeatable. + - reserve grows by exactly 5000 microSTX (0.05% of 10 STX, fee-bp = u5) + evidence: { txid: null, block-height: null, status: null } + + # ── Step 8 — the reason this plan exists ────────────────────────────────── + # Three transactions with read-only assertions between them. The assertions, + # not the txids, are the evidence: a broken ONE-step transfer-admin would emit + # three identical successful txids. This sequence is a92fb8e's fix; §6a's + # BC1 rows predate it (docs/TESTNET_STAGING.md §6a, staleness note). + + - step: 8a + type: contract-call + contract: .flashstack-stx-core-v2 + function: transfer-admin + args: [ "principal ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM" ] # OTHER, :365 + fee: 100000 # deploy-testnet.mjs:373 + nonce-offset: 7 + why: >- + OTHER is the public Clarinet default testnet deployer — a real principal + this key does NOT control. Proposing to self (the pre-a92fb8e sequence) + leaves admin equal to the deployer before and after and therefore cannot + distinguish a correct two-step contract from a broken one-step one. + asserts: # deploy-testnet.mjs:377-381 + - get-admin == # MUST NOT have moved + - get-pending-admin == (some ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM) + evidence: { txid: null, block-height: null, status: null } + + - step: 8b + type: contract-call + contract: .flashstack-stx-core-v2 + function: transfer-admin + args: [ "principal " ] + fee: 100000 # deploy-testnet.mjs:388 + nonce-offset: 8 + why: >- + Re-propose to self. Safe with a single key because a second propose + overwrites pending-admin, and it doubles as proof that a fat-fingered + address is recoverable before anyone accepts it. + asserts: # deploy-testnet.mjs:392-393 + - get-pending-admin == (some ) + evidence: { txid: null, block-height: null, status: null } + + - step: 8c + type: contract-call + contract: .flashstack-stx-core-v2 + function: accept-admin + args: [] + fee: 100000 # deploy-testnet.mjs:399 + nonce-offset: 9 + asserts: # deploy-testnet.mjs:403-404 + - get-admin == + evidence: { txid: null, block-height: null, status: null } + +# ───────────────────────────────────────────────────────────────────────────── +totals: + transactions: 10 + fees-microstx: 2310000 # 3x500000 + 100000 + 200000 + 10000 + 200000 + 3x100000 + stx-moved-microstx: 51000000 # 50000000 reserve + 1000000 receiver seed + required-balance-microstx: 53310000 # 53.31 STX + +# ───────────────────────────────────────────────────────────────────────────── +# Execution decision — REQUIRED BEFORE THIS PLAN IS RUN +# ───────────────────────────────────────────────────────────────────────────── +# Read live from the API on 2026-09-21, sender ST3XQ5DM…: +# get-admin ST3XQ5DMH4BRXVZWAHKJFBNND17CPCSAYMV4T0NFT +# get-pending-admin none +# get-reserve-balance u50005000 +# get-fee-basis-points u5 +# is-approved-receiver(.stx-test-receiver-v2) true +# deployer nonce 12, balance 946490000 microSTX +# i.e. the §6a/§6b deployment is intact and §6b's restore held. +# +# Steps 1-3 publish contract names that ALREADY EXIST at that address. A contract +# name is consumed permanently at a principal whether or not the publish took +# effect (CONTRACT_INVENTORY §3, deployment scars), so running this plan +# unmodified against the same key cannot re-publish them. That leaves two routes, +# and they are not equally cheap: +# +# A. Admin steps only, against the existing deployment. +# Costs 300000 microSTX and touches nothing else — but deploy-testnet.mjs +# is linear and has no step selection, so it needs either a step flag or a +# purpose-built script (the precedent is scripts/deploy-testnet-bc1-negative.mjs, +# which §6b used for exactly this reason). Note Flashstack-ajv.6.3's +# acceptance criterion asks for "a run of the CURRENT deploy-testnet.mjs", +# which this route does not literally satisfy. +# +# B. A fresh -v3 line, full 10-step run. +# Costs 53.31 STX (affordable at the current balance, though the script's +# preflight will warn). But it is NOT a rename in the script: +# stx-test-receiver-v2.clar:16 calls `.flashstack-stx-core-v2` statically, so +# a -v3 core needs a -v3 receiver source too. New .clar files, review, and a +# wider diff than the BC1 evidence gap warrants. +# +# Owner decision. Until it is made, no txid belongs in this file. + +# ───────────────────────────────────────────────────────────────────────────── +# Not covered by this plan +# ───────────────────────────────────────────────────────────────────────────── +# Deliberately narrow, matching deploy-testnet.mjs:25-34: +# - flashstack-stx-pool-v3 (needs its own receiver, same static-target constraint) +# - flashstack-pool-v3 + flashstack-sbtc-core-v2 (multi-asset line, add-asset +# calibration, own receiver — stageable per #55 but a materially bigger deploy) +# Also not covered, and still open on the §6 checklist for this line: +# - non-repaying receiver reverts — no such contract exists for core-v2; one +# would have to be written and published. +# - unapproved receiver is rejected — needs no new contract, but no step here +# performs it. diff --git a/docs/TESTNET_STAGING.md b/docs/TESTNET_STAGING.md index ea94967..0ab84b7 100644 --- a/docs/TESTNET_STAGING.md +++ b/docs/TESTNET_STAGING.md @@ -398,6 +398,110 @@ result doesn't extend to them automatically. --- +## 6c. §6a re-run — PREPARED, NOT EXECUTED + +> **This section contains no evidence.** It is a form. Every value in the block +> below is a placeholder, and the checkboxes are inside a fenced code block +> precisely so they cannot be read as ticked. Nothing here has happened. + +§6a's BC1 rows come from the *pre-`a92fb8e`* Step 8 — propose-to-self, then +accept, with no read-only assertions — and §6a says outright that a re-run +against the current script is required, not optional. §6b proves the negative +case with a second key and explicitly does not substitute. The current Step 8 +(`scripts/deploy-testnet.mjs:354-405`) proposes to `ST1PQHQ…`, a principal the +signing key does not control, and asserts `get-admin` is **unchanged** in +between — the one assertion that distinguishes a correct two-step contract from +a broken one-step one. That is what has to be run. + +**The plan it runs is now written**: `deployments/testnet-current-gen-plan.yaml` +— contract set, order, fees, nonce discipline and arguments, each field +referenced back to the line of `deploy-testnet.mjs` it was read off, with empty +`evidence:` slots to fill. + +### The execution decision, which is not mine + +Live read of the §6a deployment on 2026-09-21 (sender `ST3XQ5DM…`): `get-admin` += the deployer, `get-pending-admin` = `none`, `get-reserve-balance` = +`u50005000`, `is-approved-receiver` = `true`, deployer nonce 12, balance +`946490000` µSTX. The deployment is intact and §6b's restore held. + +So Steps 1–3 of the plan would publish contract names that **already exist** at +that address, and a name is consumed permanently there whether or not the +publish took effect (`CONTRACT_INVENTORY` §3, deployment scars). Two routes: + +| | Route | Cost | What it needs first | +|---|---|---|---| +| **A** | Admin steps only, against the existing deployment | 300,000 µSTX | `deploy-testnet.mjs` is linear with no step selection, so this needs a step flag or a purpose-built script (precedent: `scripts/deploy-testnet-bc1-negative.mjs`, which §6b used for this reason). Does not literally satisfy "a run of the current `deploy-testnet.mjs`". | +| **B** | A fresh `-v3` line, full 10-step run | 53.31 STX | **Not a rename in the script.** `contracts/stx-test-receiver-v2.clar:16` calls `.flashstack-stx-core-v2` statically, so a `-v3` core needs a `-v3` receiver source too — new `.clar` files and a wider diff than this evidence gap warrants. | + +Owner's call. Until it is made, no txid belongs in the plan file or in §6a. + +### Drop-in replacement for §6a + +On a successful run, this replaces §6a in full — including deleting §6a's +staleness note, which no longer applies — and §6c goes away with it. + +```markdown +## 6a. Testnet run — + +`scripts/deploy-testnet.mjs` at `` run against ``. +Deployer: ``. Plan: `deployments/testnet-current-gen-plan.yaml`. +Every item below was independently re-verified against the live testnet API +after the run — sender, function, args and decoded result read off each tx — +not taken from the script's own success output. + +**Proven, with evidence:** +- [ ] All three publishes `success`: trait `` (block ``), core + `` (block ``), receiver `` (block ``) +- [ ] Source fetched back from `/v2/contracts/source/…` for `` matches + `localize(local-source, deployer)` byte-for-byte — compared, not eyeballed +- [ ] Interface check: public and read-only function sets on the deployed + `` match the local source in both directions — `` public, + `` read-only, zero unexpected on-chain functions. This is the check + that would have caught F-7. +- [ ] Flash loan happy path: reserve `` → ``, exactly the 0.05% + fee (5,000 µSTX on a 10 STX loan at `fee-bp` = `u5`), decoded from + `get-reserve-balance`, not assumed. `` (block ``) +- [ ] **BC1 with assertion strength** — the corrected Step 8 (`a92fb8e`), + proposing to a principal this key does not control: + - [ ] `transfer-admin` → `ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM`: + `` (block ``), `success` + - [ ] `get-admin` read immediately after: **still ``** — admin did + not move on propose. *This is the assertion the pre-fix run could not + make: propose-to-self leaves admin equal to the deployer either way.* + - [ ] `get-pending-admin` = `(some ST1PQHQ…)` — the proposal landed, and + landed on someone else + - [ ] `transfer-admin` → self (re-propose): `` (block ``); + `get-pending-admin` = `(some )` — the earlier proposal was + overwritten, so a mis-addressed proposal is recoverable before anyone + accepts it + - [ ] `accept-admin`: `` (block ``), `success`; `get-admin` = + ``, `get-pending-admin` = `none` +- [ ] Recorded in `deployments/testnet-current-gen-plan.yaml`: every + `evidence:` slot filled with txid, block height and status, alongside the + commit SHA staged + +**NOT proven by this run — genuinely open, not implied by the above:** +- [ ] Flash loan with a non-repaying receiver reverts — **no non-repaying + receiver contract exists for this core.** One has to be written and + published before this item can be attempted at all. +- [ ] Unapproved receiver is rejected — needs no new contract, but no step in + the plan performs it +- [x] ~~The negative case BC1 exists to prevent~~ — proven separately with a + second key. See §6b. +``` + +### Verification protocol for the filled-in version + +Each txid is checked against `/extended/v1/tx/0x`: `tx_status`, `sender_address`, +`contract_call.function_name`, decoded `function_args`, `tx_result.repr`, and +`block_height`. Each state claim is a fresh `/v2/contracts/call-read` **after** +the run, decoded through `scripts/lib/testnet-readonly.mjs` — not the value the +script printed during it. A row whose evidence cannot be reproduced that way +does not get ticked. + +--- + ## 7. What is deliberately not in this document Fees, nonce handling and batch ordering are **not** specified here. They should be @@ -406,8 +510,13 @@ against a real chain, rather than invented in prose. Writing plausible-looking operational numbers that have never been executed would be worse than leaving the gap visible. -Likewise, no deployment plan file for the current generation is committed by this -document. Writing one requires resolving §5.1–5.3 first. +A deployment plan for the current generation **is** now committed, at +`deployments/testnet-current-gen-plan.yaml` — §5.1–5.3 are all resolved, so the +precondition for writing one is met. It derives every fee, nonce and ordering +decision from `scripts/deploy-testnet.mjs` with per-field line references, rather +than restating them here. It is deliberately **not** a Clarinet plan and must not +be run with `clarinet deployments apply`: Clarinet publishes source verbatim, which +would broadcast contracts still carrying mainnet principals (§5.1). --- @@ -418,10 +527,11 @@ document. Writing one requires resolving §5.1–5.3 first. | 1 | ~~Confirm testnet epoch/clarity-version support for pool-v3 (§5.3)~~ | **DONE 2026-09-17 — testnet accepts Clarity 6** | | 2 | ~~Decide the sBTC mock question (§5.2)~~ | **DONE 2026-09-17 — byte-identical sBTC exists on testnet; no mock needed** | | 3 | ~~Extend the patcher (§5.1)~~ | **DONE — PR #55**, `scripts/lib/testnet-localize.mjs` | -| 4 | Map `SM3VDXK3…` → `ST1PQHQ…` in the localizer and move it from `THIRD_PARTY` to a new `TESTNET_EQUIVALENT` set | Nothing | +| 4 | ~~Map `SM3VDXK3…` → `ST1PQHQ…` in the localizer and move it from `THIRD_PARTY` to a new `TESTNET_EQUIVALENT` set~~ | **DONE — PR #55**, `TESTNET_EQUIVALENT` in `scripts/lib/testnet-localize.mjs` | | 5 | ~~Determine how the deployer obtains a testnet sBTC balance~~ | **DONE 2026-09-18 — SIP-010 `transfer` from `ST1PQHQ…`, which holds 80 sBTC. Minting is unreachable and unnecessary (§5.2)** | -| 6 | Write `deployments/testnet-current-gen-plan.yaml` | 4, 5 | +| 6 | ~~Write `deployments/testnet-current-gen-plan.yaml`~~ | **DONE 2026-09-21** — written from `deploy-testnet.mjs`, `evidence:` slots empty pending a run | | 7 | Execute the stage and record evidence | A funded testnet deployer — **operator only** | +| 8 | Re-run §6a against the corrected Step 8 (`a92fb8e`) | The route A/B decision in §6c, then 7 | **All three original blockers are now closed.** The entire current generation — the STX line, `flashstack-pool-v3`, *and* the sBTC line — can be staged faithfully. What From a9fd486f1fd04a2beb89136f29a92a8db0bfa835 Mon Sep 17 00:00:00 2001 From: Hillaryhardy Date: Mon, 21 Sep 2026 12:01:08 +0300 Subject: [PATCH 2/2] docs(testnet): record the route A decision and the flag that implements it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Owner picked route A. §6b already proves the property on this deployment, so the gap is assertion strength on the positive path, not a deployment — and B would rewrite contracts to fix a documentation problem. B is parked: staging flashstack-stx-pool-v3 is worth more than a -v3 rename. §6c's route table and the plan file's execution-decision block updated to say so, and to name deploy-testnet.mjs --steps=admin (PR #66) as what makes A executable. Recorded honestly rather than quietly: --steps=admin runs deploy-testnet.mjs's own Step 8 path — extracted into proveBC1(), not copied — but not the whole script, so it does not literally satisfy ajv.6.3's original "a run of the CURRENT deploy-testnet.mjs". That criterion was amended in Beads to say so openly. Consequence for the plan file, now stated in it: steps 1-7 stay unexecuted for this line, since they are already on chain from the §6a run. Only the 8a/8b/8c evidence: slots get filled. Steps 1-7 remain the written record of how that deployment was produced, and the plan a new line would follow. Docs only; the YAML still parses. Co-Authored-By: Claude Opus 5 (1M context) --- deployments/testnet-current-gen-plan.yaml | 17 ++++++++++++++--- docs/TESTNET_STAGING.md | 19 +++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/deployments/testnet-current-gen-plan.yaml b/deployments/testnet-current-gen-plan.yaml index 1db8bc6..8b42c03 100644 --- a/deployments/testnet-current-gen-plan.yaml +++ b/deployments/testnet-current-gen-plan.yaml @@ -234,11 +234,13 @@ totals: # # A. Admin steps only, against the existing deployment. # Costs 300000 microSTX and touches nothing else — but deploy-testnet.mjs -# is linear and has no step selection, so it needs either a step flag or a +# is linear and had no step selection, so it needed either a step flag or a # purpose-built script (the precedent is scripts/deploy-testnet-bc1-negative.mjs, # which §6b used for exactly this reason). Note Flashstack-ajv.6.3's # acceptance criterion asks for "a run of the CURRENT deploy-testnet.mjs", -# which this route does not literally satisfy. +# which this route does not literally satisfy — ajv.6.3's criterion was +# amended to say so openly. --steps=admin runs that script's own Step 8 +# path, extracted rather than copied, but not the whole script. # # B. A fresh -v3 line, full 10-step run. # Costs 53.31 STX (affordable at the current balance, though the script's @@ -247,7 +249,16 @@ totals: # a -v3 core needs a -v3 receiver source too. New .clar files, review, and a # wider diff than the BC1 evidence gap warrants. # -# Owner decision. Until it is made, no txid belongs in this file. +# DECIDED 2026-09-21: route A. `deploy-testnet.mjs --steps=admin` (PR #66) runs +# Step 8 and nothing else against the existing deployment, and refuses unless the +# contract exists, admin is the signing deployer and pending-admin is none +# (scripts/lib/testnet-preconditions.mjs). B is parked: staging +# flashstack-stx-pool-v3 is worth more than a -v3 rename. +# +# CONSEQUENCE FOR THIS FILE: steps 1-7 stay unexecuted for this line — they are +# already on chain from the §6a run. Only the 8a / 8b / 8c evidence: slots get +# filled by the re-run. The steps above remain the written record of how that +# deployment was produced, and the plan a NEW line (pool-v3, sbtc) would follow. # ───────────────────────────────────────────────────────────────────────────── # Not covered by this plan diff --git a/docs/TESTNET_STAGING.md b/docs/TESTNET_STAGING.md index 0ab84b7..20c10c3 100644 --- a/docs/TESTNET_STAGING.md +++ b/docs/TESTNET_STAGING.md @@ -418,7 +418,7 @@ a broken one-step one. That is what has to be run. referenced back to the line of `deploy-testnet.mjs` it was read off, with empty `evidence:` slots to fill. -### The execution decision, which is not mine +### The execution decision — made: route A Live read of the §6a deployment on 2026-09-21 (sender `ST3XQ5DM…`): `get-admin` = the deployer, `get-pending-admin` = `none`, `get-reserve-balance` = @@ -431,10 +431,17 @@ publish took effect (`CONTRACT_INVENTORY` §3, deployment scars). Two routes: | | Route | Cost | What it needs first | |---|---|---|---| -| **A** | Admin steps only, against the existing deployment | 300,000 µSTX | `deploy-testnet.mjs` is linear with no step selection, so this needs a step flag or a purpose-built script (precedent: `scripts/deploy-testnet-bc1-negative.mjs`, which §6b used for this reason). Does not literally satisfy "a run of the current `deploy-testnet.mjs`". | -| **B** | A fresh `-v3` line, full 10-step run | 53.31 STX | **Not a rename in the script.** `contracts/stx-test-receiver-v2.clar:16` calls `.flashstack-stx-core-v2` statically, so a `-v3` core needs a `-v3` receiver source too — new `.clar` files and a wider diff than this evidence gap warrants. | - -Owner's call. Until it is made, no txid belongs in the plan file or in §6a. +| **A** ✅ | Admin steps only, against the existing deployment | 300,000 µSTX | **Chosen.** Needed step selection, which `--steps=admin` now provides (PR #66). Note it is a run of `deploy-testnet.mjs`'s own Step 8 path — extracted, not copied — but not of the *whole* script; `Flashstack-ajv.6.3`'s acceptance criterion was amended to say so. | +| **B** ❌ | A fresh `-v3` line, full 10-step run | 53.31 STX | **Not a rename in the script.** `contracts/stx-test-receiver-v2.clar:16` calls `.flashstack-stx-core-v2` statically, so a `-v3` core needs a `-v3` receiver source too — new `.clar` files and a wider diff than this evidence gap warrants. **Parked:** staging `flashstack-stx-pool-v3` is worth more than a `-v3` rename. | + +**Decided 2026-09-21: route A.** §6b already proves the property on this +deployment, so the gap is assertion strength on the positive path, not a +deployment — and B would rewrite contracts to fix a documentation problem. +`deploy-testnet.mjs --steps=admin` (PR #66) runs Step 8 and nothing else, and +refuses unless the contract exists, admin is the signing deployer and +pending-admin is `none` (`scripts/lib/testnet-preconditions.mjs`). Steps 1–7 of +the plan file below therefore stay unexecuted for this line; only the 8a/8b/8c +`evidence:` slots get filled. ### Drop-in replacement for §6a @@ -531,7 +538,7 @@ would broadcast contracts still carrying mainnet principals (§5.1). | 5 | ~~Determine how the deployer obtains a testnet sBTC balance~~ | **DONE 2026-09-18 — SIP-010 `transfer` from `ST1PQHQ…`, which holds 80 sBTC. Minting is unreachable and unnecessary (§5.2)** | | 6 | ~~Write `deployments/testnet-current-gen-plan.yaml`~~ | **DONE 2026-09-21** — written from `deploy-testnet.mjs`, `evidence:` slots empty pending a run | | 7 | Execute the stage and record evidence | A funded testnet deployer — **operator only** | -| 8 | Re-run §6a against the corrected Step 8 (`a92fb8e`) | The route A/B decision in §6c, then 7 | +| 8 | Re-run §6a against the corrected Step 8 (`a92fb8e`) | **Route A chosen**; `--steps=admin` in PR #66. Then a funded key — operator only | **All three original blockers are now closed.** The entire current generation — the STX line, `flashstack-pool-v3`, *and* the sBTC line — can be staged faithfully. What