Skip to content

chore: review-only diff of the Paseo v0.8.0 upgrade (do not merge) - #312

Closed
re-gius wants to merge 34 commits into
masterfrom
dev/testnet-upgrades
Closed

re-gius wants to merge 34 commits into
masterfrom
dev/testnet-upgrades

Conversation

@re-gius

@re-gius re-gius commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Review only. Never merged. Do not close either: this PR is also the broadcast console.

dev/testnet-upgrades is a permanent branch (see CONTRIBUTING): master flows into it, never back. This PR exists to review the upgrade in one diff, to get a full CI run over it, and to drive the broadcast: adding a run:<Script> label here triggers one gated runbook step, which pauses on the paseo-upgrade environment until a reviewer approves it, then reports back as a comment and removes its label. docs/PASEO-V080-RUNBOOK.md on the head branch is the order and the operating manual. The PR stays open until the upgrade is declared and verified; close it after that.

70 files, 20 commits, but only six shipped contracts change, all storage layout, no behaviour:

Contract Change
DotnsRegistrar, DotnsPopController gap 50 to 49
DotnsRegistrarController gap 49 plus retained __whiteListSlot, so protocolRegistry keeps its slot
DotnsNameWhitelist retained AccessControl namespace
DotnsProtocolRegistry gap 48; #304 appended two fields without shrinking it
UserStore gap 49; same defect, harmless at zero user stores

Without these the live proxies fail the layout diff, and the registrar controller would read protocolRegistry as zero and brick.

Everything else is upgrade material: 23 storage snapshots of the deployed code (c8520046, not any tag), 13 upgrade and migration scripts, 13 fork tests, StoreFactoryMigrator, the runbook.

Type

  • Bug fix
  • Feature
  • Breaking change
  • Documentation
  • Chore
  • Refactor
  • Security

Scope

  • Registration
  • Resolver
  • Store
  • Proof of Personhood
  • Deployment scripts
  • Tests

Related Issues

Supersedes #281, closed as permanent-by-design. Branch content merged via #310 and #311.

Fixes

Every pre-existing Old.sol snapshot described an implementation replaced in place months ago, so each layout diff compared the wrong pair while staying green. The store-factory migration could not have been broadcast at all.

Checklist

Code

  • Follows project style
  • forge build passes
  • forge test passes
  • No new compiler warnings

Testing

  • New tests added for changed behavior
  • Fuzz tests added where applicable
  • Invariant tests verified

Security

  • No new selfdestruct or delegatecall
  • Access control reviewed
  • No storage layout conflicts (for upgradeable contracts)

Documentation

  • NatSpec updated on changed interfaces
  • README updated if needed

Breaking Changes

  • No breaking changes
  • Breaking changes documented below

Breaking changes:

How to test

forge test --match-path 'test/unit/upgrade/LayoutCompatibility.t.sol'
RPC_URL=https://eth-rpc-paseo-next.polkadot.io scripts/shell/verify-snapshots.sh
PASEO_FORK_RPC=https://eth-rpc-paseo-next.polkadot.io \
  RPC_URL=https://eth-rpc-paseo-next.polkadot.io scripts/shell/fork-tests.sh

Notes

15 fork tests pass against live Paseo, plus 13 layout checks and 6 migrator unit tests. verify-snapshots.sh proves every snapshot reproduces the deployed bytecode, which is the check that would have caught the stale ones.

DotnsRegistrarController's deployed code will differ from the v0.8.0 tag permanently, so verify --tag reports that one key as drift by design; a second key is a real finding. See DEPLOYMENTS.md and deployments/paseo-assethub/README.md.

Merging this would put 23 Old.sol files on master, which CONTRIBUTING tells reviewers to refuse. That rule is correct and this PR is the documented exception: a review vehicle, not a merge candidate.

sphamjoli and others added 20 commits September 9, 2026 00:55
Brings the numeric-namespace change onto the upgrade-tooling branch and adds the
PR-scoped upgrade scripts, pinned pre-upgrade snapshots, and fork tests that swap
the registry, PoP controller, PoP rules, and reverse resolver proxies in place
and redeploy the lens, so every address is kept. The fork suite issues a lite
username against live state to prove it lands as a subname beneath its numeric
container.
Brings the generic SubnodeUtils, the unified lite-node derivation, the registry
write returning the subnode, and the lens store-row and cold-path fixes onto the
in-place upgrade branch, so the swapped implementations carry them.
Brings the clarified `persist` documentation and the registry store-write tests
onto the in-place upgrade branch so it stays in step with the feature branch.
## Description

