Skip to content

Q migration, v2 testnet deployment, integration test suite, repo restructure#16

Merged
moscowchill merged 16 commits into
mainfrom
dev
Apr 14, 2026
Merged

Q migration, v2 testnet deployment, integration test suite, repo restructure#16
moscowchill merged 16 commits into
mainfrom
dev

Conversation

@moscowchill
Copy link
Copy Markdown
Contributor

Summary

Consolidates everything from the v2 testnet migration cycle into main. Three already-squash-merged sub-PRs (#13/#14/#15) plus 12 follow-up commits on dev.

What landed

Z→Q migration (merged sub-PRs, now bundled for main)

Live deployment on QRL v2 testnet (chainId 1337)

Contract Address
stQRLv2 Q09046968aF19E745F4aBa7A9fa5CD946b4E981DB
DepositPoolV2 Q38F73cb87c60d365fdFA7abF0e534fc1a9D5F9B9
ValidatorManager Q1b083D7Dc47212DcBc4595249D9384Fa16cE6FC5

All 3 wired with the one-shot setStQRL / setDepositPool guards. Deployer Q2E13b52fd3cda0a57f9037856B7Df971074e2489 is sole owner.

Toolchain + infra fixes

  • Discovered testnet chainId was 1337, not 32382 — corrected in 6 config files
  • Fixed provider URL /api/zond-rpc/testnet/api/qrl-rpc/testnet
  • Archived 6 v1 deployer scripts to scripts/v1-deprecated/ (all targeted dead ABI)
  • scripts/sync-hyperion.js teaches Solidity→Hyperion dialect translation (pragma, unit suffixes ether/wei/gweiquanta/planck/shor, address literals 0x<40hex>Q<40hex>)
  • scripts/deploy-hyperion.js fixed for @theqrl/web3 v0.4 API changes (fromWeifromPlanck, reuse of .deploy().send() contract instances to keep wallet binding)
  • scripts/lib/loadDeployer.js now registers the hex seed on web3.qrl.wallet so load-by-address contract calls sign locally

Integration test suite (scripts/integration-test-v2.js)

16 phases, all verified end-to-end against the live deployment:

Phase Coverage
status Read-only dump of protocol + user state
smoke Deposit → mint shares
rewards Donate QRL → syncRewards → rate bumps
withdraw Request withdrawal, shares locked, 128-block delay
validator 40k QRL → register → fundValidatorMVP → activate
errors 6 revert paths (below-min, zero, over-balance, one-shots, bad pubkey)
pause pause() blocks deposit, unpause() restores
lifecycle VM state machine Active→Exiting→Exited + idempotency guard
claim-prep fundWithdrawalReserve reclassifies pooled → reserve
claim claimWithdrawal after 128-block wait (verified: 50 shares → 50.5 QRL)
wait-claim Poller: waits for delay, auto-claims
cancel Cancel pending withdrawal, shares unlock
transfer-locked Lock guard on stQRL.transfer
batch Register 3 validators, batchActivateValidators, dup pubkey reverts
approve QRC-20 allowance incl. infinite-allowance non-decrement
all Runs every phase

Repo restructure

Everything code-related now under contracts/:

contracts/
├── solidity/*.sol
├── hyperion/*.hyp           (generated from solidity/)
└── test/
    ├── *.sol                (Foundry suite, 178 tests)
    └── hyperion/*.t.hyp     (generated mirrors)
build/hyperion/              (hypc artifacts — gitignored)

Validation

  • forge build clean
  • forge test 178/178 passing (stQRLv2 55, DepositPoolV2 68, ValidatorManager 55)
  • node scripts/compile-hyperion.js clean (3 contracts + 2 interfaces)
  • Live integration suite: all 16 phases green on chainId 1337
  • Deployer / contract state consistent, protocol invariants hold

Still open (intentionally deferred)

  • DEPOSIT_CONTRACT = Q4242… address verification — QRL team's staking guide in QA (per Discord). Until verified, pool.fundValidator() (real beacon path) stays off; MVP path is safe and exercised
  • Real validator deployment — needs cloud hardware running gqrl + qrysm
  • Monitoring contract-exporter rewrite — still on v1 ABI, returns zeros
  • Slashing path — not forceable on testnet (unit-test coverage only)

Test plan

  • Gemini bot review of all 12 direct-to-dev commits (feat: migrate scripts/contracts/monitoring to Q-prefix v2 testnet #13–15 already reviewed pre-merge)
  • Sanity read docs/V2-DEPLOYMENT-STATUS.md for live state + handoff notes
  • Sanity read contracts/hyperion/README.md for the Hyperion workflow
  • Confirm .env + live testnet node scripts/integration-test-v2.js status round-trip on the reviewer's machine (optional)

moscowchill and others added 15 commits April 13, 2026 14:35
* feat: migrate Z-prefix scripts/contracts/monitoring to Q-prefix v2 testnet

Bump @theqrl/web3 to ^0.4.0 and @theqrl/wallet.js to ^3.0.1 (matching
the ported myqrlwallet-frontend), then sweep all dependent code:

- scripts/ (10 files): web3.zond.* -> web3.qrl.*, replace
  MnemonicToSeedBin with MLDSA87.newWalletFromMnemonic, swap Z-prefix
  literals (zero address sentinel + EVM beacon deposit address) to
  Q-prefix.
- monitoring/contract-exporter (3 src files + .env.example +
  docker-compose.yml + package.json): same namespace sweep, rename
  ZOND_RPC_URL to QRL_RPC_URL, swap fallback Z-prefix addresses,
  point default RPC URL at /api/qrl-rpc/testnet.
- contracts/solidity/v2 (3 files): NatSpec only (Zond -> QRL); EVM
  bytecode unchanged. v1-deprecated/ left as-is.
- config/testnet.json: clear stale v1 contract addresses (v2 not yet
  deployed); update provider to /api/qrl-rpc/testnet.
- package.json metadata: drop "zond" keyword, update description.

Validation: forge build + 178/178 forge tests pass. node -c on every
touched script. Live RPC smoke-test against http://46.224.165.196:8545
verified web3.qrl.getChainId returns 1337n earlier in the session.

Out of scope (follow-up PRs):
- Infrastructure (Ansible roles, Terraform vars, shell scripts, Grafana
  dashboards, Prometheus alerts) - blocked on QRL team confirmation of
  the gzond -> gqrl binary rename.
- Documentation sweep (README + infrastructure/docs/**).

Note: TESTNET_SEED in deployer .env may need regeneration since
wallet.js v3 now uses 34-word mnemonics (was 32 in v0.x).

* refactor(scripts): extract loadDeployer helper, validate mnemonic length

Address gemini-code-assist review on PR #13: the wallet.js v3 mnemonic-
length check was missing across all 9 deployer scripts. Rather than
inlining the same guard nine times, extract the entire seed-derivation
block (validate -> MLDSA87.newWalletFromMnemonic -> getHexExtendedSeed
-> seedToAccount -> wallet.add) into scripts/lib/loadDeployer.js.

Each call site collapses from a 4-line block to one call:

  const account = loadDeployer(web3, mnemonic);

Helper throws a clear error if the mnemonic is missing or not 34 words,
covering the bot's flagged scenario where an old 32-word v1/v2 seed is
still in .env after the wallet.js v3 upgrade.

Scope:
- New: scripts/lib/loadDeployer.js
- Refactored: configure.js, deploy.js, deploy-test-token.js,
  test-deposit.js, fund-validator.js, submit-deposit.js,
  upgrade-deposit-pool.js, deploy-hyperion.js, integration-test.js
- integration-test.js's separate random-seed code path (crypto.randomBytes
  for ephemeral test wallets) is intentionally left untouched.

Net change: +19 / -47.
…monitoring (#14)

Part 2 of the Z→Q testnet migration. Renames the execution-client binary
(gzond → gqrl), its Ansible role directory, all gzond_* variables, the
systemd service template, cross-role references (qrysm-beacon, security,
monitoring), Terraform variables (zond_rpc_url → qrl_rpc_url, ZOND_RPC_URL →
QRL_RPC_URL), Prometheus scrape job + alert names (Gzond* → Gqrl*),
Grafana dashboard queries, and infrastructure README/ARCHITECTURE comments.

Runbooks and standalone documentation are intentionally out of scope and
will be covered in PR 3.
* docs: complete Z→Q migration sweep across README and runbooks

Third and final PR of the Z→Q testnet migration. Rewrites all
user-facing documentation to use QRL branding: README, architecture
docs, deployment guide, validator-integration guide, and all runbooks
(emergency, failover, monitoring, add-validator, update-clients).

Updates binary names (gzond→gqrl), the go-qrl source repo, JSON-RPC
namespace references (zond_call→qrl_call), Z-prefixed example
addresses (Z...→Q...), the prod RPC URL path (/api/qrl-rpc/testnet),
and prose references to "Zond testnet"→"QRL v2 testnet".

The canonical QRL install-guide URL (test-zond.theqrl.org) is
preserved unchanged since it's still the upstream project's own URL.

* docs: dedupe redundant QRL/QRL heading per review
- Build task: drop bogus `creates:` (prevented rebuilds after first
  deploy) and gate on either source change or missing binary, so a
  rebuild fires when expected.
- Sync-status display: map raw eth_syncing result to "Synced"/"Syncing"
  instead of the confusing literal `False`.
- Service template: replace hardcoded `--verbosity 3` with new
  `gqrl_verbosity` default so it can be overridden per environment.
- Move six scripts that target the v1 contract ABI into
  scripts/v1-deprecated/. They will fail against the v2 contracts
  (totalAssets/convertToShares/getQueueStatus/liquidReserve/setRewardsOracle
  do not exist in v2). README in the new dir explains the v2 path.
- Flip config/testnet-hyperion.json provider from the pre-rebrand
  /api/zond-rpc/testnet to /api/qrl-rpc/testnet to match the rest
  of the workspace and the actual current proxy route.
… dialect

Pre-flight against the v2 testnet (qrlwallet.com/api/qrl-rpc/testnet
and the synced node at 46.224.165.196:8545) returned chainId 0x539
(1337), not the 32382 the configs claimed. 32382 was the pre-rebrand
Zond testnet ID. Updates configs, Ansible defaults, inventory, and
key-management/generate-keys.sh.

scripts/sync-hyperion.js now translates three Solidity-vs-Hyperion
dialect differences when generating .hyp mirrors, so hypc compiles
the contracts cleanly:

  - pragma solidity X     -> pragma hyperion >=0.0
    (Hyperion is on its own 0.2.x track)
  - N ether / wei / gwei  -> N quanta / planck / shor
    (Hyperion's QRL-native unit names)
  - 0x<40hex>             -> Q<40hex>
    (Hyperion address-literal syntax)

Regenerated hyperion/contracts and hyperion/test mirrors with the new
rules. hypc-produced ABIs and bin live in hyperion/artifacts/ (still
gitignored).
…act instances

Two fixes that together let scripts/deploy-hyperion.js complete an
end-to-end deploy + wire on the QRL v2 testnet (chainId 1337,
qrlwallet.com/api/qrl-rpc/testnet):

1. web3.utils.fromWei does not exist on @theqrl/web3 v0.4 — replaced
   with web3.utils.fromPlanck(balance, 'quanta'), the QRL-native unit
   pair that maps 1:1 onto wei/ether semantics.

2. The wiring step constructed fresh `new web3.qrl.Contract(abi, addr)`
   instances and called `.send({from})` on them, which fails with
   "unknown account" because new Contract objects do not inherit the
   wallet attached to the deploying contract instance. Reuse the
   already-deployed contract instances (depositPool, stQRL,
   validatorManager) directly — they already have the wallet bound.

Persists the live testnet addresses in config/testnet-hyperion.json:
  stQRLv2:          Q09046968aF19E745F4aBa7A9fa5CD946b4E981DB
  DepositPoolV2:    Q38F73cb87c60d365fdFA7abF0e534fc1a9D5F9B9
  ValidatorManager: Q1b083D7Dc47212DcBc4595249D9384Fa16cE6FC5

Smoke test confirms: deployer is owner of all three; stQRL <-> pool
one-shot wiring intact; vm.depositPool set; constants
(minDeposit=100 QRL, VALIDATOR_STAKE=40000 QRL, DEPOSIT_CONTRACT=Q4242…)
match Solidity sources; nothing paused.
…ete)

V2-DEPLOYMENT-STATUS.md captures the live testnet state (addresses,
deployer, what's done, what's blocked, how to resume) so the next
session has full context without spelunking the repo.

scripts/integration-test-v2.js is staged as a phased MVP test
(smoke / rewards / withdraw / validator) but does not yet execute:
load-by-address Contract instances on @theqrl/web3 v0.4 don't
auto-bind to the wallet on the parent web3, so .send() fails with
"unknown account" from the proxy. Workaround (manual sign +
qrl_sendRawTransaction) is documented in the status doc and will
land in the next session.
…ansaction

Contract instances created from (abi, addr) with @theqrl/web3 v0.4 do not
inherit the wallet on the parent web3; calling `.send({from})` on them
forwards as qrl_sendTransaction and the proxy rejects with "unknown
account". Port the pattern proven in myqrlwallet-frontend (qrlStore.ts
sendToken): encode the method, build the tx object, and submit via
web3.qrl.sendTransaction so the locally-registered wallet signs it.

Also register the hex seed on `web3.qrl.wallet` in loadDeployer so
consumers that use the encode-and-send path pick up the signing key
without needing a second init step. Keeps the existing
`accounts.wallet.add(account)` call for the .deploy().send() path.

Validated on live QRL v2 testnet (chainId 1337):
  Phase 1 (smoke):     deposit 100 QRL, shares minted, totals consistent
  Phase 2 (rewards):   donate 1 QRL + syncRewards; rate 1.00 -> 1.01
  Phase 3 (withdraw):  request 50 shares locked, blocksRemaining=128
  Phase 4 (validator): deposit-to-buffer, registerValidator,
                       fundValidatorMVP, activateValidator all assert-clean
…ases

Expands scripts/integration-test-v2.js with four new phases plus a
read-only status dump. All pass against the live v2 testnet:

  status      Read-only: user position, protocol accounting, vm stats,
              pending withdrawal requests. No state change.
  errors      Six revert paths: deposit below min, zero withdrawal,
              over-unlocked withdrawal, one-shot setStQRL/setDepositPool
              guards, wrong-length pubkey on registerValidator.
  pause       pool.pause() blocks deposit with ContractPaused; unpause
              restores.
  lifecycle   Active -> Exiting -> Exited on VM; active count
              decrements; markValidatorExited guard on already-exited.
  claim-prep  fundWithdrawalReserve reclassifies pooled QRL into
              reserve (invariant maintained); claimWithdrawal still
              reverts WithdrawalNotReady until WITHDRAWAL_DELAY blocks
              elapse.

expectRevert treats the proxy's generic "execution reverted" as a
success (the custom error name is stripped by the RPC layer; Foundry
suite already asserts the specific names at unit-test level).
…ed phases

Five more phases expand end-to-end coverage of the protocol:

  claim           Claim the next FIFO withdrawal request if ready
                  (needs WITHDRAWAL_DELAY elapsed + reserve funded).
  wait-claim      Poll getWithdrawalRequest() every 60s until canClaim
                  goes true, then claim. Handy because testnet block
                  time is ~60s and WITHDRAWAL_DELAY=128 blocks (~2h).
  cancel          Create a 1-share withdrawal → cancelWithdrawal → verify
                  shares unlocked, request zeroed+claimed-flagged,
                  totalWithdrawalShares unchanged, re-cancel reverts.
  transfer-locked Assert stQRL.transfer(self, unlocked+1) reverts with
                  InsufficientUnlockedShares while exact-unlocked amount
                  succeeds. Proves the lock guard is tight.

All four pass on live testnet. Remaining intentional gap: real beacon
deposit via pool.fundValidator() (blocked on QRL team confirming
DEPOSIT_CONTRACT=Q4242…) and slashing (no way to force on testnet).
Moves the hyperion tree into the conventional locations rather than a
sibling root dir, so both language flavors are co-located:

  hyperion/contracts/ -> contracts/hyperion/
  hyperion/test/      -> test/hyperion/
  hyperion/artifacts/ -> build/hyperion/   (gitignored)
  hyperion/README.md  -> contracts/hyperion/README.md
  hyperion/                                  (removed; was empty)

Path references updated in:
- scripts/sync-hyperion.js     (source/target dirs + test import rewrite
                                now produces ../../contracts/hyperion/)
- scripts/compile-hyperion.js  (contracts + artifacts paths)
- scripts/deploy-hyperion.js   (manifest path)
- scripts/integration-test-v2.js  (loadAbi path)
- .gitignore                   (hyperion/artifacts/ -> build/)
- README.md, docs/V2-DEPLOYMENT-STATUS.md, CLAUDE.md,
  contracts/hyperion/README.md, scripts/v1-deprecated/README.md

Verified end-to-end on live testnet (chainId 1337):
- `compile-hyperion.js` regenerates build/hyperion/ cleanly
- `integration-test-v2.js status` reads the new path
- `integration-test-v2.js approve` (6 txs, allowance flow) runs green,
  including an asserts-pass on the infinite-allowance non-decrement
  path in transferFrom.

No contract bytecode change (compile is deterministic); no chain
state touched by the refactor itself.
… in contracts/

Final shape:
  contracts/
  ├── solidity/*.sol             canonical sources
  ├── hyperion/*.hyp             generated mirrors
  └── test/
      ├── *.sol                  Foundry tests
      └── hyperion/*.t.hyp       generated test mirrors

Updates:
- foundry.toml: src=contracts/solidity, test=contracts/test
- Test .sol imports: ../contracts/solidity/ -> ../solidity/
- scripts/sync-hyperion.js: test dirs + import rewrite
  (../solidity/Foo.sol -> ../../hyperion/Foo.hyp, since .hyp mirror is
  two levels deep under contracts/test/hyperion/)
- CLAUDE.md, contracts/hyperion/README.md: path refs

Verified: forge build clean, forge test 178/178 pass, hypc compile OK.
…yout + coverage

README:
- Updated Project Structure tree to reflect the contracts/-rooted layout
  (solidity/, hyperion/, test/ all nested under contracts/; build/ for
  hypc output)
- Rewrote the prose that described the old sibling hyperion/ directory

V2-DEPLOYMENT-STATUS:
- Rewritten with the full 16-phase integration-test coverage matrix
- Captured the end-to-end claim validation (50 shares → 50.5 QRL paid
  out exactly; snapshot semantics preserved claimer's entitlement
  through reserve-carve-out rate fluctuations)
- Updated "Files of interest" paths for the new layout
- Moved "blocked" list to reflect reality (integration test long
  unblocked; only DEPOSIT_CONTRACT verify, real-validator hardware,
  and contract-exporter rewrite remain open)

architecture.md:
- Corrected minDeposit (100 QRL, not 1 ether) and ABSOLUTE_MIN note
- Verified block time as ~60s on testnet
- Added an integration-test subsection pointing at the 16-phase
  live-testnet coverage alongside the Foundry 178-test suite
- Expanded Deployment Checklist to describe what deploy-hyperion.js
  actually does, including the wallet-binding rationale for why the
  script uses .deploy().send() return values directly rather than
  freshly-loaded Contract instances
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request rebrands the QuantaPool protocol from 'Zond' to 'QRL', restructuring the project directory and updating address prefixes, chain IDs, and unit denominations. It includes upgrades to @theqrl/web3 and @theqrl/wallet.js, along with new integration tests and deployment scripts. Feedback focuses on updating stale contract addresses in the monitoring configuration and documentation to reflect the v2 deployment, and improving type safety in the integration tests by explicitly casting gas price results to BigInt.

Comment on lines +13 to +16
STQRL_ADDRESS: process.env.STQRL_ADDRESS || 'Q844A6eB87927780E938908743eA24a56A220Efe8',
DEPOSIT_POOL_ADDRESS: process.env.DEPOSIT_POOL_ADDRESS || 'Q9E800e8271df4Ac91334C65641405b04584B57DC',
REWARDS_ORACLE_ADDRESS: process.env.REWARDS_ORACLE_ADDRESS || 'Q541b1f2c501956BCd7a4a6913180b2Fc27BdE17E',
OPERATOR_REGISTRY_ADDRESS: process.env.OPERATOR_REGISTRY_ADDRESS || 'QD370e9505D265381e839f8289f46D02815d0FF95',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The default contract addresses in the exporter configuration are stale. They appear to be the v1 addresses converted to the Q prefix, but they do not match the live v2 deployment addresses mentioned in the PR description and config/testnet-hyperion.json. Since the exporter is being updated to use the web3.qrl provider, these defaults should be aligned with the v2 contracts to ensure the monitoring stack points to the correct on-chain state by default.

Suggested change
STQRL_ADDRESS: process.env.STQRL_ADDRESS || 'Q844A6eB87927780E938908743eA24a56A220Efe8',
DEPOSIT_POOL_ADDRESS: process.env.DEPOSIT_POOL_ADDRESS || 'Q9E800e8271df4Ac91334C65641405b04584B57DC',
REWARDS_ORACLE_ADDRESS: process.env.REWARDS_ORACLE_ADDRESS || 'Q541b1f2c501956BCd7a4a6913180b2Fc27BdE17E',
OPERATOR_REGISTRY_ADDRESS: process.env.OPERATOR_REGISTRY_ADDRESS || 'QD370e9505D265381e839f8289f46D02815d0FF95',
STQRL_ADDRESS: process.env.STQRL_ADDRESS || 'Q09046968aF19E745F4aBa7A9fa5CD946b4E981DB',
DEPOSIT_POOL_ADDRESS: process.env.DEPOSIT_POOL_ADDRESS || 'Q38F73cb87c60d365fdFA7abF0e534fc1a9D5F9B9',
REWARDS_ORACLE_ADDRESS: process.env.REWARDS_ORACLE_ADDRESS || 'Q541b1f2c501956BCd7a4a6913180b2Fc27BdE17E',
OPERATOR_REGISTRY_ADDRESS: process.env.OPERATOR_REGISTRY_ADDRESS || 'Q1b083D7Dc47212DcBc4595249D9384Fa16cE6FC5',

Comment thread monitoring/.env.example Outdated
Comment on lines +26 to +29
STQRL_ADDRESS=Q844A6eB87927780E938908743eA24a56A220Efe8
DEPOSIT_POOL_ADDRESS=Q9E800e8271df4Ac91334C65641405b04584B57DC
REWARDS_ORACLE_ADDRESS=Q541b1f2c501956BCd7a4a6913180b2Fc27BdE17E
OPERATOR_REGISTRY_ADDRESS=QD370e9505D265381e839f8289f46D02815d0FF95
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The example contract addresses should be updated to reflect the v2 deployment addresses. Using the v1 addresses (even with the Q prefix) in the documentation/examples can lead to confusion during setup, especially since the ValidatorManager (at Q1b083...) has replaced the legacy OperatorRegistry logic.

STQRL_ADDRESS=Q09046968aF19E745F4aBa7A9fa5CD946b4E981DB
DEPOSIT_POOL_ADDRESS=Q38F73cb87c60d365fdFA7abF0e534fc1a9D5F9B9
REWARDS_ORACLE_ADDRESS=Q541b1f2c501956BCd7a4a6913180b2Fc27BdE17E
OPERATOR_REGISTRY_ADDRESS=Q1b083D7Dc47212DcBc4595249D9384Fa16cE6FC5

Comment thread scripts/integration-test-v2.js Outdated
data,
value: value.toString()
});
const baseGasPrice = (await web3.qrl.getGasPrice()) || 1_000_000_000n;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The web3.qrl.getGasPrice() method in @theqrl/web3 (based on web3.js v4) typically returns a BigInt. However, depending on the provider configuration or specific RPC responses, it might return a string. To prevent potential TypeError when performing arithmetic operations (like baseGasPrice * 2n on line 87), it is safer to explicitly wrap the result in BigInt().

Suggested change
const baseGasPrice = (await web3.qrl.getGasPrice()) || 1_000_000_000n;
const baseGasPrice = BigInt(await web3.qrl.getGasPrice() || 1_000_000_000);

- monitoring/contract-exporter/src/config.js, monitoring/.env.example:
  Replace stale v1-era fallback addresses (which had been Q-prefixed
  but still pointed at removed contracts) with the live v2 testnet
  addresses. Add VALIDATOR_MANAGER_ADDRESS for completeness. Clear
  REWARDS_ORACLE_ADDRESS and OPERATOR_REGISTRY_ADDRESS — v2 removed
  both (trustless _syncRewards replaces the oracle; ValidatorManager
  subsumes the registry). Exporter code still targets v1 ABI and is
  the tracked follow-up rewrite; this at least stops it from lying
  about which contracts it points to.
- scripts/integration-test-v2.js: Explicitly BigInt() the
  getGasPrice() return before using it in arithmetic, so a string
  response from the RPC can't trip a TypeError in the tx helper.
  Reported twice by Gemini (same helper reached by multiple phases).
@moscowchill moscowchill merged commit bda774e into main Apr 14, 2026
2 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.

1 participant