# Anyone can sell other users' tokens as `fromToken`, and get the `toToken`'s themselves due to `decodeData.payer` is never checked.

D3Proxy's swap callback deposits from an unchecked decodeData.payer, letting anyone sell a victim's approved tokens and keep the toToken proceeds.

- Payout: Contest reward
- Severity: high
- Program: Dodo
- Credited: dirk_y
- Disclosed: 2023-06-14
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-06-dodo-judging/issues/106
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-06-dodo%3AH-3
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** D3Proxy.sol sellTokens / d3MMSwapCallBack on D3MM pool
**Root cause:** d3MMSwapCallBack decodes SwapCallbackData.payer and calls _deposit(payer,...) without verifying the payer is the actual seller who initiated sellTokens.
**Steps:**
1. Victim approves D3Proxy/pool for fromToken (e.g. max approval).
2. Attacker calls `D3Proxy.sellTokens(pool, attacker, fromToken, toToken, fromAmount, minReceiveAmount, data, deadLine)` with `data = abi.encode(SwapCallbackData({payer: victim}))`.
3. Pool transfers toToken to attacker via `_transferOut(to, toToken, receiveToAmount)`.
4. Pool calls back `d3MMSwapCallBack(fromToken, fromAmount, data)`; proxy runs `_deposit(victim, pool, fromToken, fromAmount)` pulling victim's approved tokens.
5. Pool balance check passes; attacker keeps toToken proceeds.
**How found:** Code review of the sellToken flow: noticed callback deposits from decodeData.payer and that no check ties payer to the seller (msg.sender is the pool in callback).
**Exploitation:** Attacker scans token allowances to D3Proxy/pool or front-runs a victim's approval, then submits sellTokens with payer set to the victim, extracting the swapped toToken to their own address while victim's fromToken is deposited.
**Escalation:** Can be repeated across any user with standing approval; mempool front-running of approvals widens victim set.
**Insight:** In callback-based DEX proxies, the deposit payer field is attacker-controlled calldata; verify payer equals the original sellTokens caller (cache seller before the pool call) rather than trusting decoded data.
