<!-- canonical: https://0xsimao.com/findings/autonomint-overpays-usda-downside-protection -->

# The user overpays the USDA amount for downside protection while withdrawing

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

Finding H-32 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/1004

---

## Summary

The protocol provides >= 20% downside protection on the collateral depending on the volatility of collateral. However, users should pay USDA amount for downside protection, while withdrawing and protocol doesn't cover downside protection.
## Root Cause

In the [BorrowLib.sol](https://github.com/sherlock-audit/2024-11-autonomint/blob/0d324e04d4c0ca306e1ae4d4c65f0cb9d681751b/Blockchain/Blockchian/contracts/lib/BorrowLib.sol#L867) `withdraw()` function, users return usda and receive collateral. Although protocol covers 20% downside protection, users should return amount of `downsideProtected`.

Let's see line 867 and line 878, and calculate total usda amount users should hold: burnValue + (borrowerDebt - depositDetail.borrowedAmount) + discountedCollateral = depositDetail.borrowedAmount - discountedCollateral + (borrowerDebt - depositDetail.borrowedAmount) + discountedCollateral = borrowerDebt.

As result, users should return full debt(borrowerDebt) and the protocol doesn't cover `downsideProtected`.

```solidity
    function withdraw(
        ITreasury.DepositDetails memory depositDetail,
        IBorrowing.BorrowWithdraw_Params memory params,
        IBorrowing.Interfaces memory interfaces
    ) external returns (IBorrowing.BorrowWithdraw_Result memory) {

        ...

        // Calculate the USDa to burn
867     uint256 burnValue = depositDetail.borrowedAmount - discountedCollateral;

        // Burn the USDa from the Borrower
        bool success = interfaces.usda.burnFromUser(msg.sender, burnValue);
        if (!success) revert IBorrowing.Borrow_BurnFailed();

        ...

        //Transfer the remaining USDa to the treasury
878     bool transfer = interfaces.usda.transferFrom(
            msg.sender,
            address(interfaces.treasury),
            (borrowerDebt - depositDetail.borrowedAmount) + discountedCollateral
        );
        if (!transfer) revert IBorrowing.Borrow_USDaTransferFailed();
        ...
    }
```


## Internal pre-conditions

## External pre-conditions

## Attack Path

## Impact

Users should return usda amount for downside protection and the protocol doesn't cover downside protection.

## Mitigation

Deduct downside protection.

```diff
    function withdraw(
        ITreasury.DepositDetails memory depositDetail,
        IBorrowing.BorrowWithdraw_Params memory params,
        IBorrowing.Interfaces memory interfaces
    ) external returns (IBorrowing.BorrowWithdraw_Result memory) {

        ...

        // Calculate the USDa to burn
        uint256 burnValue = depositDetail.borrowedAmount - discountedCollateral;

        // Burn the USDa from the Borrower
        bool success = interfaces.usda.burnFromUser(msg.sender, burnValue);
        if (!success) revert IBorrowing.Borrow_BurnFailed();

        ...

        //Transfer the remaining USDa to the treasury
        bool transfer = interfaces.usda.transferFrom(
            msg.sender,
            address(interfaces.treasury),
-           (borrowerDebt - depositDetail.borrowedAmount) + discountedCollateral
+           (borrowerDebt - depositDetail.borrowedAmount - downsideProtected) + discountedCollateral
        );
        if (!transfer) revert IBorrowing.Borrow_USDaTransferFailed();
        ...
    }
```

---

Related findings:

- [Users redeeming early will withdraw `Ra` without decreasing the amount locked, which will lead to stolen funds when withdrawing after expiry](https://0xsimao.com/findings/cork-protocol-redeeming-withdraw-locked-stolen): Cork Protocol
