Ondo Finance - carrotsmuggler's results

Institutional-Grade Finance, Now Onchain.

General Information

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

Ondo Finance

Findings Distribution

Researcher Performance

Rank: 8/72

Findings: 2

Award: $646.09

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: carrotsmuggler

Also found by: 0xCiphky, 0xmystery, Breeje, dvrkzy, radev_sw

Labels

bug
2 (Med Risk)
primary issue
satisfactory
selected for report
sponsor disputed
sufficient quality report
:robot:_19_group
M-03

Awards

637.8133 USDC - $637.81

External Links

Lines of code

https://github.com/code-423n4/2024-03-ondo-finance/blob/78779c30bebfd46e6f416b03066c55d587e8b30b/contracts/ousg/ousgInstantManager.sol#L402-L405

Vulnerability details

Impact

The InstantManager contract restricts deposits and withdrawals to certain minimum amounts. Users can deposit a minimum of 100k USDC tokens, and withdraw a minimum of 50k USDC tokens.

The issue is that the minimum withdrawal limit can lead to users losing access to part of their funds. Say a user deposits 100k USDC tokens and then later withdraws 60k USDC tokens. Now, the user only has 40kUSDC worth holdings in their account, and cannot withdraw the full amount. This is because it falls below the minimum withdrawal limit of 50k USDC tokens. The user is now stuck with 40k USDC tokens in their account, and cannot withdraw them.

The only option the user has is to deposit 100k USDC more, and then withdraw the whole 140k USDC amount. This will incur fees on the extra 100k USDC the user brings as well. Thus this is a medium severity issue.

Proof of Concept

The scenario can be recreated in the following steps:

  1. User ALICE deposits 100k USDC tokens.
  2. User ALICE withdraws 60k USDC tokens.
  3. User ALICE tries to withdraw 40k USDC tokens. The contract reverts, as the amount is below the minimum withdrawal limit of 50k USDC tokens.

Tools Used

Manual Review

Allow users to remove all their funds from the contract even if it is below the minimum limit. Since the protocol now uses a more liquid system such as the BUIDL token, this should be possible and should not affect the protocol's functioning.

Assessed type

Other

#0 - c4-pre-sort

2024-04-04T23:49:50Z

0xRobocop marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-04-04T23:49:53Z

0xRobocop marked the issue as primary issue

#2 - 0xRobocop

2024-04-04T23:54:56Z

The worst impact is a temporary DoS over some users funds, admin can always change the limit. Leaving for sponsor review.

#3 - cameronclifton

2024-04-05T22:14:42Z

This is an obvious design decision and also assumes that there is no other ways for investors to redeem OUSG/rOUSG, which is not incorrect.

#4 - c4-sponsor

2024-04-05T22:14:44Z

cameronclifton (sponsor) disputed

#5 - 3docSec

2024-04-09T11:25:57Z

I acknowledge this behavior is a design decision.

I however would keep this as a valid medium for an audit report, because:

  • there is an availability impact for users, in a condition that they did not necessarily have to purposely create for themselves
  • users can decide to still withdraw for a loss in fees "for minting more to redeem all"
  • the report highlights what I find to be a very reasonable mitigation - which could be the behavior users reasonably expect:

Allow users to remove all their funds from the contract even if it is below the minimum limit.

this mitigation seems feasible and difficult to exploit for systematic, abusive bypasses of minimumRedemptionAmount, because both OUSG and rOUSG have a KYC requirement on token holders

#6 - c4-judge

2024-04-09T11:27:13Z

3docSec marked the issue as selected for report

#7 - c4-judge

2024-04-09T11:27:25Z

3docSec marked the issue as satisfactory

#8 - cameronclifton

2024-04-10T16:45:14Z

This finding is a feature suggestion to remove the minimum redemption amount. Having explicit minimum redemption and subscription amounts clearly implies that there could be conditions in which users would have a balance below the minimum and be unable to transact. Users are made well aware of these minimums. Users are also able to contact us directly should they need to redeem via other mechanisms.

