Skip to content

Add ABI/annotation drift check; fix one dropped stakingV2 face - #3003

Draft
taopunks wants to merge 2 commits into
RaoFoundation:mainfrom
taopunks:fix/stakingv2-abi-drift
Draft

Add ABI/annotation drift check; fix one dropped stakingV2 face#3003
taopunks wants to merge 2 commits into
RaoFoundation:mainfrom
taopunks:fix/stakingv2-abi-drift

Conversation

@taopunks

@taopunks taopunks commented Jul 28, 2026

Copy link
Copy Markdown

getTotalColdkeyStakeOnSubnet(bytes32,uint256) is declared in precompiles/src/staking.rs with #[precompile::public] and #[precompile::view] inside impl StakingPrecompileV2, and dispatches on chain today. It is absent from precompiles/src/solidity/stakingV2.abi and stakingV2.sol.

Present in the Rust and missing from the vendored artifacts at both v438 (c1463f2c) and v440 (e4ffa2e1) — two releases. stakingV2.abi grew from 24 to 33 function entries across v439, so the artifacts are actively maintained and this looks like a drop rather than staleness.

An integrator enumerating callable faces from the vendored ABI — the natural thing to do, since it is the machine-readable artifact — cannot see this face at all.

Reproduce

Extract every #[precompile::public("…")] from precompiles/src/*.rs; extract every type: "function" signature from precompiles/src/solidity/*.abi; diff both directions. At e4ffa2e1: 168 rust faces, 168 abi functions, one present only in the Rust.

The reverse direction returns only verify(bytes32,bytes32,bytes32,bytes32) on ed25519Verify/sr25519Verify — those precompiles consume raw calldata and dispatch no selector, so the artifacts describe a calling convention with no annotated face behind them. Allowlisted in the check with that reasoning inline.

Two implementation notes

The Rust scanner is newline-agnostic on purpose. rustfmt wraps long attributes, so a line-oriented scan silently misses exactly the faces with the most parameters — today serveAxonTls and both long registerNetwork variants. A strict single-line regex finds 165 of 168.

The ABI side is module-agnostic, unioning every .abi rather than pairing each to a Rust module. Modules are snake_case, artifacts are camelCase, and staking.rs alone declares both staking and stakingV2 — a per-module mapping is a second thing that can be wrong, and it fails in the direction that manufactures findings. (My first attempt did exactly that and reported 9 false drops.)

Commits

  1. the check — fails on main today, naming the drifted face
  2. the fix — adds the entry to both artifacts; the check passes

Verification

Run against 1.89.0 (matching rust-toolchain.toml), with the workspace's expect-used / unwrap-used / indexing-slicing / arithmetic-side-effects deny lints replicated:

  • cargo test --test abi_drift on pristine mainfails, naming getTotalColdkeyStakeOnSubnet(bytes32,uint256)
  • same test with the fix applied → passes
  • cargo clippy --all-targets -- -D warningsclean

The test module carries #![allow(clippy::expect_used, clippy::arithmetic_side_effects, clippy::indexing_slicing)], matching the pattern already used in address_mapping.rs, alpha.rs, crowdloan.rs, leasing.rs and others. It uses no .unwrap().

No runtime logic is touched — requesting the no-spec-version-bump label.

Related

#2455 (precompile versioning and deprecation lifecycle) describes the general fragility this sits inside. #2998's coverage-and-testing.md specifies finding drift in both directions between the Rust signatures and the vendored ABIs — this adds a mechanical check for that specific direction, and the one face it currently finds is the motivation.

Disclosure

I hit this from the integrator side: I gate precompile calls from a contract and enumerate the callable surface to build that gate. The missing face is why I noticed.

taopunks added 2 commits July 28, 2026 12:35
… source

precompiles/src/solidity/*.abi is what EVM integrators consume as the interface of
record. It is maintained alongside precompiles/src/*.rs rather than generated from
it, so a face can be added to the Rust and missed in the ABI. The omission is
silent: the precompile dispatches correctly on chain, but tooling that enumerates
from the vendored ABI cannot see the face at all.

This test diffs the two sets in both directions and fails naming the signature.

Two details worth noting:

The Rust scanner is newline-agnostic. rustfmt wraps long attributes, so a
line-oriented scan silently misses exactly the faces with the most parameters —
today that is serveAxonTls and both long registerNetwork variants, three of the
most privileged faces in the tree. A strict single-line regex finds 165 of 168.

The ABI side is module-agnostic, unioning every .abi rather than pairing each to a
Rust module. Modules are snake_case and artifacts are camelCase, and staking.rs
alone declares both staking and stakingV2 — a per-module mapping is a second thing
that can be wrong, and it fails in the direction that manufactures findings.

ed25519/sr25519 verify() is allowlisted: those precompiles consume raw calldata and
dispatch no selector, so the artifacts describe a calling convention with no
annotated face behind it.

This commit fails: it finds one drifted face. The fix follows.
…V2 artifacts

getTotalColdkeyStakeOnSubnet(bytes32,uint256) is declared at precompiles/src/
staking.rs with #[precompile::public] and #[precompile::view], inside
impl StakingPrecompileV2, and dispatches on chain today. It is absent from
precompiles/src/solidity/stakingV2.abi and stakingV2.sol.

Present in the Rust and missing from the vendored artifacts at both v438
(c1463f2) and v440 (e4ffa2e) — two releases. stakingV2.abi grew 101 -> 139
entries across v439, so the artifacts are actively maintained and this is a drop
rather than staleness.

An integrator enumerating callable faces from the vendored ABI — which is the
natural thing to do, since it is the machine-readable artifact — cannot see this
face at all.

Added to both the .abi and the .sol, matching the shape and placement of its
sibling getTotalColdkeyStake(bytes32). With this commit the test added in the
previous commit passes.
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

@taopunks is attempting to deploy a commit to the RaoFoundation Team on Vercel.

A member of the Team first needs to authorize it.

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