Skip to content

fix(enforcers): reject non-zero native value on ERC20 streaming and ownership transfer - #197

Open
SashaMIT wants to merge 1 commit into
MetaMask:mainfrom
SashaMIT:fix/erc20-streaming-zero-value
Open

fix(enforcers): reject non-zero native value on ERC20 streaming and ownership transfer#197
SashaMIT wants to merge 1 commit into
MetaMask:mainfrom
SashaMIT:fix/erc20-streaming-zero-value

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Aug 8, 2026

Copy link
Copy Markdown

Summary

Sibling of #195. Two more enforcers still decoded executions as (target,, callData) and never constrained native ETH:

  • ERC20StreamingEnforcer (streaming ERC20 transfer)
  • OwnershipTransferEnforcer (transferOwnership)

The framework executes target.call{value: value}(callData) from the delegator's account, so a token/ownership-scoped delegation placed no constraint on ETH riding along. For standard non-payable selectors this is inert today, but any payable transfer / transferOwnership target turns the delegation into an unbounded native spend.

The repo already requires value == 0 in ApprovalRevocationEnforcer and MultiTokenPeriodEnforcer (ERC20 path), and #195 covers the other transfer enforcers. This PR brings the two remaining outliers into that pattern.

Fix

Bind value_ from decodeSingle and require(value_ == 0, "...:invalid-value") before the existing length/method checks.

Test plan

  • test_revertOnNonZeroValue on both suites (execution value = 1 expects invalid-value)
  • Mutation check: removing the streaming require makes test_revertOnNonZeroValue fail (next call did not revert as expected); restore passes
  • forge test --match-contract 'ERC20StreamingEnforcerTest|OwnershipTransferEnforcerTest' — 30/30 pass

Made with Cursor

…wnership transfer

ERC20StreamingEnforcer and OwnershipTransferEnforcer decoded executions as
(target,, callData) and never constrained native value. Token/ownership-scoped
delegations could therefore accompany unbounded ETH on payable transfer /
transferOwnership targets. Match ApprovalRevocationEnforcer /
MultiTokenPeriodEnforcer (and open MetaMask#195 siblings) by requiring value == 0.

Signed-off-by: Sasha Mitchell <sash.t.mitchell@gmail.com>
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