Upgrades the deployed proxies in place so the numeric-namespace change
reaches live state while
every address is kept. It swaps the registry, PoP controller, PoP rules,
and reverse resolver
implementations behind their existing proxies and redeploys the
immutable lens, repointing the
`popLens` key. Each proxy swap resolves its target from the on-disk
manifest and diffs the new
storage layout against a pinned pre-upgrade snapshot, failing closed if
a slot moves, shrinks, or
changes type.

Fork tests run each script against live Paseo Asset Hub state through
the ETH-RPC adapter. One test
per upgrade proves the swap keeps the address, the owner, and the state;
an end-to-end test issues a
lite username and checks it lands as a subname beneath its numeric
container, owned in the registry
rather than held as a token.

Every upgrade script, pre-upgrade snapshot, and fork test in this change
is scoped to this pull
request and removed before merge, so the default branch keeps no upgrade
scaffolding and the fork
suite runs zero tests between upgrades.

This branch is based on the upgrade-tooling branch and carries the
numeric-namespace contract change
so the swapped implementations contain it.

Migration note: lite usernames issued before this upgrade were recorded
as atomic labels under the
top level. The upgraded code addresses a lite name at the
container-then-stem node, so a pre-upgrade
lite name is not read by the new path and its subname node can be issued
afresh. That overwrite is
accepted.

## Type

- [ ] Bug fix
- [x] Feature
- [x] Breaking change
- [ ] Documentation
- [ ] Chore
- [ ] Refactor
- [ ] Security

## Scope

- [x] Registration
- [x] Resolver
- [ ] Store
- [x] Proof of Personhood
- [x] Deployment scripts
- [x] Tests

## Related Issues

- #287

## Fixes

## Checklist

### Code

- [x] Follows project style
- [x] `forge build` passes
- [x] `forge test` passes
- [x] No new compiler warnings

### Testing

- [x] New tests added for changed behavior
- [ ] Fuzz tests added where applicable
- [ ] Invariant tests verified

### Security

- [x] No new `selfdestruct` or `delegatecall`
- [x] Access control reviewed
- [x] No storage layout conflicts (for upgradeable contracts)

### Documentation

- [x] NatSpec updated on changed interfaces
- [ ] README updated if needed

### Breaking Changes

- [ ] No breaking changes
- [x] Breaking changes documented below

**Breaking changes:**

- Lite usernames issued before this upgrade are addressed at a different
node afterwards and are not
migrated. Their subname node can be issued afresh, so a pre-upgrade lite
name is not preserved.

## How to test

Fork tests need the local ETH-RPC adapter on `paseo_local`.

```bash
bun run test:fork
```

## Notes

Upgrade scripts run through `scripts/deploy/upgrade.sh`, for example
`SCRIPT=UpgradeRegistry ACCOUNT_NAME=<keystore> RPC_URL=<network>
./scripts/deploy/upgrade.sh`.
Brings the dev branch up to tag v0.8.0 (3c8a9e9), so the upgrade artefacts sit
on top of the released code instead of a fork point 43 commits behind it. This
is step 1 of the Paseo in-place upgrade: #301 (writeNewLabel), #304 (protocol
version and codehash declarations), #298 (UUPS StoreFactory) and #305 (deferred
store-write gate) all arrive before any upgrade script is written against them.

The textual merge was conflict-free, but it left one semantic conflict:
DotnsRegistryOld calls StoreUtils.writeLabel, which #301 removed. The snapshot
has to keep reproducing the implementation deployed on chain, so it cannot move
to writeNewLabel. Resolved by adding contracts/utils/StoreUtilsOld.sol, a
verbatim PR-scoped snapshot of the library as deployed, and pointing the Old
registry at it. It is deleted along with every other *Old.sol before the upgrade
branch merges to master.

Outside *Old.sol, the contract diff against master is the four storage-layout
fixes this branch carries and nothing else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Description

Merges master at v0.8.0 (3c8a9e9) into the upgrade branch

## Type

- [ ] Bug fix
- [ ] Feature
- [ ] Breaking change
- [ ] Documentation
- [x] Chore
- [ ] Refactor
- [ ] Security

