[#138] Finding 3: Forge dev scripts — chainid guard (anti mainnet mis-RPC) #141

Closed
opened 2026-05-04 08:51:58 +00:00 by PlasticDigits · 5 comments
PlasticDigits commented 2026-05-04 08:51:58 +00:00 (Migrated from gitlab.com)

Parent: Split from #138 — Pre-deploy review pass 2 (Finding 3).

Severity: Medium

Problem

Dev-oriented Foundry scripts run without block.chainid guards:

DeployDev (representative risks):

  • Deploys MockReserveCl8y with public mint — unlimited supply if deployed live.
  • Schedules sale / enables redemption & podium gates / vesting per operator script — catastrophic on mainnet if RPC URL is mis-pointed.

One mistaken --rpc-url + real PRIVATE_KEY can broadcast a full dev stack to production.

References

Kind Path / link
Scripts contracts/script/DeployDev.s.sol and siblings listed above
Ops docs/operations/final-signoff-and-value-movement.md (gates #55)
Invariants docs/testing/invariants-and-business-logic.md
Related GitLab #131 (Doubloon minter burn footgun compounds mis-deploy)
Skill .cursor/skills/yieldomega-guardrails/SKILL.md

At the top of each script’s run():

require(
    block.chainid == 31337 || block.chainid == 6342 || block.chainid == 6343,
    "DeployDev: dev/testnet only"
);

Adjust allowed IDs to match this repo’s documented local + MegaETH testnet/mainnet policy (confirm with docs/contracts/foundry-and-megaeth.md / team). Add a one-line comment referencing intentional allowlist.

Optional: document in docs/testing/e2e-anvil.md or deploy runbooks that production deploys must not use these script names.

Acceptance criteria

  • All four scripts revert immediately on disallowed chain IDs before deploying contracts.
  • Anvil (31337) and approved MegaETH chain IDs from project docs still work.
  • Forge tests or script smoke: assert revert on a mocked wrong chain if feasible.

Verification checklist

  • forge script script/DeployDev.s.sol against Anvil succeeds.
  • Attempt wrong RPC (or fork trick) fails at require with clear message.
  • CI / local forge test still passes for contracts/.
  • README or ops note updated if operators rely on these scripts.
**Parent:** Split from [#138 — Pre-deploy review pass 2](https://gitlab.com/PlasticDigits/yieldomega/-/issues/138) (Finding 3). **Severity:** Medium ## Problem Dev-oriented Foundry scripts run **without `block.chainid` guards**: - [`contracts/script/DeployDev.s.sol`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/script/DeployDev.s.sol) - [`contracts/script/DeployKumbayaAnvilFixtures.s.sol`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/script/DeployKumbayaAnvilFixtures.s.sol) - [`contracts/script/AnvilSameBlockDrill.s.sol`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/script/AnvilSameBlockDrill.s.sol) - [`contracts/script/SimulateAnvilRichState.s.sol`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/script/SimulateAnvilRichState.s.sol) (path may vary — confirm repo) `DeployDev` (representative risks): - Deploys **`MockReserveCl8y`** with public `mint` — unlimited supply if deployed live. - Schedules sale / enables redemption & podium gates / vesting per operator script — catastrophic on mainnet if RPC URL is mis-pointed. One mistaken `--rpc-url` + real `PRIVATE_KEY` can broadcast a **full dev stack to production**. ## References | Kind | Path / link | |------|-------------| | Scripts | [`contracts/script/DeployDev.s.sol`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/script/DeployDev.s.sol) and siblings listed above | | Ops | [`docs/operations/final-signoff-and-value-movement.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/operations/final-signoff-and-value-movement.md) (gates #55) | | Invariants | [`docs/testing/invariants-and-business-logic.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/testing/invariants-and-business-logic.md) | | Related | GitLab [#131](https://gitlab.com/PlasticDigits/yieldomega/-/issues/131) (Doubloon minter burn footgun compounds mis-deploy) | | Skill | [`.cursor/skills/yieldomega-guardrails/SKILL.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/.cursor/skills/yieldomega-guardrails/SKILL.md) | ## Recommended fix At the top of each script’s `run()`: ```solidity require( block.chainid == 31337 || block.chainid == 6342 || block.chainid == 6343, "DeployDev: dev/testnet only" ); ``` Adjust allowed IDs to match **this repo’s** documented local + MegaETH testnet/mainnet policy (confirm with `docs/contracts/foundry-and-megaeth.md` / team). Add a one-line comment referencing intentional allowlist. Optional: document in [`docs/testing/e2e-anvil.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/testing/e2e-anvil.md) or deploy runbooks that production deploys **must not** use these script names. ## Acceptance criteria - [ ] All four scripts revert immediately on disallowed chain IDs before deploying contracts. - [ ] Anvil (`31337`) and approved MegaETH chain IDs from project docs still work. - [ ] Forge tests or script smoke: assert revert on a mocked wrong chain if feasible. ## Verification checklist - [ ] `forge script script/DeployDev.s.sol` against Anvil succeeds. - [ ] Attempt wrong RPC (or fork trick) fails at `require` with clear message. - [ ] CI / local `forge test` still passes for `contracts/`. - [ ] README or ops note updated if operators rely on these scripts.
PlasticDigits commented 2026-05-04 08:53:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #138

mentioned in issue #138
PlasticDigits commented 2026-05-04 13:40:52 +00:00 (Migrated from gitlab.com)

mentioned in commit efeb854610

mentioned in commit efeb854610b58086cc0bbd9b4495a9dac65b521b
PlasticDigits commented 2026-05-04 13:42:38 +00:00 (Migrated from gitlab.com)

Shipped on main (merge ce71d7f)

@brouie please verify when you can — issue stays open per agent runbook.

What changed

  • Added contracts/script/DevOnlyChainGuard.sol: assertDevScriptChain() allows 31337 (Anvil), 6343 (MegaETH testnet), 6342 (legacy); reverts on 4326 (MegaETH mainnet), Ethereum 1, and all other chain IDs with message DevOnlyChainGuard: chain not allowed (31337/6342/6343).
  • Wired at the start of run() for: DeployDev, DeployKumbayaAnvilFixtures, AnvilSameBlockDrill, SimulateAnvilRichStatePart1 / Part2 / Part2EndSaleOnly.
  • Tests: contracts/test/DevOnlyChainGuard.t.sol (FOUNDRY_PROFILE=ci forge test — 302 passed in agent run).

Checklist for verification

  1. cd contracts && FOUNDRY_PROFILE=ci forge test passes (includes DevOnlyChainGuardTest).
  2. Anvil: anvil then forge script script/DeployDev.s.sol --broadcast --rpc-url http://127.0.0.1:8545 --code-size-limit 524288 completes (or your usual stack script).
  3. Wrong chain: forge script script/DeployDev.s.sol -vvv --fork-url https://eth.llamarpc.com (or any RPC with chain id ≠ 31337/6342/6343) should simulate-revert at the guard before any deploy.
  4. Optional: cast chain-id --rpc-url <megaeth-testnet> returns 6343 — fork/broadcast tests against that ID should pass the guard (still exercise caution with real keys).

Parent context: #138 Finding 3.

## Shipped on `main` (merge ce71d7f) @brouie please verify when you can — **issue stays open** per agent runbook. ### What changed - Added [`contracts/script/DevOnlyChainGuard.sol`](contracts/script/DevOnlyChainGuard.sol): `assertDevScriptChain()` allows **31337** (Anvil), **6343** (MegaETH testnet), **6342** (legacy); reverts on **4326** (MegaETH mainnet), Ethereum **1**, and all other chain IDs with message `DevOnlyChainGuard: chain not allowed (31337/6342/6343)`. - Wired at the **start of `run()`** for: `DeployDev`, `DeployKumbayaAnvilFixtures`, `AnvilSameBlockDrill`, `SimulateAnvilRichStatePart1` / `Part2` / `Part2EndSaleOnly`. - Tests: [`contracts/test/DevOnlyChainGuard.t.sol`](contracts/test/DevOnlyChainGuard.t.sol) (`FOUNDRY_PROFILE=ci forge test` — 302 passed in agent run). ### Docs / cross-links - Invariant **`INV-DEVSCRIPT-141`**: [invariants — §141](docs/testing/invariants-and-business-logic.md#forge-dev-scripts-chain-allowlist-gitlab-141) - [docs/contracts/foundry-and-megaeth.md](docs/contracts/foundry-and-megaeth.md#dev-only-forge-script-entrypoints-chain-allowlist-gitlab-141), [docs/testing/e2e-anvil.md](docs/testing/e2e-anvil.md#forge-dev-scripts-chain-allowlist-gitlab-141), [contracts/README.md](contracts/README.md), [skills/README.md](skills/README.md), [.cursor/skills/yieldomega-guardrails/SKILL.md](.cursor/skills/yieldomega-guardrails/SKILL.md) item 47. ### Checklist for verification 1. `cd contracts && FOUNDRY_PROFILE=ci forge test` passes (includes `DevOnlyChainGuardTest`). 2. **Anvil:** `anvil` then `forge script script/DeployDev.s.sol --broadcast --rpc-url http://127.0.0.1:8545 --code-size-limit 524288` completes (or your usual stack script). 3. **Wrong chain:** `forge script script/DeployDev.s.sol -vvv --fork-url https://eth.llamarpc.com` (or any RPC with chain id **≠** 31337/6342/6343) should **simulate-revert** at the guard before any deploy. 4. Optional: `cast chain-id --rpc-url <megaeth-testnet>` returns **6343** — fork/broadcast tests against that ID should pass the guard (still exercise caution with real keys). Parent context: [#138](https://gitlab.com/PlasticDigits/yieldomega/-/issues/138) Finding 3.
PlasticDigits commented 2026-05-04 14:34:03 +00:00 (Migrated from gitlab.com)

mentioned in commit 0f7b9a4e34

mentioned in commit 0f7b9a4e3428a61b87530717ec32e780f3c27b28
Brouie commented 2026-05-05 02:10:31 +00:00 (Migrated from gitlab.com)

@PlasticDigits — verification PASS on ce71d7f. walked your checklist:

  1. FOUNDRY_PROFILE=ci forge test --match-contract DevOnlyChainGuardTest green: 5/5 PASS — allows_anvil (31337), allows_megaeth_testnet (6343), allows_megaeth_testnet_legacy (6342), reverts_mainnet_eth (1), reverts_megaeth_mainnet (4326). full forge suite 310/310 on a421ba1.
    2-3. live anvil deploy + wrong-chain fork smoke skipped this round (no localnet stack up). guard wiring verified at source: DeployDev.s.sol:42, DeployKumbayaAnvilFixtures.s.sol:26, AnvilSameBlockDrill.s.sol:35, SimulateAnvilRichState.s.sol:64/135/227 (all three Parts). DevOnlyChainGuard.assertDevScriptChain() reverts DevOnlyChainGuard: chain not allowed (31337/6342/6343) on disallowed IDs.
  2. info-only — skipped.
    the test that matters most for the actual misconfig risk is reverts_megaeth_mainnet (4326) since that's the realistic 'staging RPC env points at mainnet by mistake' shape. that path reverts cleanly.
    ready for close on your side.
@PlasticDigits — verification PASS on `ce71d7f`. walked your checklist: 1. `FOUNDRY_PROFILE=ci forge test --match-contract DevOnlyChainGuardTest` green: 5/5 PASS — `allows_anvil` (31337), `allows_megaeth_testnet` (6343), `allows_megaeth_testnet_legacy` (6342), `reverts_mainnet_eth` (1), `reverts_megaeth_mainnet` (4326). full forge suite 310/310 on `a421ba1`. 2-3. live anvil deploy + wrong-chain fork smoke skipped this round (no localnet stack up). guard wiring verified at source: `DeployDev.s.sol:42`, `DeployKumbayaAnvilFixtures.s.sol:26`, `AnvilSameBlockDrill.s.sol:35`, `SimulateAnvilRichState.s.sol:64/135/227` (all three Parts). `DevOnlyChainGuard.assertDevScriptChain()` reverts `DevOnlyChainGuard: chain not allowed (31337/6342/6343)` on disallowed IDs. 4. info-only — skipped. the test that matters most for the actual misconfig risk is `reverts_megaeth_mainnet` (4326) since that's the realistic 'staging RPC env points at mainnet by mistake' shape. that path reverts cleanly. ready for close on your side.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-05 02:35:52 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#141
No description provided.