Skip to content

Gate transfer decode to exact Balances calls - #604

Open
LandynDev wants to merge 2 commits into
testfrom
fix/decode-transfer-module-gate
Open

Gate transfer decode to exact Balances calls#604
LandynDev wants to merge 2 commits into
testfrom
fix/decode-transfer-module-gate

Conversation

@LandynDev

@LandynDev LandynDev commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

decode_transfer accepted any call with transfer in its name — no pallet check. Both decode paths are now gated to exact Balances.{transfer_allow_death, transfer_keep_alive}; adds decode_stake_transfer for SubtensorModule.transfer_stake (needed by the upcoming chain watcher).

Severity: hardening, not a live hole — transfer_all/transfer_stake decoded with amount=0, and both call sites require amount >= expected, so no payment could ever have been falsely approved. The real prior defect was false negatives (e.g. a genuine transfer_all payment could never verify) plus a lookalike-call surface the exact-name gate now closes. The raw path's 7: transfer_all entry never matched anything — transfer_all is call index 4 on Subtensor — so it is dropped rather than fixed, and the rejection test pins index 4.

Before → after (structured path, same fixtures as the new tests):

transfer_all    ('0xabc', '5Miner…', 0, '5User…')    → None        # previously amount 0: a real payment that could never verify
transfer_stake  ('0xdef', '', 0, '5User…')           → None        # not a TAO transfer at all
keep_alive      ('0x123', '5Miner…', 5000, '5User…') → unchanged

Independent fix: the decode is only called from fetch_matching_tx / find_recent_outgoing in the same file, and call_module is present in the installed scalecodec serialization. Full suite: 814 passed.

@anderdc anderdc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests/test_decode_transfer.py:124 — transfer_all is call index 4 on Subtensor, not 7; index 7 doesn't exist in the Balances pallet (verified against live finney metadata: 0/2/3/4/5/6/8/9/10). test_raw_path_rejects_transfer_all_index passes for any unmapped index, so it pins nothing — use call_idx=4. allways/chain_providers/subtensor.py:26-28 — the raw path never decoded transfer_all either, since 4 was never in _TRANSFER_CALLS; drop that claim from the comment and the PR body so nobody later "restores" 7. The structured-path gate itself is correct and verified against real mainnet extrinsics on the pinned async-substrate-interface 2.2.1. Worth stating the true severity too: transfer_all/transfer_stake decoded with amount 0 and both call sites require amount >= expected, so no payment could ever have been falsely approved — this is hardening, not a live hole.

@LandynDev

Copy link
Copy Markdown
Collaborator Author

All three points addressed in the latest push: rejection test now pins the real index 4 (with a comment naming it so the pin is legible), the index-7/keep_alive claim is dropped from the module comment, test docstring, and PR body, and the body now states the honest severity — hardening against false negatives + lookalike calls, not a falsely-approving hole. Thanks for checking against live finney metadata.

@LandynDev
LandynDev requested a review from anderdc July 28, 2026 18:53
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.

2 participants