## Scope

- [ ] Registration
- [ ] Resolver
- [x] Store
- [ ] Proof of Personhood
- [x] Deployment scripts
- [ ] Tests

## Related Issues

## Fixes

## Checklist

### Code

- [x] Follows project style
- [x] `forge build` passes
- [x] `forge test` passes
- [x] No new compiler warnings

### Testing

- [ ] New tests added for changed behavior
- [ ] Fuzz tests added where applicable
- [ ] Invariant tests verified

### Security

- [x] No new `selfdestruct` or `delegatecall`
- [x] Access control reviewed
- [x] No storage layout conflicts (for upgradeable contracts)

### Documentation

- [x] NatSpec updated on changed interfaces
- [x] README updated if needed

### Breaking Changes

- [x] No breaking changes
- [ ] Breaking changes documented below

**Breaking changes:**

## How to test

```bash
forge test --mt <testName>
```

## Notes
The `*Old.sol` snapshots on this branch described implementations that were
replaced in place months ago. All four built to different bytecode from what
Paseo Asset Hub Next is running, and nothing noticed: the OpenZeppelin layout
diff compares the new implementation against whatever the snapshot happens to
be, so a stale reference produces an honest diff of the wrong pair, and a
change that lives in calldata leaves no trace in a layout at all.

Regenerate all of them from the build that is actually deployed (c852004),
and prove it. `scripts/shell/verify-snapshots.sh` builds each snapshot and
compares runtime bytecode against the implementation behind the proxy, masking
only `UUPSUpgradeable.__self` and the trailing CBOR metadata. All twelve
upgraded proxies match byte for byte. `fork-tests.sh` runs it before the suite,
so the check cannot be skipped by anyone running the tests the normal way.

The snapshot set is larger than the twelve contracts because master has moved
26 contract files since the deployed build. A snapshot that imports the current
tree stops reproducing the deployed bytecode, and one that imports a snapshot
hands a renamed type to a signature expecting the current one. The set is
therefore closed over both: everything reachable that changed, plus everything
that reaches one of those. Sixteen unchanged interfaces and libraries stay
shared, unrenamed.

CI now runs on pull requests into `spha/**`. It previously triggered on master
alone, so a PR into this branch got lint and nothing else, which is how the
stale snapshots reached review in the first place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…the gap it caught

The storage-layout diff only ran inside an upgrade script, which meant it only
ran when someone brought up the ETH-RPC adapter and ran the fork suite. Lift it
into a plain unit test, one case per proxy, so every push answers the question
the upgrade actually turns on: would `upgradeProxy` accept this layout change.

It found one on its first run. `DotnsProtocolRegistry` appends
`_expectedCodehash` and `_protocolVersion` for the declarations added in #304,
but left `__gap` at 50, so the gap starts two slots later than on the deployed
proxy and the contract's footprint grows. The validator rejects it, and any
field appended after the gap in a later release would land on a slot the live
proxy does not expect. Sized to 48, which keeps the 54-slot footprint. This is
a fifth storage-layout correction of the same family as the four already on
this branch, and like those it stays here per the branch policy.

The fix moves no bytecode: a gap reserves slots and emits no code, so the
implementation still builds byte-identical to the v0.8.0 tag. The release-drift
finding is unchanged, and `DotnsRegistrarController` remains the only proxy
whose deployed code will differ from the tag.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ation

Thirteen scripts and thirteen fork tests, paired one to one. Twelve swap a
proxy in place; the thirteenth migrates the store factory, which cannot be
swapped because what is deployed is a plain contract from an earlier release
and the current one puts the factory behind a proxy at a different address.

Each fork test reads live state through the deployed implementation, runs the
script's own internal path rather than reimplementing the upgrade, and reads
the same state back. Each asserts the implementation address actually changed,
without which a swap that silently did nothing would satisfy every
state-preservation assertion. The assertions are per contract: the registry
drives the new deferral gate against the live controller set, which a unit test
cannot reach; the registrar controller reads back the protocol registry pointer
that the retained slot exists to keep in place; the escrow asserts its redeem
window is both unchanged and non-zero, that being the field an upgrade has
dropped before.

