graphprotocol / graphprotocol/contracts
CI does not pin Foundry: forge 1.8 breaks the issuance callback gas canary
Nobody has claimed this yet.
- Dominant language
- Solidity
- Stars
- 374
- Forks
- 176
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 4
Description
Summary
On a clean checkout of main, pnpm test fails for anyone running Foundry 1.8.x:
packages/issuance/test/unit/agreement-manager/callbackGas.t.sol
test_AfterCollection_GasWithinBudget_CanceledBySP
[FAIL: afterCollection (canceled by SP) exceeds 1/10th of callback gas budget: 181458 >= 150000]
Not a contract regression — the bytecode is unchanged. Foundry 1.8 changed warm/cold storage
accounting across calls within a test body, and the canary was relying on the old behaviour.
Bisect
Same commit, same solc_version = '0.8.35' / evm_version = 'cancun', only the forge binary changed:
| forge | result |
|---|---|
| v1.4.0 | PASS |
| v1.5.0 | PASS |
| v1.7.0 | PASS |
| v1.8.0 | FAIL — 181,458 |
| v1.8.1 | FAIL — 181,458 |
Mechanism
From -vvvv traces of the identical test:
| forge 1.7.0 | forge 1.8.1 | |
|---|---|---|
distributeIssuance() |
5,424 | 31,124 |
afterCollection() |
89,772 | 191,772 |
setUp() and _offerAgreement() touch the allocator, token account and escrow slots before the
measured call. Under ≤1.7 those stayed warm into afterCollection; under 1.8 they are cold and
pay full EIP-2929 cost. I have not confirmed against the 1.8 changelog whether this was
deliberate, though it looks intentional — the callback is its own transaction in production,
where cold slots are the honest baseline.
Why CI hasn't caught it
.github/actions/setup/action.yml:14 uses foundry-rs/foundry-toolchain@v1 with no version,
which defaults to stable. The cache input doesn't pin it either (cache-key is per-SHA).
Triage note: the green checks on main aren't evidence against this. The latest
build-test.yml run is 2026-08-26T20:03:43Z; forge 1.8.1 was built 2026-08-28. No CI run has
executed against 1.8.x yet because no PR has opened since. The next PR will surface it, as a
mystery failure in a package the author didn't touch.
Suggested fix
- uses: foundry-rs/foundry-toolchain@v1
with:
version: v1.7.0
Separately, worth deciding what the canary should measure. Its stated intent is catching RAM code
getting heavier, but under ≤1.7 roughly 60k of its slack came from warm-slot carryover rather than
lean code. Since the production callback runs as its own transaction, 181k is closer to real than
89k — so the true margin against MAX_CALLBACK_GAS is thinner than the suite has reported. Either
re-baseline against cold accounting or warm the slots deliberately in setUp.
Minor, related
README.md:52 lists only git and pnpm as prerequisites. Foundry is required — horizon,
subgraph-service, issuance and testing all shell out to forge, and the first two need it at
compile time via hardhat-foundry. Following the README as written, pnpm build fails with
Error in plugin hardhat-foundry: Couldn't run 'forge', which doesn't name the missing prerequisite.
Environment
forge 1.8.1 (982849d314) / 1.8.0, compared against 1.7.0 / 1.5.0 / 1.4.0 · Node v24.20.0 · pnpm 10.28.0 · WSL2
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with .github/actions/setup/action.yml:14 and inspect how the Foundry toolchain action receives its version and cache settings. Run pnpm test with the current CI toolchain to reproduce the callbackGas.t.sol failure, then verify that CI uses a pinned Forge version and the issuance gas canary passes; the separate cold-accounting and README concerns need maintainer direction.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions, solidity
- Domain
- ci-cd, testing
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 78/100