Platform: Code4rena
Start Date: 29/03/2024
Pot Size: $36,500 USDC
Total HM: 5
Participants: 72
Period: 5 days
Judge: 3docSec
Total Solo HM: 1
Id: 357
League: ETH
Rank: 34/72
Findings: 1
Award: $8.28
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: immeas
Also found by: 0xAkira, 0xCiphky, 0xGreyWolf, 0xJaeger, 0xMosh, 0xabhay, 0xlemon, 0xmystery, 0xweb3boy, Aamir, Abdessamed, Aymen0909, Breeje, DanielArmstrong, DarkTower, Dots, EaglesSecurity, FastChecker, HChang26, Honour, IceBear, JC, K42, Krace, MaslarovK, Omik, OxTenma, SAQ, Shubham, Stormreckson, Tigerfrake, Tychai0s, VAD37, ZanyBonzy, albahaca, arnie, ast3ros, asui, b0g0, bareli, baz1ka, btk, caglankaan, carrotsmuggler, cheatc0d3, dd0x7e8, grearlake, igbinosuneric, jaydhales, kaden, kartik_giri_47538, m4ttm, ni8mare, niser93, nonn_ac, oualidpro, pfapostol, pkqs90, popeye, radev_sw, samuraii77, slvDev, zabihullahazadzoi
8.2807 USDC - $8.28
https://github.com/code-423n4/2024-03-ondo-finance/blob/main/contracts%2Fousg%2FousgInstantManager.sol#L388-L400 https://github.com/code-423n4/2024-03-ondo-finance/blob/main/contracts%2Fousg%2FousgInstantManager.sol#L699-L705
Users first deposit/mint USDC
and get an equal amount of OUSG
then can be wrapped into rOUSG
to earn rebase interests.
However when the user wants to redeem the OUSG
for USDC
due to the difference in magnitude between amountE36
and decimalsMultiplier
rounding issue occurs which leads to loss of funds for the user.
the amountE36
represents the product of the ousgAmountBurned
and price
, which is relatively small compared to the large value of decimalsMultiplier
.
Financial loss for the user
Users redeem by calling redeem
function redeem( uint256 ousgAmountIn ) external override nonReentrant whenRedeemNotPaused returns (uint256 usdcAmountOut) { require( ousg.allowance(msg.sender, address(this)) >= ousgAmountIn, "OUSGInstantManager::redeem: Insufficient allowance" ); ousg.transferFrom(msg.sender, address(this), ousgAmountIn); usdcAmountOut = _redeem(ousgAmountIn); emit InstantRedemptionOUSG(msg.sender, ousgAmountIn, usdcAmountOut); } `` Which inturn calls `_redeem` with the `OUSG` amount being withdrawn by the user https://github.com/code-423n4/2024-03-ondo-finance/blob/main/contracts%2Fousg%2FousgInstantManager.sol#L388-L400 ```solidity function _redeem( uint256 ousgAmountIn ) internal returns (uint256 usdcAmountOut) { require( IERC20Metadata(address(usdc)).decimals() == 6, "OUSGInstantManager::_redeem: USDC decimals must be 6" ); require( IERC20Metadata(address(buidl)).decimals() == 6, "OUSGInstantManager::_redeem: BUIDL decimals must be 6" ); uint256 ousgPrice = getOUSGPrice(); uint256 usdcAmountToRedeem = _getRedemptionAmount(ousgAmountIn, ousgPrice);
Then the _getRedemptionAmount
calculates the amount of USDC
the user recieves.
https://github.com/code-423n4/2024-03-ondo-finance/blob/main/contracts%2Fousg%2FousgInstantManager.sol#L699-L705
function _getRedemptionAmount( uint256 ousgAmountBurned, uint256 price ) internal view returns (uint256 usdcOwed) { uint256 amountE36 = ousgAmountBurned * price; usdcOwed = _scaleDown(amountE36 / 1e18); }
SupposeousgAmountBurned
is 1,000,000 OUSG
tokens and price is $0.001 USDC
per OUSG
token.
Calculate the amount in E36 (E36 denotes 10^36):
amountE36 = ousgAmountBurned * price = 1,000,000 * 0.001 = 1,000`
scale down amountE36
by decimalsMultiplier
, which is 1 trillion:
scaledAmount = amountE36 / decimalsMultiplier = 1,000 / 1,000,000,000,000 = 0
decimalsMultiplier ` is calculated as follows
decimalsMultiplier = 10 ** (IERC20Metadata(_ousg).decimals() - IERC20Metadata(_usdc).decimals());
decimalsMultiplier = 10 ** (IERC20Metadata(_ousg).decimals() - IERC20Metadata(_usdc).decimals()) = 10 ** (18 - 6) = 10 ** 12 = 1,000,000,000,000
In this example, after scaling down, the result is rounded down to 0 due to the significant difference in magnitudes between amountE36
and decimalsMultiplier
.
scaledAmount = amountE36 / decimalsMultiplier = 1,000 / 1,000,000,000,000 = 0
Which indicates smaller values will be rounded down to zero leading to loss of precision in the calculation
Manual Review
consider using fixed-point arithmetic or external library for precise calculations.
Math
#0 - c4-pre-sort
2024-04-05T02:55:05Z
0xRobocop marked the issue as duplicate of #246
#1 - 0xRobocop
2024-04-05T02:55:22Z
0.001 USDC per OUSG is not realistic.
#2 - c4-judge
2024-04-09T12:26:57Z
3docSec changed the severity to QA (Quality Assurance)
#3 - c4-judge
2024-04-09T12:27:25Z
3docSec marked the issue as grade-b