`StoreFactoryMigrator` closes the migration without a release. It is the
shipped factory with four fields widened and a one-shot owner-only import,
swapped into the proxy for a single transaction and swapped back out, so the
deployment ends on the shipped implementation with the bindings in place. Both
directions are layout-diffed.

The holder list it needs cannot be read from the factory: the mapping has no
enumeration, and the list it does keep holds store addresses, which do not know
which user they belong to. Only `LabelStoreDeployed` carries the pairing, so
`scripts/shell/store-holders.sh` replays it and reconciles the result against
the factory's own count. It refuses to print a list it cannot account for,
which matters because the public gateway answers log queries with an empty
result rather than an error: a naive replay against it looks like it worked and
is empty. The count also moves, from 57 to 58 while this was being written, so
the list is read immediately before broadcasting and never reused.

`DeclareRelease` extends `WireDeployments` rather than restating its key list,
so a release that adds a key cannot be declared on a fresh deploy and silently
skipped on every upgrade.

Docs carry the parts that are not obvious from the code. CONTRIBUTING now says
the artefacts stay on a branch that never merges, and that a snapshot is of the
deployed code rather than of the previous release. DEPLOYMENTS and a folder
README record why this network's chain id does not identify it, why its
gateway's empty log results are a trap, and why `verify --tag` will report one
key as drift permanently. The README no longer claims a lite name's node cannot
collide with a subname, which stopped being true when lite names became
subnames.

The note stayed out of the manifest deliberately: the deploy pipeline parses
every key there as an address, so a text field fails it on first read.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Four things an AI review caught, the first of which was mine and the worst.

The migration was built on a false premise. I claimed the deployed factory had
no enumeration and that stores did not know their user, and wrote a log-replay
helper, a count-reconciliation guard and two fork tests around that. Both
claims are false: `getLabelStores(0, n)` answers on the live factory, and
`IDotnsStore.owner()` on a live store round-trips back through
`getLabelStore`. `importStores` now takes only the old factory and reads the
count, the list and each store's owner on chain, checking every pairing back
through the mapping before it writes. `store-holders.sh` is deleted.

That also closes a race the old shape carried. The set was read off chain and
passed in, so a store created between the read and the import was silently left
unbound, and its holder would be handed an empty store on their next
registration. The count on this network moved while this branch was being
written. Reading inside the transaction removes the window, and a test covers
a binding created after the decision to migrate.

The script could not have been broadcast. It read the destination from the
manifest key `StoreFactory`, which still names the factory being migrated from,
and nothing deployed the replacement: the CREATE3 address for it is empty on
chain. Meanwhile the fork test quietly deployed the proxy itself, so the two
told different stories and the test passed. `MigrateStoreFactory` now deploys
the replacement through the pipeline's own helper, which also adopts one a
previous run left behind, and records it and its beacons in the manifest.

The success condition was never asserted. After a real migration every mint
resolves `STORE_FACTORY` through the protocol registry and calls
`ensureLabelStore`; nothing exercised that path. The fork test now upgrades the
protocol registry first, because the rewire declares a codehash that entrypoint
does not have yet, runs all four legs, and asserts a live holder resolves to
the store they already had with no extra store deployed.

Two smaller ones. `verify-snapshots.sh` ran only from `fork-tests.sh`, and CI
calls `forge test` directly, so the check this branch leans on was absent from
the one place reviewers see; it now runs in the fork job. `UserStore` added
`_protocolRegistry` without shrinking its gap, the same defect already fixed on
the protocol registry; it is harmless at zero user stores and would not stay
harmless through a beacon rotation.

`docs/PASEO-V080-RUNBOOK.md` writes down the broadcast order. Nothing in the
scripts enforces it and they are independently runnable by design, so the three
dependencies that fix the order live there: registry first because every
`version()` reads through it, the migration before the declaration because it
rewires a key the declaration records, and the declaration last because it
claims something about the whole deployment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d factory

Three findings from the second review, all correct.

The fork test could not have run the deploy leg it claims to exercise.
`_deployReplacement` reaches `_create3Factory()`, which falls back to reading
`DotnsProtocolRegistry` out of the manifest, and the manifest is only populated
by `initDeployment`, which `run` calls and the harness does not. The test would
have failed at CREATE3 resolution before reaching its assertion, and the unit
tests cannot see that. `_deployReplacement` now adopts the CREATE3 factory from
the protocol registry it was already handed, so the leg depends on no ambient
state and production and the test run the same path.

