Open c4-bot-10 opened 6 months ago
0xRobocop marked the issue as duplicate of #156
3docSec marked the issue as satisfactory
3docSec marked the issue as not a duplicate
3docSec marked the issue as primary issue
3docSec marked the issue as selected for report
I'm quoting from the warden's description:
However, these functions do not have any type of slippage control since the amount of tokens received by the user is determined by an interaction with an oracle, meaning that the amount received in return may vary indefinitely while the request is waiting to be executed.
I believe this is wrong, the amount to receive will never vary indefinitely as mentioned, because Oracle doesn't allow %1 price change when updating the price. So the user may still view the current OUSG price and can still determine the outcome of the transaction.
This means that the user has no way to predict how many OUSG they will get back at the moment of burning shares, as the price could be updated while the request is in the mempool.
This is very unlikely to happen, the price is updated once every 23 hours at best scenario. So an unwrap/burn transaction encounter the oracle::setPrice
in the mempool is very unlikely. Even if such rare cases happen, the price won't change too much as the oracle doesn't allow a change slippage of %1
☝️ this is a very good point.
In summary:
All of the above give factual proof that slippage is negligible in this context. 💯 @Brivan-26
Update, it's actually 2% in RWAOracleExternalComparisonCheck
but the argument stands.
3docSec changed the severity to QA (Quality Assurance)
3docSec marked the issue as grade-b
3docSec marked the issue as not selected for report
Hey @3docSec, 2% may seem small, but it's not negligible. A significant number of users are likely to utilize both redeemRebasingOUSG and mintRebasingOUSG, with a minimum requirement of 50k for redemption and 100k for minting. Hence, a 2% loss translates to 1k during redemption and 2k during minting, posing a non-trivial risk of asset loss, warranting a medium severity i believe.
Lines of code
https://github.com/code-423n4/2024-03-ondo-finance/blob/be2e9ebca6fca460c5b0253970ab280701a15ca1/contracts/ousg/rOUSG.sol#L624-L640
Vulnerability details
Summary
The
ROUSG.burn()
function allowsadmin
to burnrOUSG
tokens from any_account
thereby gettingOUSG
in return. TheROUSG.unwrap()
on the other hand is called by users to unwrap theirrOUSG
tokens.However, these functions do not have any type of
slippage control
since the amount oftokens
received by the user is determined by an interaction with anoracle
, meaning that the amount received in return may vary indefinitely while the request is waiting to be executed.Also the users will have no defense against price manipulation attacks, if they were to be found after the protocol's deployment.
Proof of Concept
Instance 1:
ROUSG.burn()
The
ousgSharesAmount
to be burned is determined by thegetSharesByROUSG()
function of the same contract:As can be observed, this function uses
oracle
interaction through the division bygetOUSGPrice()
. ThegetOUSGPrice()
function queries the externaloracle
for the asset price:To determine the amount of
OUSG
to be received after share burning, theousgSharesAmount
calculated above is divided byOUSG_TO_ROUSG_SHARES_MULTIPLIER
:This means that the user has no way to predict how many
OUSG
they will get back at the moment of burningshares
, as the price could be updated while the request is in the mempool.Instance 2:
ROUSG.unwrap()
ousgSharesAmount
is detamined by callinggetSharesByROUSG()
:which also uses
getOUSGPrice()
in division as above. This invokes the externaloracle
to get the asset price:And finally to determine the amount of
OUSG
to be received after unwrapping, theousgSharesAmount
calculated above is divided byOUSG_TO_ROUSG_SHARES_MULTIPLIER
:Similarly, the user has no way to predict how many
OUSG
they will get back at the moment of unwrapping, as the price could be updated while the request is in the mempool.Tools Used
Manual Review
Recommended Mitigation Steps
Add additional parameter that could be added in these functions, to decide the
minimum amount of tokens to be received
, with a relative check afterburning/unwrapping.
Assessed type
Oracle