<!-- canonical: https://0xsimao.com/findings/autonomint-withdraw-downside-misscalculate-fees -->

# `borrowing::withdraw()` at a loss will increase downside protected and misscalculate option fees

Crit/High · Sherlock · Hedged stablecoin · 4th December 2024

Finding H-17 of the Autonomint competition.

- Protocol: https://audits.sherlock.xyz/contests/569
- Report: /reports/autonomint
- Codebase: https://github.com/0xsimao/2024-11-autonomint/tree/0d324e04d4c0ca306e1ae4d4c65f0cb9d681751b
- Source: https://github.com/sherlock-audit/2024-11-autonomint-judging/issues/757

---

### Summary

`borrowing::withdraw()` at a loss increases the downside protected, [here](https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/lib/BorrowLib.sol#L873-L875). Then, whenever someone deposits to borrow, option fees are [added](https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/lib/BorrowLib.sol#L731) to the cumulative rate, which is [calculated](https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/Core_logic/CDS.sol#L680) based on `omniChainData.totalCdsDepositedAmountWithOptionFees - omniChainData.downsideProtected`.
As it calculates the rate based on a decreased amount, but the rate is then multiplied by the full amount checkpointed at the cds deposit (normalized), extra option fees will be given to cds depositors.

### Root Cause

In `CDS.sol:680`, downside protected is subtracted from `totalCdsDepositedAmountWithOptionFees`. 

### Internal pre-conditions

None.

### External pre-conditions

None.

### Attack Path

1. Consider a eth price of 1000 USD / ETH.
2. Cds deposits 1000 USDa.
3. Borrower deposits 1 ETH and borrows 800 USDa.
4. Price drops to 900 USD / ETH.
5. Borrower withdraws, setting downside protected to 100.
Now, assume that the first borrower did not charge option fees, for simplicity, and the rate is 1 (ignore precision).
6. Another borrower deposits, charging 50 USD option fees given by `uint128 percentageChange = _fees / netCDSPoolValue; = 50 / (1000 - 100) = 50 / 900`. `currentCumulativeRate = 1 + 50 / 900 = 950 / 900`. [Here](https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/Core_logic/CDS.sol#L680) is the downsideProtection subtracted and the percentage calculation [here](https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/lib/CDSLib.sol#L182).
7. Cds depositor withdraws (after borrower withdraws or there is enough ratio), calculating option fees given by `cdsDepositDetails.normalizedAmount * omniChainData.lastCumulativeRate) - cdsDepositDetails.depositedAmount`, where `cdsDepositDetails.normalizedAmount = 1000 / 1 = 1000`, yielding `1000 / 1 * 950 / 900 - 1000 =  55.555`, more than the 50 USD option fees.

### Impact

Cds depositors gets more option fees than it should, stealing USDa from other users in the protocol, such as other cds depositors that will not be able to withdraw due to lack of liquidity.

### PoC

See the calculations above.

### Mitigation

The downside protection must not be taken into account when calculating the option fees.

---

Related findings:

- [Liquidating maturies with unassigned earnings will not take into account floating assets increase leading to loss of funds](https://0xsimao.com/findings/exactly-protocol-update-staking-contract-ii-liquidating-maturies-unassigned-floating): Exactly Protocol Update - Staking Contract
- [`Vault::withdraw()` withdraws too much liquidity leading to idle capital and loss of fees](https://0xsimao.com/findings/yieldoor-withdraw-withdraws-capital-fees): Yieldoor
- [`burnSharesToWithdrawEarnings` burns before math, causing the share value to increase](https://0xsimao.com/findings/teller-finance-burn-shares-withdraw-share): Teller Finance
- [Malicious users could lock in the NAV/Share of the DV to cause the loss of fees](https://0xsimao.com/findings/tokemak-lock-nav-share-fees): Tokemak