The script erased the only durable pointer to the factory it migrates away
from. The deploy reuses the `StoreFactory` label and the replacement mints its
own beacons, so after a successful run all three manifest entries described the
new deployment, while the imported stores stayed on the old beacons. Those
beacons answer to the old factory, and it is the only contract that can ever
rotate the implementation behind those stores. The outgoing addresses are now
written first, as `StoreFactoryLegacy`, `LabelStoreBeaconLegacy` and
`UserStoreBeaconLegacy`, and the runbook says which one a later rotation goes
through.

The resume claim was too strong. Adoption covers a run that died between the
deploy and the import, and nothing else: once the import has landed a second
run reverts on the first user it tries to bind, and if the proxy is still on
the migrator the adopt is refused, because the deployer requires the occupant
to delegate to the implementation that run deployed. The NatSpec said the step
was resumable; it now says what is actually true, and the runbook marks step 13
as the one step to inspect and continue rather than re-run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Description

Brings Paseo Asset Hub Next to the current release in place: 12 proxies
swapped, store factory migrated, release declared last. Only two shipped
contracts change (`DotnsProtocolRegistry`, new `StoreFactoryMigrator`);
the rest is upgrade tooling, snapshots and tests.

Two things were broken and passing every check:

- **All four `Old.sol` snapshots were stale**, describing
implementations replaced in place months ago, so every layout diff
compared the wrong pair. Nothing can catch that: the diff compares
whatever it is handed, and a calldata-only change leaves no trace in a
layout. Regenerated from `c8520046` (the build actually deployed) and
proved by `scripts/shell/verify-snapshots.sh`, which compares each
snapshot's bytecode against the implementation behind the proxy. All 12
match; `fork-tests.sh` runs it before the suite.
- **`DotnsProtocolRegistry` could not be upgraded onto the live proxy.**
#304 appended two fields but left `__gap` at 50, so the gap starts two
slots late and the validator rejects it. Now 48. Found by the new layout
suite, which moves the diff into a plain unit test so it runs on every
push. No bytecode change.

The store factory cannot be swapped: what is deployed is a plain
contract, and the release puts the factory behind a proxy elsewhere. Its
bindings are proxy storage with no export, so re-pointing
`STORE_FACTORY` at a fresh factory gives every existing holder a second
empty store and drops their labels from enumeration.
`StoreFactoryMigrator` avoids that without a release: the shipped
factory with four fields widened plus a one-shot owner-only import,
swapped in for one transaction and back out, both directions
layout-diffed.

## Type

- [ ] Bug fix
- [ ] Feature
- [ ] Breaking change
- [ ] Documentation
- [x] Chore
- [ ] Refactor
- [ ] Security

## Scope

- [ ] Registration
- [ ] Resolver
- [ ] Store
- [ ] Proof of Personhood
- [x] Deployment scripts
- [ ] Tests

## Related Issues

Follows #308 (master merged into this branch). Supersedes #306.

## Fixes

Fixes deployment upgrade to v0.8.0 on Paseo

## Checklist

### Code

- [ ] Follows project style
- [ ] `forge build` passes
- [ ] `forge test` passes
- [ ] No new compiler warnings

### Testing

- [ ] New tests added for changed behavior
- [ ] Fuzz tests added where applicable
- [ ] Invariant tests verified

### Security

- [ ] No new `selfdestruct` or `delegatecall`
- [ ] Access control reviewed
- [ ] No storage layout conflicts (for upgradeable contracts)

### Documentation

- [ ] NatSpec updated on changed interfaces
- [ ] README updated if needed

### Breaking Changes

- [ ] No breaking changes
- [ ] Breaking changes documented below

**Breaking changes:**

## How to test

```bash
forge test --match-path 'test/unit/upgrade/LayoutCompatibility.t.sol'
forge test --match-path 'test/unit/store/StoreFactoryMigrator.t.sol'
```

## Notes

**Permanent drift on `DotnsRegistrarController`.** Its retained slot
changes emitted slot constants, so the deployed code will differ from
the v0.8.0 tag forever. A tag build reads `protocolRegistry` as zero and
bricks the contract, so the branch build is the only deployable one.
`verify --tag` reports that one key as drift by design; a second one is
a real finding. Recorded in DEPLOYMENTS.md and
`deployments/paseo-assethub/README.md`.
  
