# Unvalidated fee field drains tokens

Fee or refund fields from attacker input used to move funds without bounds or recipient checks

_Area: Smart contract access control and control flow. Seen in 3 disclosed reports; one confirmed bounty: $1,000,000; latest 2023-11-21. Updated 2026-10-23._

## How it works
A contract accepts a fee, refund address, or relayer field from caller-supplied input (a message blob, a call-params struct, a signed order) and uses it to move funds. The broken assumption is that the fee is a small, legitimate amount and that the party paying it is the caller. When the code forwards a whole balance as `msg.value`, or trusts a fee parsed from an untrusted message, the excess or the fee itself is paid out of funds the caller does not own — the contract's balance or a victim's tokens — to an address the caller chose.

## Where it shows up
- Payable calls forwarding `address(this).balance` instead of a computed required fee.
- Functions that refund excess `msg.value` to a caller-supplied `refundAddress`.
- Bridge/token handlers parsing fee, relayer, or recipient from a user-supplied `msg` blob.
- Order validation that checks recipient, tokens, price, slippage but skips fee fields.
- Any field in a signed struct consumed by fill math but not constrained.

## How to review
For each externally supplied fee/refund/relayer field, trace where it is used to move value. The invariant: the amount moved must be bounded by what the caller actually supplied or is entitled to, and the recipient of any refund must be the payer. Check that `msg.value` forwarded equals the required fee, not the contract balance; that parsed fees are bounded by the transferred amount and charged to the sender; and that every order-struct field the exchange consumes is validated (fees zero or within limits).

## Variants seen
- Whole contract balance forwarded as `msg.value`, excess refunded to attacker address [E1](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-48.md).
- Fee parsed from attacker `msg` blob, transferred from recipient to relayer, draining victim ERC20s [E2](https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-aurora-improper-input-sanitization-bugfix-review.md).
- Signed order omits makerFee/takerFee checks, letting a manager route maker proceeds to fees [E3](https://bugbountylibrary.com/r/c4%3A2022-01-notional%3AH-03.md).

## Impact and severity
Direct theft of contract or victim token balances; E2 reached up to 18.4 ETH per call. Severity is high because the drain is repeatable and needs no special privilege, only the ability to submit the crafted field. Worse when the same balance is reused across calls or the fee is unbounded.

## Why fixes fail
Partial validation that checks some order fields but not fees [E3](https://bugbountylibrary.com/r/c4%3A2022-01-notional%3AH-03.md) leaves the drain open; bounding one path (fee) without fixing the refund recipient [E1](https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-48.md) still leaks the balance.

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-48.md
- E2: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-aurora-improper-input-sanitization-bugfix-review.md
- E3: https://bugbountylibrary.com/r/c4%3A2022-01-notional%3AH-03.md
