This repository has been archived by the owner on Jul 14, 2024. It is now read-only.
0xadrii - amoMinterBorrow() improperly allows borrowing unclaimedPoolCollateral, breaking protocol functionality #127
Labels
Non-Reward
This issue will not receive a payout
0xadrii
high
amoMinterBorrow() improperly allows borrowing unclaimedPoolCollateral, breaking protocol functionality
Summary
The
amoMinterBorrow()
does not consider the collateral that has been queued for redeems, which potentially makes users unable to access collateral and cause denial of service in some functions.Vulnerability Detail
Ubiquity allows AMO (Automatic Market Operations) minters to borrow the collateral deposited in the protocol in order to make yield on external protocols. In order to allow such functionality,
UbiquityPoolFacet.sol
incorporates anamoMinterBorrow()
function, which internally callsLibUbiquityPool.sol
'samoMinterBorrow()
:As shown in the code snippet,
amoMinterBorrow()
allows any AMO minter to borrow an arbitrarycollateralAmount
amount from Ubiquity’s total deposited collateral.On the other hand, Ubiquity redeem process is split in two steps:
redeemDollar()
, which queues a desired collateral amount to be redeemed and burns the redeemer’s uAD. The queued collateral amount to be redeemed is tracked individually for the redeemer in thepoolStorage.redeemCollateralBalances
mapping, and globally in thepoolStorage.unclaimedPoolCollateral
mapping.collectRedemption()
Once the borrowing and redeeming mechanics are understood, we can acknowledge an issue regarding the amounts allowed to be borrowed in
amoMinterBorrow()
. As mentioned before, an arbitrarycollateralAmount
amount can be borrowed by the AMO minters. The problem with this approach is that borrowing does not consider the currently queued unclaimed pool collaterals. This makes two problems arise:AMO minters are susceptible of leaving the contract without enough funds for redeemers to be able to collect their queued redemptions because no limit is imposed in
amoMinterBorrow()
. This will prevent users from withdrawing their queued collateral, even if the minimum redemption delay has passed.If AMO minters borrow a higher amount than the current
poolStorage.unclaimedPoolCollateral
, minting will be DoS’ed due to usingfreeCollateralBalance()
. Let’s examine thefreeCollateralBalance()
function, which returns the free collateral balance (i.e the amount that can be borrowed by AMO minters):As we can see,
poolStorage.unclaimedPoolCollateral[collateralIndex]
will be substracted from Ubiquity’s current collateral balance(IERC20(poolStorage.collateralAddresses[collateralIndex]).balanceOf(address(this))
). Because AMO minters have no restriction when borrowing, they can leave the contract with a balance smaller than the actual amount stored inpoolStorage.unclaimedPoolCollateral[collateralIndex]
(i. e(IERC20(poolStorage.collateralAddresses[collateralIndex]).balanceOf(address(this))
<poolStorage.unclaimedPoolCollateral[collateralIndex]
). If such situation takes place,freeCollateralBalance()
will always throw an underflow error due to the substraction performed in the function.Given that
freeCollateralBalance()
is used in themintDollar()
function in order to check the pool’s ceiling, if such situation arises, minting will be effectively DoS’ed, rendering a crucial protocol mechanic unusable:Impact
High. It is true that although users are prevented from obtaining their funds after waiting for the redemption delay period, funds are not stuck forever and can be recovered when AMO minters return funds back to the protocol.
However, as stated in this report, this vulnerability can potentially DoS uAD minting, which is a crucial mechanism to keep uAD’s peg to $1. If such operation is DoS’ed, the main goal of the protocol (keeping uAD’s peg with USD) will not be fulfilled, which is actually of HIGH impact.
Proof of Concept
The following proof of concept illustrates how a redeemer won’t be able to collect the amount borrowed by the amo minter. In order to run it, just enter the
ubiquity-dollar/packages/contracts
folder in your terminal and add the function showed below intoUbiquityPoolFacet.t.sol
. Finally, execute the following command to run the PoC:forge test --mt testVuln_amoMinterBorrowAllowsBorrowingUnclaimedPoolCollateral -vv
.Code Snippet
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/facets/UbiquityPoolFacet.sol#L124
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibUbiquityPool.sol#L574-L598
Tool used
Manual Review, foundry
Recommendation
Check the freeCollateralBalance() in amoMinterBorrow() so that AMO minters cannot borrow an amount greater than the actual borrowable amount (amount that considers theunclaimedPoolCollateral):
Duplicate of #1
The text was updated successfully, but these errors were encountered: