# Non terminal tokens received via Balancer batchSwap are not accounted for

Sentiment's BalancerController only registered the final token from Balancer batchSwap, so intermediate tokens received were unaccounted and could trigger premature liquidation.

- Payout: Contest reward
- Severity: high
- Program: Sentiment
- Credited: Bahurum
- Disclosed: 2022-10-31
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2022-11-sentiment-judging/issues/6
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-11-sentiment%3AH-1
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:liquidation

**Target:** BalancerController.sol canBatchSwap / batchSwap integration
**Root cause:** canBatchSwap only records the final output token in tokensIn/tokensOut, ignoring intermediate tokens returned by Balancer batchSwap when per-step amounts leave residual balances.
**Steps:**
1. Call Balancer batchSwap with multiple steps where a later step's amount is less than the prior step's output (e.g. step1: 400 BAL->max WETH, step2: 1 WETH->max USDC).
2. Balancer returns residual WETH plus final USDC to the user.
3. Observe canBatchSwap only registers USDC in tokensIn[], leaving WETH unregistered in the account's asset list.
4. RiskEngine._getBalance() ignores the unregistered WETH, understating collateral and enabling earlier liquidation.
**How found:** Code review of BalancerController's canBatchSwap against Balancer batchSwap semantics; noticed batchSwap can return multiple tokens along the path while the controller only records the final asset, then confirmed with a Foundry test.
**Exploitation:** User performs a legitimate batchSwap with intermediate amounts; residual tokens land in their account but are not tracked, so the risk engine undervalues collateral and liquidators can seize positions sooner than fair.
**Insight:** When integrating DEX routers that return multiple assets (batchSwap, multi-hop), always reconcile against the router's returned assetDeltas array rather than assuming a single in/out token; residual intermediate balances silently break collateral accounting.
