Ondo Finance - 0xCiphky'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: 11/72

Findings: 2

Award: $498.91

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Findings Information

🌟 Selected for report: carrotsmuggler

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

Labels

bug
2 (Med Risk)
satisfactory
:robot:_19_group
duplicate-142

Awards

490.6256 USDC - $490.63

External Links

Lines of code

https://github.com/code-423n4/2024-03-ondo-finance/blob/be2e9ebca6fca460c5b0253970ab280701a15ca1/contracts/ousg/ousgInstantManager.sol#L388 https://github.com/code-423n4/2024-03-ondo-finance/blob/be2e9ebca6fca460c5b0253970ab280701a15ca1/contracts/ousg/ousgInstantManager.sol#L599

Vulnerability details

Vulnerability details:

The OUSGInstantManager contract implements a minimum redemption amount that is enforced in the _redeem function, dictating the minimum amount a user can redeem at one time. This limit can be modified at any time by an admin with the CONFIGURER_ROLE using the setMinimumRedemptionAmount function.

    function _redeem(uint256 ousgAmountIn) internal returns (uint256 usdcAmountOut) {
        ...
        require(
            usdcAmountToRedeem >= minimumRedemptionAmount, "OUSGInstantManager::_redeem: Redemption amount too small"
        );
        ...
    }

However, this can be problematic because users having deposited enough or left in an amount over the minimum could be forced to now make an extra deposit to be able to redeem their shares if the minimum is raised. Since there is a fee paid in deposits this will mean users will end up paying an extra amount to redeem their funds. This can also be abused by an admin to get users to pay more fees or be unable to redeem their shares.


    function setMinimumRedemptionAmount(uint256 _minimumRedemptionAmount) external override onlyRole(CONFIGURER_ROLE) {
        require(_minimumRedemptionAmount >= FEE_GRANULARITY, "setMinimumRedemptionAmount: Amount too small");
        emit MinimumRedemptionAmountSet(minimumRedemptionAmount, _minimumRedemptionAmount);
        minimumRedemptionAmount = _minimumRedemptionAmount;
    }

Impact:

  • Severity: Low/Medium. This will cause a loss of funds for users as they will have to pay an extra fee.
  • Likelihood: Low/Medium. This can be inadvertently done when an admin changes the minimumRedemptionAmount.

Tools Used:

  • Manual analysis

Recommendation:

Set a reasonable ceiling for what the minimumRedemptionAmount can be set to, that way even if the minimum amount is increased users can have an idea of the maximum it can be set. Furthermore, this can’t be abused by an admin to get a user to pay more fees.

Assessed type

Other

#0 - c4-pre-sort

2024-04-04T23:51:25Z

0xRobocop marked the issue as duplicate of #142

#1 - c4-judge

2024-04-09T11:27:44Z

3docSec marked the issue as satisfactory

Lines of code

https://github.com/code-423n4/2024-03-ondo-finance/blob/be2e9ebca6fca460c5b0253970ab280701a15ca1/contracts/ousg/ousgInstantManager.sol#L278 https://github.com/code-423n4/2024-03-ondo-finance/blob/be2e9ebca6fca460c5b0253970ab280701a15ca1/contracts/ousg/ousgInstantManager.sol#L290

Vulnerability details

Vulnerability details:

The OUSGInstantManager contract implements a mint limit that is enforced in the _mint function, dictating how much USDC can be transferred for minting in a specified duration. The function charges an instant mint fee that is deducted from the usdcAmountIn before minting, but the fee is not actually minted. Instead, it is directly transferred to the usdcReceiver address. When incrementing the mint limit through the _checkAndUpdateInstantMintLimit function the usdcAmountIn value is used.

    function _mint(uint256 usdcAmountIn, address to) internal returns (uint256 ousgAmountOut) {
        ...
        _checkAndUpdateInstantMintLimit(usdcAmountIn);
        if (address(investorBasedRateLimiter) != address(0)) {
            investorBasedRateLimiter.checkAndUpdateMintLimit(msg.sender, usdcAmountIn);
        }
	...
        uint256 usdcfees = _getInstantMintFees(usdcAmountIn);
        uint256 usdcAmountAfterFee = usdcAmountIn - usdcfees;
        ...
        // Transfer USDC
        if (usdcfees > 0) {
            usdc.transferFrom(msg.sender, feeReceiver, usdcfees);
        }
        usdc.transferFrom(msg.sender, usdcReceiver, usdcAmountAfterFee);
	...
        ousg.mint(to, ousgAmountOut);
    }

This means that the mint limit is incorrectly being incremented by the fee amount as well, making it impossible for the minted tokens to reach the mint limit for a specific duration, even if there is enough demand.

Impact:

  • Severity: Low. The mint limit will not be able to be reached for a specific duration.
  • Likelihood: High. This issue will occur for every cycle.

Tools Used:

  • Manual analysis

Recommendation:

Modify the _mint function to call the _checkAndUpdateInstantMintLimit function with the usdcAmountAfterFee instead of usdcAmountIn. This way, only the tokens being minted will be accounted for in the mint limit calculation.

    function _mint(uint256 usdcAmountIn, address to) internal returns (uint256 ousgAmountOut) {
        ...
        uint256 usdcfees = _getInstantMintFees(usdcAmountIn);
        uint256 usdcAmountAfterFee = usdcAmountIn - usdcfees;
        
        _checkAndUpdateInstantMintLimit(usdcAmountAfterFee); // change here
        ...
    }

Assessed type

Other

#0 - c4-pre-sort

2024-04-04T05:18:12Z

0xRobocop marked the issue as duplicate of #47

#1 - c4-judge

2024-04-09T09:53:14Z

3docSec changed the severity to QA (Quality Assurance)

#2 - c4-judge

2024-04-09T09:53:29Z

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