**Holder list for the migration** cannot be read from the factory: no
enumeration, and the list it keeps holds stores, which do not know their
user. `scripts/shell/store-holders.sh` replays `LabelStoreDeployed` and
reconciles against the factory's count, refusing a list it cannot
account for. The public gateway returns empty for `eth_getLogs` instead
of erroring, so a naive replay looks like it worked. The count moved 57
to 58 mid-work, so read it immediately before broadcasting.
  
**Manifest deliberately untouched.** `initDeployment` parses every key
as an address, so a note field breaks the pipeline; it went in a sibling
README.
Prepares the rename of `spha/registrar-upgrade`. GitHub retargets open pull
requests and leaves a redirect, but it does not touch file contents, so these
four references would have gone stale silently.

The CI trigger is the one that matters. It matched `spha/**`, and a renamed
branch stops matching, which puts pull requests into it back to running lint
and nothing else. That is the gap that let a storage snapshot describing a
replaced implementation reach review in the first place. Now matched as
`dev/**`, by prefix rather than by name, so the next long-lived branch is
covered the day it is created instead of the day someone remembers this file.

The other three are prose: CONTRIBUTING on why the artefacts stay on a branch
that never merges, and DEPLOYMENTS and the manifest folder README on why this
network's deployed code matches no release tag.

Land this before the rename, not after. Nothing here touches `contracts/**`,
`test/**` or `**.sol`, so the test workflow's path filter skips this commit
under either branch name and no window opens either way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
)

Follows the rename of `spha/registrar-upgrade` to
`dev/testnet-upgrades`.

GitHub retargets open pull requests and leaves a redirect, but it does
not touch file contents, so four references would have gone stale
silently.

The CI trigger is the one that matters. It matched `spha/**`, and the
renamed branch stops matching, which puts pull requests into it back to
running lint and nothing else. That is the gap that let a storage
snapshot describing a replaced implementation reach review in the first
place. Now matched as `dev/**`, by prefix rather than by name, so the
next long-lived branch is covered the day it is created.

The other three are prose: CONTRIBUTING on why the artefacts stay on a
branch that never merges, and DEPLOYMENTS plus the manifest folder
README on why this networks deployed code matches no release tag.

Nothing here touches `contracts/**`, `test/**` or `**.sol`, so the test
workflow path filter skips this commit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
…uite

`DeclareRelease` would have aborted on Paseo Asset Hub Next, at step 14, after
every swap and the store migration had already been broadcast. The registry's
self-reference key resolves to the zero address there, and `_verifyDeployment`
asserts it matches the manifest. Sixteen of the seventeen keys are wired and
agree; that one is a hole a fresh deploy never has, left by a network wired
before the key existed.

`_wireMissingKeys` sets keys that are unset and leaves every other key exactly
as it is. A key pointing somewhere unexpected still fails verification, because
that is drift, and repairing it here would make the check that follows
tautological and hide the thing it exists to surface.

The fork suite has now been run, for the first time. All 15 tests pass against
live state, including the three for the store migration, which could not have
run at all before the CREATE3 resolution fix in the previous commit: they would
have died resolving the factory out of a manifest the harness never loaded.

They went unrun because they needed Docker. The adapter only translates for the
same node the hosted endpoint already fronts, so `PASEO_FORK_RPC` now overrides
the fork endpoint and the whole suite runs in under a minute with no container.
The default stays on the local alias, so CI and anyone mid-deployment are not
silently pointed at a public gateway. `fork-tests.sh` and the runbook carry the
invocation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

CI Summary

Check Result
4naly3er Analysis Failed
Slither Analysis Failed
Contract Tests (Unit + Fuzz) Failed
Contract Tests (Invariant) Failed
Coverage Failed
Documentation Passed - 90 pages generated - View Docs
Format & Lint Passed - Code formatted correctly
File Validation Passed - All tracked files valid
Deploy Contracts Reproduces the expected address set; resume verified
PR Title PR Title Valid
Labels Unknown
Gas Report Failed - missing shard: pr master
Upgrade Fork Tests Failed
Secret Scan Passed - No secrets detected

Deploy Contracts

Deployed addresses vs the expected set

Expected is the committed expected-address set; actual is this CI deployment of the same pipeline.

