# Lender can trade claimToken in a malicious way to steal the borrower's money via claimAndRepay() in SpigotedLine by using malicious zeroExTradeData

Lender-controlled zeroExTradeData in SpigotedLine.claimAndRepay lets lender sell claimed revenue tokens to self and repay only a token amount, stealing borrower funds.

- Payout: Contest reward
- Severity: medium
- Program: Debt DAO
- Credited: perseverancesuccess
- Disclosed: 2023-02-07
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-11-debtdao-findings/issues/110
- Library page: https://bugbountylibrary.com/r/c4%3A2022-11-debtdao%3AM-04
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** SpigotedLine.claimAndRepay / SpigotedLineLib.claimAndTrade
**Root cause:** Lender supplies arbitrary zeroExTradeData to swap claimed revenue tokens; the only post-trade check is tokensBought != 0, so a malicious swap target can route proceeds to an attacker contract that transfers a tiny amount of credit token back to satisfy the balance check.
**Steps:**
1. Borrower opens credit line with revenue token (e.g. DAI) spigoted.
2. Lender crafts zeroExTradeData selling the full claimed claimToken amount to ETH, with swapTarget = attacker contract.
3. Attacker contract receive() forwards a tiny creditToken amount (e.g. 100 wei BUSD) to SpigotedLine.
4. Lender calls claimAndRepay(claimToken, maliciousData); spigot.claimEscrow pulls 1000 DAI, swap sends 0.6324 ETH to attacker.
5. LineLib.getBalance(targetToken) - oldTargetTokens returns the tiny injected amount, passing tokensBought != 0; _repay credits only that amount.
**How found:** Code review of claimAndTrade: noticed zeroExTradeData is fully lender-controlled and the only validation is a balance-delta != 0 check, which can be satisfied by an attacker callback injecting a tiny amount of target token.
**Exploitation:** Lender claims the borrower's escrowed revenue token via spigot.claimEscrow, swaps it through a malicious 0x trade target that pays ETH to the attacker contract, and the receive() callback transfers a minimal creditToken amount to SpigotedLine so the balance-delta check passes; borrower's debt is repaid only by the dust amount while lender keeps the swap proceeds.
**Insight:** When a swap's output is validated only by a balance delta, an attacker-controlled swap target can inject a dust amount of the target token during the callback to satisfy the check while routing real proceeds elsewhere; look for user-supplied swap calldata with weak post-trade accounting.
