# denial of service

SavingsAccountUtil.transferTokens used msg.value instead of _amount, so ETH withdrawals paid the caller's own msg.value and burned their liquidity tokens, permanently losing funds.

- Payout: Audit contest
- Severity: high
- Program: Sublime
- Found by: certora
- Disclosed: 2022-02-14
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-12-sublime-findings/issues/154
- Library page: https://bugbountylibrary.com/r/c4%3A2021-12-sublime%3AH-03
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Pool.sol withdrawLiquidity / SavingsAccountUtil.transferTokens
**Root cause:** transferTokens forwards msg.value of the calling function rather than the _amount argument, so when the borrow token is address(0) the ETH sent equals the caller's msg.value, not the liquidity being withdrawn.
**Steps:**
1. Call `withdrawLiquidity` on Pool.sol with borrow token = address(0) (ETH)
2. Pool calls `SavingsAccountUtil.transferTokens(msg.sender, msg.value)` internally
3. Caller receives back only their own msg.value while liquidity tokens are burned
4. Funds remain stuck; caller cannot recover withdrawn liquidity
**How found:** Code review of Pool.sol line 645 and SavingsAccountUtil.transferTokens, noticing msg.value is only valid in external payable calls and is wrong inside an internal helper.
**Exploitation:** Any user withdrawing ETH liquidity triggers the internal transferTokens which refunds their own msg.value instead of the withdrawn amount; their LP tokens are burned, so the liquidity is permanently lost to them.
**Insight:** In internal/library transfer helpers, never reference msg.value — it reflects the outer call's value, not the intended amount; audit any payable helper that forwards msg.value for ETH paths.