Contract Expected Actual Match
Create3Factory 0x8533c79E058c5a6489CAFeCA86dc600E029D75f5 0x8533c79E058c5a6489CAFeCA86dc600E029D75f5 match
DotnsContentResolver 0x7F74D7CD50f5a834270E2ad395a01b01891AB37d 0x7F74D7CD50f5a834270E2ad395a01b01891AB37d match
DotnsCostModelRegistry 0x8bfd1f0957e73716732e725802f13830B5682da4 0x8bfd1f0957e73716732e725802f13830B5682da4 match
DotnsFlatPricing 0xD839B281dF72Df44fF275305E72cAEEc0fDAA648 0xD839B281dF72Df44fF275305E72cAEEc0fDAA648 match
DotnsNameEscrow 0x4881Afb78e7C908cAe818168B926229D93376520 0x4881Afb78e7C908cAe818168B926229D93376520 match
DotnsNameWhitelist 0x420166cD67Ca0233094E492a4BbA67045eD7C38C 0x420166cD67Ca0233094E492a4BbA67045eD7C38C match
DotnsPopController 0xCC932348606cc1f3318cADeC5A5Cd2CA447f8a4b 0xCC932348606cc1f3318cADeC5A5Cd2CA447f8a4b match
DotnsPopLens 0xfe5A45f7fD58D1A6FE09455DB799405b1dcE9411 0xfe5A45f7fD58D1A6FE09455DB799405b1dcE9411 match
DotnsPopResolver 0xDaC984884EcA8Fc44011f1D6C49B27828390A72B 0xDaC984884EcA8Fc44011f1D6C49B27828390A72B match
DotnsProtocolRegistry 0xD19e3D0C97CF501125a04A97405e3e6592fa846E 0xD19e3D0C97CF501125a04A97405e3e6592fa846E match
DotnsRegistrar 0x4f06E818Ba3d987704fd91cf3d868E4b019106Ab 0x4f06E818Ba3d987704fd91cf3d868E4b019106Ab match
DotnsRegistrarController 0xBdaA01bD1bA67d709F2b1fF286Da0d854977EA30 0xBdaA01bD1bA67d709F2b1fF286Da0d854977EA30 match
DotnsRegistry 0xf34054fd76BbF85f216cf9908226D5f0A72E50CA 0xf34054fd76BbF85f216cf9908226D5f0A72E50CA match
DotnsResolver 0xbd1165E549DF96F083c0A16f61590927bC187009 0xbd1165E549DF96F083c0A16f61590927bC187009 match
DotnsReverseResolver 0xee3883d7eB60Ee9BCD7F3bcD8f2f05302A9Cc035 0xee3883d7eB60Ee9BCD7F3bcD8f2f05302A9Cc035 match
LabelStoreBeacon 0x2227d9807F5A71332Aaa0640643030f2A3bf84cD 0x2227d9807F5A71332Aaa0640643030f2A3bf84cD match
Multicall3 0xB4468000abD87D3c56cbFBd153161223D7b109e5 0xB4468000abD87D3c56cbFBd153161223D7b109e5 match
PopRules 0x747B456bE03aec0b42bd85C51513730FBD45DA31 0x747B456bE03aec0b42bd85C51513730FBD45DA31 match
StoreFactory 0x99605a926FcB40aB520F659c6505E5ff862771f6 0x99605a926FcB40aB520F659c6505E5ff862771f6 match
UserStoreBeacon 0x3d1Ca165f7A5e387C2df02DB2FadD3149c1C72ad 0x3d1Ca165f7A5e387C2df02DB2FadD3149c1C72ad match

View full logs

Labels

dependencies, smartcontracts, other, scope: registration, scope: resolver, type: test, type: docs, scope: store, scope: pop

@github-actions github-actions Bot removed the run:UpgradeNameWhitelist Broadcast UpgradeNameWhitelist on Paseo (gated) label Sep 21, 2026
@re-gius re-gius added the run:UpgradeResolver Broadcast UpgradeResolver on Paseo (gated) label Sep 21, 2026
@re-gius
re-gius deployed to testnet-upgrades September 21, 2026 18:15 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown
Contributor

UpgradeResolver: success. Run. Broadcast record and manifest attached as artifacts. Re-add run:UpgradeResolver to retry; for MigrateStoreFactory, read the runbook before retrying anything.

