All findings

HyperFX ·Ethereum

CallDispatcher — unauthenticated dispatch() drains stranded tokens

Medium

Verified with working PoC

Contract: 0xE2C7e576E26E0bE7aC97c6fE925bcDAbD87c4bEd

access controlintent architecturefund drain

Summary

An honest, fully valid IntentGatewayV2.placeOrder() order that unwraps a real LP position via predispatch strands the undeclared leg on CallDispatcher, which an unrelated third party can then drain via a direct, unauthenticated dispatch() call.

Root cause

placeOrder's sweep loop iterates order.inputs, not whatever the predispatch calldata actually produced, and dispatch() has no caller restriction at all.

Verification

Falsifies the invariant 'no undeclared ERC20 ever remains on CallDispatcher after a valid placeOrder() call' with a passing mainnet-fork Foundry test - real, currently-deployed CallDispatcher address confirmed by reading the actual on-chain storage, correcting an earlier address mismap from the minified frontend bundle mid-investigation.

Verified against real, live deployed contract state.

Receipt on GitHub