Regarding the mitigation suggestion: Allow users to remove all their funds from the contract even if it is below the minimum limit. Since the protocol now uses a more liquid system such as the BUIDL token, this should be possible and should not affect the protocol's functioning. - I don't understand how this is can be assumed to be a reasonable mitigation without knowing the reason for why the minimum subscription and redemption amounts exists.

#9 - Henrychang26

2024-04-12T08:27:33Z

In setMinimumRedemptionAmount(), minimumRedemptionAmount can be set as low as FEE_GRANULARITY == 10_000. The max amount that can potentially be locked is 9,999 which is less than $0.1 approx $0.09999

To provide more context: In setMinimumDepositAmount(), minimumDepositAmount can also be set as low as FEE_GRANULARITY. The highest possible additional fee that may incur to put user over the minimumRedemptionAmount in order to redeem(), is 1.99%. $0.1 x 0.0199 = $0.00199

#10 - thebrittfactor

2024-04-23T18:44:36Z

Per further discussion with the sponsor team, adding this final input on their behalf for inclusion in the report:

We will not be removing minimum redemption requirement from the smart contract as there are other means in which users can redeem OUSG or rOUSG tokens from Ondo Finance.

Lines of code

https://github.com/code-423n4/2024-03-ondo-finance/blob/78779c30bebfd46e6f416b03066c55d587e8b30b/contracts/ousg/ousgInstantManager.sol#L479-L48

Vulnerability details

Impact

The InstantManager contract has a hardcoded MINIMUM_OUSG_PRICE value of 105e18. The current price of OUSG tokens on coingecko is 105.63 USD, which is only 0.6% above the hardcoded value. The assumption is that the value of the token does not ever fall below 105 USD, below which the oracle is assumed to be misbehaving, and thus all operations are stopped.

function getOUSGPrice() public view returns (uint256 price) {
        (price,) = oracle.getPriceData();
        require(price > MINIMUM_OUSG_PRICE, "OUSGInstantManager::getOUSGPrice: Price unexpectedly low");
    }

The issue is that this is a very small margin of error. The funds in the contract will be deposited to the BUIDL fund. The contract already assumes that some USDC will remain unused in the contract, thus the APY realized by OUSG will be lower than the BUIDL fund.

Te BUIDL fund, according to the details available here, will invest 100% of its total assets in cash, U.S. Treasury bills, notes and other obligations issued or guaranteed as to principal and interest by the U.S. Treasury, and repurchase agreements secured by such obligations or cash. The Fund will invest, in both the primary and secondary markets, in U.S. Treasury bills, notes or other obligations that mature in three months or less from the settlement of the purchase.

While cash, notes and treasury bills are saef and can be assumed to never go down in value, repo (repurchase agreements) on secondary markets can have some level of risk associated with it, albeit very low. So there is a possibility that in the short term the fund can lose some value, enough to trigger the MINIMUM_OUSG_PRICE check on the protocol here built on top of it. This would then lead to a DOS of the protocol, since all price operations will stop.

Proof of Concept

Assume the blackrock fund loses 0.6% of its value due to some unforseen circumstances. That will be enough to trigger the MINIMUM_OUSG_PRICE check and stop all operations on the protocol. It is very unlikely that the fund will lose this value in the long term, however volatility in repo agreements in the short term are definitely possible.

Tools Used

Manual Review

Consider making the hardcoded value programmable. Or a lower more conservative limit like 104 USD would be more appropriate, which was the price of OUSG at the beginning of this year.

Assessed type

Other

#0 - c4-pre-sort

2024-04-04T05:51:42Z

0xRobocop marked the issue as duplicate of #245

#1 - c4-judge

2024-04-09T13:01:21Z

3docSec changed the severity to QA (Quality Assurance)

#2 - c4-judge

2024-04-09T13:02:06Z

3docSec marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter