Cross-contract reentrancy in vault settle() via fee plugin callback
The vault settles balances after invoking a user-controlled fee plugin. An attacker can register a malicious plugin that re-enters settle() before the vault state is updated, draining funds across positions.
A single attacker can drain the vault of all active positions in a single transaction. Loss is bounded only by available liquidity at the time of attack.
- 01Deploy malicious feePlugin contract whose hook callback re-enters Vault.settle().
- 02Open a small position in the vault to qualify as a registered user.
- 03Trigger settle() — the vault calls plugin.onSettle() before updating internal accounting.
- 04Plugin re-enters settle() with crafted parameters, repeatedly draining shares before balance writes complete.
Apply checks-effects-interactions: write final balances and update internal accounting before invoking any external plugin. Add a non-reentrant guard on settle() and on every external function that mutates shares. Consider isolating plugin execution via a stateless adapter contract to remove the call from the trust boundary.
- SWC-107
- ConsenSys Reentrancy Patterns