From b8a21971e2dff78a9a5e41b8ceaabed945446110 Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Mon, 15 Jun 2026 13:55:05 -0700 Subject: [PATCH 1/8] ci(smoke): add per-platform install + Base precompile smoke test (BOP-385) Validate published base-anvil binaries the way an external developer does: run the public install one-liner, then a dependency-free Base precompile test that passes only when the binary registered + seeded the Base ActivationRegistry (no false pass). v0 covers the POSIX legs (Linux gnu amd64 new/old glibc, arm64; macOS arm64 + Intel). Windows and Alpine/musl deferred to a follow-up. Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 80 +++++++++++++++++++++++++++++++++ smoke/.gitignore | 3 ++ smoke/foundry.toml | 5 +++ smoke/test/BasePrecompile.t.sol | 46 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 .github/workflows/smoke.yml create mode 100644 smoke/.gitignore create mode 100644 smoke/foundry.toml create mode 100644 smoke/test/BasePrecompile.t.sol diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml new file mode 100644 index 000000000..c0a3866b1 --- /dev/null +++ b/.github/workflows/smoke.yml @@ -0,0 +1,80 @@ +name: smoke + +# Validate ALREADY-PUBLISHED base-anvil binaries on each target OS by doing +# exactly what an external developer does: run the public install one-liner, +# then run a real Base precompile test. This is the per-platform coverage a +# single laptop cannot do locally (BOP-385). +# +# v0 scope: the POSIX (bash) legs only -- Linux gnu (amd64 on new + old glibc, +# arm64) and macOS (arm64 + Intel). Windows and Alpine/musl are deliberately +# deferred to a follow-up iteration: they need extra shell/dependency handling. + +on: + workflow_dispatch: + inputs: + version: + description: "Published release to validate (e.g. v1.1.0-rc.19). Blank = base-foundryup default." + required: false + default: "" + # Once this is green, enable a daily run against the current default release: + # schedule: + # - cron: "0 12 * * *" + +permissions: {} + +jobs: + smoke: + name: smoke ${{ matrix.label }} + runs-on: ${{ matrix.runner }} + timeout-minutes: 20 + strategy: + fail-fast: false # one platform failing must not hide the others + matrix: + include: + - label: linux-amd64 (glibc, ubuntu 24.04) + runner: ubuntu-24.04 + - label: linux-amd64 (older glibc, ubuntu 22.04) + runner: ubuntu-22.04 + - label: linux-arm64 (glibc, ubuntu 24.04) + runner: ubuntu-24.04-arm + - label: macos-arm64 + runner: macos-latest + - label: macos-amd64 (intel) + runner: macos-13 + steps: + - name: Check out the proof test + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Install base-anvil via the public flow + shell: bash + env: + VERSION: ${{ inputs.version }} + FOUNDRY_DISABLE_NIGHTLY_WARNING: "1" + run: | + set -euo pipefail + curl -L https://raw.githubusercontent.com/base/base-anvil/HEAD/foundryup/install | bash + export PATH="$HOME/.foundry/bin:$PATH" + + # Resilient to either install variant: the namespaced base-foundryup + # (current default branch) or the older `foundryup --network base`. + if command -v base-foundryup >/dev/null 2>&1; then + base-foundryup ${VERSION:+--install "$VERSION"} + echo "FORGE=base-forge" >> "$GITHUB_ENV" + else + foundryup --network base ${VERSION:+--install "$VERSION"} + echo "FORGE=forge" >> "$GITHUB_ENV" + fi + + - name: Run the Base proof test + shell: bash + run: | + set -euo pipefail + export PATH="$HOME/.foundry/bin:$PATH" + cd smoke + if [ "$FORGE" = base-forge ]; then + base-forge test -vvv # base-forge enables Base by default + else + forge test --base -vvv + fi diff --git a/smoke/.gitignore b/smoke/.gitignore new file mode 100644 index 000000000..ccb098322 --- /dev/null +++ b/smoke/.gitignore @@ -0,0 +1,3 @@ +cache/ +out/ +broadcast/ diff --git a/smoke/foundry.toml b/smoke/foundry.toml new file mode 100644 index 000000000..ece2b0479 --- /dev/null +++ b/smoke/foundry.toml @@ -0,0 +1,5 @@ +[profile.default] +test = "test" +# Deliberately dependency-free so the smoke test stays hermetic: no forge-std, +# no `forge install`, no submodules, no network. The proof test inlines the one +# interface it needs. diff --git a/smoke/test/BasePrecompile.t.sol b/smoke/test/BasePrecompile.t.sol new file mode 100644 index 000000000..5243b331b --- /dev/null +++ b/smoke/test/BasePrecompile.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface IActivationRegistry { + function isActivated(bytes32 feature) external view returns (bool); +} + +/// @notice Proof that a base-anvil binary actually installed and seeded the Base +/// precompiles. Run via `base-forge test` (Base enabled by default) or +/// `forge test --base`. +/// +/// The address and feature ids are the real Base values: +/// - ActivationRegistry address: base-std `StdPrecompiles.sol`. +/// - feature ids: base-std `ActivationRegistryFeatureList.sol`, which match +/// the three features base-anvil seeds active in +/// `crates/evm/networks/src/lib.rs` (`base_activation_seeds()`). +/// +/// WITHOUT --base the address is an empty account, `isActivated()` returns +/// false, and this test FAILS: the false-pass becomes a visible failure. +/// WITH --base the precompile is registered and seeded, so it returns true. +contract BasePrecompileSmokeTest { + IActivationRegistry constant ACTIVATION_REGISTRY = + IActivationRegistry(0x8453000000000000000000000000000000000001); + + // keccak256("base.b20_asset") + bytes32 constant B20_ASSET = 0xcdcc772fe4cbdb1029f822861176d09e646db96723d4c1e82ddfdeb8163ef54c; + // keccak256("base.b20_stablecoin") + bytes32 constant B20_STABLECOIN = 0xecfa0def2c10020caaf65e6155aa69c84b24892aaef76eeac52e0e2b3a0b8601; + // keccak256("base.policy_registry") + bytes32 constant POLICY_REGISTRY = 0xb582ebae03f16fee49a6763f78df482fb11ae73f103ed0d330bbe556aa90a43f; + + function test_basePrecompileSeededActive() external view { + require( + ACTIVATION_REGISTRY.isActivated(B20_ASSET), + "B20_ASSET inactive: --base not applied or precompile missing" + ); + require( + ACTIVATION_REGISTRY.isActivated(B20_STABLECOIN), + "B20_STABLECOIN inactive: --base not applied or precompile missing" + ); + require( + ACTIVATION_REGISTRY.isActivated(POLICY_REGISTRY), + "POLICY_REGISTRY inactive: --base not applied or precompile missing" + ); + } +} From 214ca45465940e729114543850abc2bf26e679f7 Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Mon, 15 Jun 2026 14:02:22 -0700 Subject: [PATCH 2/8] ci(smoke): run on PRs touching smoke files workflow_dispatch is not triggerable until the file lands on the default branch, so add a path-scoped pull_request trigger to exercise the matrix on this PR (and whenever the smoke harness changes). Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index c0a3866b1..c097d77d2 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -16,6 +16,13 @@ on: description: "Published release to validate (e.g. v1.1.0-rc.19). Blank = base-foundryup default." required: false default: "" + # Self-test the smoke harness whenever it changes (and on this PR). Scoped to + # smoke files so it does not run on unrelated PRs. workflow_dispatch only + # becomes triggerable once this file is on the default branch. + pull_request: + paths: + - "smoke/**" + - ".github/workflows/smoke.yml" # Once this is green, enable a daily run against the current default release: # schedule: # - cron: "0 12 * * *" From 84bd3a51f2f9a3b84ad8c80ebdf736ebeee2997a Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Mon, 15 Jun 2026 14:25:15 -0700 Subject: [PATCH 3/8] ci(smoke): fix install dir on Linux + defer Intel-Mac leg - Pin FOUNDRY_DIR=$HOME/.foundry and use absolute bin paths + $GITHUB_PATH: XDG_CONFIG_HOME is set on the Linux runners (not macOS), so the installer put base-foundryup under $XDG_CONFIG_HOME/.foundry and the hardcoded $HOME/.foundry/bin missed it (exit 127). - Comment out the macos-13 (Intel) leg: that runner does not provision in this org and hangs until the 24h timeout (same as BOP-367). Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index c097d77d2..2b34f8f93 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -5,9 +5,9 @@ name: smoke # then run a real Base precompile test. This is the per-platform coverage a # single laptop cannot do locally (BOP-385). # -# v0 scope: the POSIX (bash) legs only -- Linux gnu (amd64 on new + old glibc, -# arm64) and macOS (arm64 + Intel). Windows and Alpine/musl are deliberately -# deferred to a follow-up iteration: they need extra shell/dependency handling. +# v0 scope: Linux gnu (amd64 on new + old glibc, arm64) and macOS arm64. +# Deferred to follow-ups: Windows and Alpine/musl (extra shell/dependency +# handling) and Intel macOS (macos-13 runner does not provision here). on: workflow_dispatch: @@ -46,8 +46,12 @@ jobs: runner: ubuntu-24.04-arm - label: macos-arm64 runner: macos-latest - - label: macos-amd64 (intel) - runner: macos-13 + # macos-amd64 (Intel) is deferred: the macos-13 runner does not + # provision in this org (it sits queued until the 24h timeout, the + # same symptom noted in BOP-367). Intel-Mac coverage will come via a + # Rosetta-on-arm64 run or a self-hosted runner in a follow-up. + # - label: macos-amd64 (intel) + # runner: macos-13 steps: - name: Check out the proof test uses: actions/checkout@v6 @@ -61,16 +65,21 @@ jobs: FOUNDRY_DISABLE_NIGHTLY_WARNING: "1" run: | set -euo pipefail + # Pin the install dir: the installer otherwise uses + # ${XDG_CONFIG_HOME:-$HOME}/.foundry, and XDG_CONFIG_HOME is set on the + # Linux runners (but not macOS), which moves the bin dir out from under us. + export FOUNDRY_DIR="$HOME/.foundry" curl -L https://raw.githubusercontent.com/base/base-anvil/HEAD/foundryup/install | bash - export PATH="$HOME/.foundry/bin:$PATH" + bin="$FOUNDRY_DIR/bin" + echo "$bin" >> "$GITHUB_PATH" # Resilient to either install variant: the namespaced base-foundryup # (current default branch) or the older `foundryup --network base`. - if command -v base-foundryup >/dev/null 2>&1; then - base-foundryup ${VERSION:+--install "$VERSION"} + if [ -x "$bin/base-foundryup" ]; then + "$bin/base-foundryup" ${VERSION:+--install "$VERSION"} echo "FORGE=base-forge" >> "$GITHUB_ENV" else - foundryup --network base ${VERSION:+--install "$VERSION"} + "$bin/foundryup" --network base ${VERSION:+--install "$VERSION"} echo "FORGE=forge" >> "$GITHUB_ENV" fi @@ -78,7 +87,6 @@ jobs: shell: bash run: | set -euo pipefail - export PATH="$HOME/.foundry/bin:$PATH" cd smoke if [ "$FORGE" = base-forge ]; then base-forge test -vvv # base-forge enables Base by default From 5acf3d4a1c18b643c200afaf81791f52521cd2bd Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Tue, 23 Jun 2026 14:21:30 -0700 Subject: [PATCH 4/8] ci(smoke): add arm64 old-glibc leg (ubuntu-22.04-arm) The ticket's headline finding was an arm64-specific glibc floor (gnu arm64 binaries needing GLIBC_2.39). The matrix only tested arm64 on new glibc (24.04); add ubuntu-22.04-arm so the smoke job actually exercises the arm64 old-glibc path that bug lived on. Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 2b34f8f93..6d5d497d4 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -5,7 +5,7 @@ name: smoke # then run a real Base precompile test. This is the per-platform coverage a # single laptop cannot do locally (BOP-385). # -# v0 scope: Linux gnu (amd64 on new + old glibc, arm64) and macOS arm64. +# v0 scope: Linux gnu (amd64 and arm64, each on new + old glibc) and macOS arm64. # Deferred to follow-ups: Windows and Alpine/musl (extra shell/dependency # handling) and Intel macOS (macos-13 runner does not provision here). @@ -44,6 +44,8 @@ jobs: runner: ubuntu-22.04 - label: linux-arm64 (glibc, ubuntu 24.04) runner: ubuntu-24.04-arm + - label: linux-arm64 (older glibc, ubuntu 22.04) + runner: ubuntu-22.04-arm - label: macos-arm64 runner: macos-latest # macos-amd64 (Intel) is deferred: the macos-13 runner does not From 34491f0ac595b7d9a3422449c27a5779e08dcb1a Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Tue, 23 Jun 2026 14:23:54 -0700 Subject: [PATCH 5/8] ci(smoke): quarantine arm64 old-glibc leg as non-blocking The leg reproduces a real, currently-live failure: the rc.19 arm64 gnu binary the default base-foundryup installs needs GLIBC_2.38/2.39 and fails on old-glibc arm64. Mark it experimental (continue-on-error) so it keeps reporting but does not block the run; it auto-flips green once the #42 glibc-floor fix ships to the default release. Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 6d5d497d4..a8bb73760 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -34,6 +34,8 @@ jobs: name: smoke ${{ matrix.label }} runs-on: ${{ matrix.runner }} timeout-minutes: 20 + # A leg flagged experimental reports its result but does not fail the run. + continue-on-error: ${{ matrix.experimental || false }} strategy: fail-fast: false # one platform failing must not hide the others matrix: @@ -44,8 +46,13 @@ jobs: runner: ubuntu-22.04 - label: linux-arm64 (glibc, ubuntu 24.04) runner: ubuntu-24.04-arm + # Known-failing until the arm64 glibc-floor fix (#42) ships to the + # release base-foundryup installs by default: rc.19's arm64 gnu binary + # needs GLIBC_2.38/2.39, so it fails on old-glibc arm64. Kept running + # (non-blocking) so it auto-flips green once a fixed release lands. - label: linux-arm64 (older glibc, ubuntu 22.04) runner: ubuntu-22.04-arm + experimental: true - label: macos-arm64 runner: macos-latest # macos-amd64 (Intel) is deferred: the macos-13 runner does not From 1c388457934a55429f8381d369e814ee6b86b374 Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Tue, 23 Jun 2026 14:40:43 -0700 Subject: [PATCH 6/8] ci(smoke): un-quarantine arm64 old-glibc leg (v1.1.0 default, #46) #46 made v1.1.0 the default base-foundryup release, and its arm64 gnu binary carries the #42 glibc-floor fix, so old-glibc arm64 now installs and passes. Drop the experimental/continue-on-error quarantine: all five legs are required again. Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index a8bb73760..6d5d497d4 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -34,8 +34,6 @@ jobs: name: smoke ${{ matrix.label }} runs-on: ${{ matrix.runner }} timeout-minutes: 20 - # A leg flagged experimental reports its result but does not fail the run. - continue-on-error: ${{ matrix.experimental || false }} strategy: fail-fast: false # one platform failing must not hide the others matrix: @@ -46,13 +44,8 @@ jobs: runner: ubuntu-22.04 - label: linux-arm64 (glibc, ubuntu 24.04) runner: ubuntu-24.04-arm - # Known-failing until the arm64 glibc-floor fix (#42) ships to the - # release base-foundryup installs by default: rc.19's arm64 gnu binary - # needs GLIBC_2.38/2.39, so it fails on old-glibc arm64. Kept running - # (non-blocking) so it auto-flips green once a fixed release lands. - label: linux-arm64 (older glibc, ubuntu 22.04) runner: ubuntu-22.04-arm - experimental: true - label: macos-arm64 runner: macos-latest # macos-amd64 (Intel) is deferred: the macos-13 runner does not From 955e2cdc179c8e93ea420f4618c8b8ba6dfa4211 Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Tue, 23 Jun 2026 14:48:21 -0700 Subject: [PATCH 7/8] ci(smoke): update version-input example from rc.19 to v1.1.0 Cosmetic: the workflow_dispatch input description example still named the old rc; the default install path was never pinned to it. Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 6d5d497d4..5c169c1ad 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -13,7 +13,7 @@ on: workflow_dispatch: inputs: version: - description: "Published release to validate (e.g. v1.1.0-rc.19). Blank = base-foundryup default." + description: "Published release to validate (e.g. v1.1.0). Blank = base-foundryup default." required: false default: "" # Self-test the smoke harness whenever it changes (and on this PR). Scoped to From 62de5d802c1b9a1060e8467ce76e2cf7601f4fee Mon Sep 17 00:00:00 2001 From: Amie Corso Date: Tue, 23 Jun 2026 15:15:12 -0700 Subject: [PATCH 8/8] ci(smoke): correct deferred Intel-Mac note (macos-13 retired; macos-15-intel) macos-13 was retired by GitHub on 2025-12-04, so the old comment's 'does not provision in this org' was inaccurate. Point the follow-up at the current macos-15-intel label and frame the test-or-drop decision. Co-authored-by: OpenCode --- .github/workflows/smoke.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 5c169c1ad..02a2071f9 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -7,7 +7,7 @@ name: smoke # # v0 scope: Linux gnu (amd64 and arm64, each on new + old glibc) and macOS arm64. # Deferred to follow-ups: Windows and Alpine/musl (extra shell/dependency -# handling) and Intel macOS (macos-13 runner does not provision here). +# handling) and Intel macOS (needs the macos-15-intel label; test-or-drop TBD). on: workflow_dispatch: @@ -48,12 +48,14 @@ jobs: runner: ubuntu-22.04-arm - label: macos-arm64 runner: macos-latest - # macos-amd64 (Intel) is deferred: the macos-13 runner does not - # provision in this org (it sits queued until the 24h timeout, the - # same symptom noted in BOP-367). Intel-Mac coverage will come via a - # Rosetta-on-arm64 run or a self-hosted runner in a follow-up. + # macos-amd64 (Intel) is deferred. GitHub retired the macos-13 image + # on 2025-12-04, so that label never provisions (jobs queue until they + # time out). Intel x86_64 macOS now runs on the macos-15-intel label, + # supported until ~Aug 2027 when Actions drops Intel macOS entirely. + # Follow-up decision: cover Intel-Mac (uncomment the leg below) or drop + # the darwin_amd64 build from the release pipeline. Don't ship it untested. # - label: macos-amd64 (intel) - # runner: macos-13 + # runner: macos-15-intel steps: - name: Check out the proof test uses: actions/checkout@v6