@github-actions github-actions Bot removed the run:UpgradeResolver Broadcast UpgradeResolver on Paseo (gated) label Sep 21, 2026
@re-gius re-gius added the run:UpgradeReverseResolver Broadcast UpgradeReverseResolver on Paseo (gated) label Sep 21, 2026
@re-gius
re-gius deployed to testnet-upgrades September 21, 2026 18:19 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown
Contributor

UpgradeReverseResolver: success. Run. Broadcast record and manifest attached as artifacts. Re-add run:UpgradeReverseResolver to retry; for MigrateStoreFactory, read the runbook before retrying anything.

@github-actions github-actions Bot removed the run:UpgradeReverseResolver Broadcast UpgradeReverseResolver on Paseo (gated) label Sep 21, 2026
@re-gius re-gius added the run:UpgradeContentResolver Broadcast UpgradeContentResolver on Paseo (gated) label Sep 21, 2026
@re-gius
re-gius deployed to testnet-upgrades September 21, 2026 18:24 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown
Contributor

UpgradeContentResolver: success. Run. Broadcast record and manifest attached as artifacts. Re-add run:UpgradeContentResolver to retry; for MigrateStoreFactory, read the runbook before retrying anything.

@github-actions github-actions Bot removed the run:UpgradeContentResolver Broadcast UpgradeContentResolver on Paseo (gated) label Sep 21, 2026
@re-gius re-gius added the run:UpgradePopResolver Broadcast UpgradePopResolver on Paseo (gated) label Sep 21, 2026
@re-gius
re-gius deployed to testnet-upgrades September 21, 2026 18:27 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown
Contributor

UpgradePopResolver: success. Run. Broadcast record and manifest attached as artifacts. Re-add run:UpgradePopResolver to retry; for MigrateStoreFactory, read the runbook before retrying anything.

@github-actions github-actions Bot removed the run:UpgradePopResolver Broadcast UpgradePopResolver on Paseo (gated) label Sep 21, 2026
@re-gius re-gius added the run:MigrateStoreFactory Broadcast MigrateStoreFactory on Paseo (gated) label Sep 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

MigrateStoreFactory: failure. Run. Broadcast record and manifest attached as artifacts. Re-add run:MigrateStoreFactory to retry; for MigrateStoreFactory, read the runbook before retrying anything.

@github-actions github-actions Bot removed the run:MigrateStoreFactory Broadcast MigrateStoreFactory on Paseo (gated) label Sep 22, 2026
The first MigrateStoreFactory broadcast proved a single transaction
importing all 63 live bindings does not fit in a block: estimation died
mid-loop around the 44th store at any gas limit, the multi-dimensional
weight exhaustion surfacing as OpenZeppelin's FailedCall. Nothing
off-chain models that ceiling, so the import is now paged.

- importStores(oldFactory, offset, limit): idempotent per binding, a
  conflicting rebind still reverts, the final page asserts the count
- the script broadcasts pages of DOTNS_IMPORT_CHUNK (default 15,
  roughly a third of the measured capacity)
- runbook step 13 maps each death state to label retry or manual
  page replay; a fork test drills the mid-import recovery against live

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@re-gius re-gius added the run:MigrateStoreFactory Broadcast MigrateStoreFactory on Paseo (gated) label Sep 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

MigrateStoreFactory: success. Run. Broadcast record and manifest attached as artifacts. Re-add run:MigrateStoreFactory to retry; for MigrateStoreFactory, read the runbook before retrying anything.

@github-actions

Copy link
Copy Markdown
Contributor

DeclareRelease: success. Run. Broadcast record and manifest attached as artifacts. Re-add run:DeclareRelease to retry; for MigrateStoreFactory, read the runbook before retrying anything.

@re-gius

re-gius commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator Author

All 15 runbook steps executed and chain-verified: ownership rotated to a fresh key, 12 proxies swapped to v0.8.0, the store factory migrated with all 63 bindings carried, and the release declared. protocolVersion() reads 0.8.0 and the release verify reports paseo-assethub matches the chain. The broadcast workflow is disabled; this PR served as the gated broadcast console and closes unmerged by design, per CONTRIBUTING. The permanent record lives on dev/testnet-upgrades at tag upgrades/paseo-nv2-v0.8.0.

@re-gius re-gius mentioned this pull request Sep 22, 2026
12 of 27 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants