fix(bindings): regenerate stale ABI JSONs + honor FOUNDRY_OUT in gen-bindings#206
Conversation
…bindings The xtask copied bindings/abi/*.json from a HARDCODED `out/local-build/...`, so any FOUNDRY_OUT-redirected `gen-bindings` (which is required whenever the default `out/` is root-owned/unwritable — a recurring condition on this checkout) left the .rs bindings fresh but the abi/*.json STALE from a pre-0.19 build. Result: the committed abi JSONs still advertised removed functions (blueprintSources, canScheduleExit) and a fat getSlashProposal tuple (proposedAt/disputeReason/disputedAt) — the ABIs the dapp syncs. Publishing would have shipped these wrong ABIs. Fix: source the abi copy from the SAME out dir the build wrote to (std::env FOUNDRY_OUT, default out/local-build). Regenerate: the abi JSONs now match the 0.19 contracts (blueprintSources/canScheduleExit/getBlueprintRecord absent; getSlashProposal free of the removed timestamp/reason fields). Verified: ITangleFull.json + the 6 other synced ABIs regenerated from the fresh artifacts; forge bind .rs unchanged (it was already reading the fresh dir).
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 9e9ca52c
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
tangletools · auto-approval · reason: drewstone_author · 2026-07-07T20:49:42Z
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 120.2s (2 bridge agents) |
| Total | 120.2s |
💰 Value — sound-with-nits
Fixes a real stale-ABI bug by making cargo xtask gen-bindings copy ABI JSONs from the same Foundry output directory that the build wrote to (honoring FOUNDRY_OUT), and regenerates the 0.19 ABIs so they match the source.
- What it does: Changes
xtask/src/main.rs:167to readFOUNDRY_OUTfrom the environment and fall back toout/local-build, instead of hardcodingout/local-buildin every ABI copy path. It also regenerates the committed ABI JSONs inbindings/abi/so they reflect the current 0.19 contract source (e.g.,SlashProposalno longer contains the removedproposedAt,disputeReason, ordisputedAtfields). - Goals it achieves: Ensures that a
FOUNDRY_OUT-redirected build no longer silently copies stale ABI JSONs while producing fresh.rsbindings. This prevents shipping bindings whose JSON ABIs advertise removed functions/fields, which is what the dapp consumes. - Assessment: Good change. It fixes a coherent latent bug that would have shipped a 0.19 release with stale ABIs, and it does so in the grain of the existing Rust xtask/Foundry toolchain. The regenerated ABI JSONs now match the source struct definitions (
src/libraries/SlashingLib.sol:46-70). - Better / existing approach: none — this is the right approach. The only alternative would be parsing
foundry.tomlto derive the defaultoutvalue instead of hardcodingout/local-build, but that adds TOML parsing complexity for minimal gain; honoringFOUNDRY_OUTis the standard Foundry contract and solves the reported failure mode. - Model: opencode/kimi-for-coding/k2p7
- Bridge attempts: 1
🎯 Usefulness — sound
Correct 1-line fix making the ABI-copy step honor FOUNDRY_OUT like forge already does, plus regenerated 0.19 ABI JSONs that the dapp syncs — prevents a stale-ABI publish.
- Integration: The gen-bindings xtask is the documented canonical bindings generator (xtask/README.md, CLAUDE.md). bindings/abi/.json ship in the published crate (Cargo.toml:14-21 include = abi/**/) and are synced by the dapp; TNT_CORE_VERSION is exposed at bindings/src/lib.rs:26. The fix targets the single code path (ABI copy at xtask/src/main.rs:167-199) that was inconsistent with the forge build/bind calls
- Fit with existing patterns: Fits the grain precisely. It is a minimal behavioral fix to an existing code path — reads the same env var foundry itself uses (FOUNDRY_OUT), with a default that matches the profile config (foundry.toml:45 out = "out/local-build"). No new abstraction, no competing pattern; it removes a hardcoded path that diverged from how the surrounding forge invocations already resolved output.
- Real-world viability: Holds up on the redirected-build path it was written for: foundry's FOUNDRY_OUT replaces the whole out path (the profile subdir name is already baked into the foundry.toml out = setting), so repo_root.join(out_dir).join(rel) resolves identically to where forge build wrote. Rust Command::env overrides only the named var, so forge children inherit the parent FOUNDRY_OUT. Both relative and absolute F
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
💰 Value Audit
🟡 Default output dir is hardcoded in both foundry.toml and xtask [maintenance] ``
The fallback
out_dirdefaults toout/local-build(xtask/src/main.rs:167), which matchesfoundry.toml:45only by convention. If thelocal_buildprofile'soutvalue changes, non-FOUNDRY_OUT builds will silently copy from the wrong place again. Consider readingfoundry.tomlor runningforge configto derive the default whenFOUNDRY_OUTis unset.
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
✅ No Blockers —
|
| deepseek | kimi-code | aggregate | |
|---|---|---|---|
| Readiness | 95 | 82 | 82 |
| Confidence | 75 | 75 | 75 |
| Correctness | 95 | 82 | 82 |
| Security | 95 | 82 | 82 |
| Testing | 95 | 82 | 82 |
| Architecture | 95 | 82 | 82 |
Reviewer score is advisory once the run is complete and the verdict has no blockers.
Full multi-shot audit completed 3/3 planned shots over 9 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 3/3 planned shots over 9 changed files. Global verifier still owns final merge decision.
🟠 MEDIUM Stale TNT_CORE_VERSION hash — bindings/TNT_CORE_VERSION
Line 1 contains 691c7c7 (#203), which is an ancestor of both the PR base (69d3a0f...) and head (9e9ca52...). The PR modifies bindings/abi/.json and bindings/src/bindings/.rs, so the version stamp should reflect the commit from which those bindings were generated. Because TNT_CORE_VERSION was not updated, downstream consumers and release tooling will misreport the source commit. Fix by regenerating bindings with xtask (or setting TNT_CORE_VERSION_OVERRIDE to the PR head) so the file matches the actual source commit.
🟡 LOW Breaking ABI surface changes in generated interface ABIs — bindings/abi/ITangle.json
Concrete evidence: ITangle.json removed function selectors blueprintSources(uint64) and canScheduleExit(uint64,address), and getOperatorRegistration now returns a tuple with only registeredAt (uint64). IBlueprintServiceManager.json changed onJobResult from (uint64,uint8,uint64,address,bytes,bytes) to (uint64,uint8,uint64,address,bytes32,bytes). MultiAssetDelegation.json removed getOperatorSlashFactor(address,bytes32). These are intentional source-driven changes, but any downstream caller using the old selectors will revert. The PR already updates bindings/src Rust bindings, but external SDK/TS consumers must be aligned before relying on these ABIs.
tangletools · 2026-07-07T21:03:06Z · trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 2 non-blocking findings — 9e9ca52c
Full multi-shot audit completed 3/3 planned shots over 9 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 3/3 planned shots over 9 changed files. Global verifier still owns final merge decision.
Full immutable report for this review: trace
Summary comment for this run: full summary
tangletools · 2026-07-07T21:03:06Z · immutable trace
Latent bug that a 0.19 publish would have shipped.
cargo xtask gen-bindingscopiedbindings/abi/*.jsonfrom a hardcodedout/local-build/, so anyFOUNDRY_OUT-redirected build (required when the defaultout/is root-owned — a recurring condition) left the.rsbindings fresh but the abi JSONs stale from a pre-0.19 build. The committed abi still advertised removed functions (blueprintSources,canScheduleExit) and a fatgetSlashProposaltuple (proposedAt/disputeReason/disputedAt) — and those abi JSONs are exactly what the dapp syncs.Caught while wiring the dapp for 0.19 (its ABIs didn't match the source).
Fix: source the abi copy from the same out dir the build wrote to (
std::env FOUNDRY_OUT, defaultout/local-build), and regenerate. The abi now matches 0.19:blueprintSources/canScheduleExit/getBlueprintRecordabsent,getSlashProposalfree of the removed fields. Verified by parsing the regeneratedITangleFull.json. The.rsbindings were already correct (forge bind read the fresh dir).