Skip to content

Prevent native protocol fee payout DoS - #32

Merged
dangerousfood merged 2 commits into
masterfrom
codex/nonblocking-native-protocol-fees
Aug 14, 2026
Merged

dangerousfood merged 2 commits into
masterfrom
codex/nonblocking-native-protocol-fees

Conversation

@dangerousfood

@dangerousfood dangerousfood commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • route owner-configured protocol fee payouts through Solady forceSafeTransferETH when the fee token is native ETH
  • preserve standard ERC-20 fee transfers and existing caller, maker, refund, and caller-selected integrator payout semantics
  • cover rejecting protocol recipients across fill, fillWithIntegratorFee, fillRoute, and fillRouteWithIntegratorFee
  • verify accepting contract recipients still receive one normal callback before the force-transfer fallback is considered

Root cause

Native protocol fees used safeTransferETH, so an owner-configured recipient with a reverting or non-payable receiver reverted the complete matched fill. The same global recipient is shared by all fills, allowing one configuration mistake to halt ETH-output execution until the owner corrected it.

The fix uses Solady’s bounded-call force-transfer path only for protocol fees. If the recipient rejects the bounded call, an ephemeral contract force-delivers the exact ETH amount. Integrator recipients remain regular safe transfers because they are caller-selected and only affect the opt-in call that supplied them.

Validation

  • forge test --match-path test/DeepstateV1NativeETH.t.sol -vv: 19 passed
  • make test: 388 passed
  • native ETH stateful invariants: 3 passed, each with 256 runs and 16,384 calls
  • make coverage-check: adjusted 100% lines, statements, branches, and functions
  • make snapshot-runtime: 80 isolated gas tests passed; all 44 changed baselines decreased by 5-28 gas, with no increases
  • make formal-smt: 1,253 complete-domain SMT obligations passed
  • make formal-halmos: 26 symbolic tests passed
  • make slither: 0 findings
  • forge fmt --check, forge lint, make build-size: passed; runtime size 22,589 bytes (1,987-byte margin)

@dangerousfood
dangerousfood marked this pull request as ready for review August 14, 2026 17:13
@dangerousfood
dangerousfood merged commit 9488201 into master Aug 14, 2026
19 checks passed
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