Skip to content

Redeemers will receive less collateral than expected if function completeRedemptions() is called with empty refundees list #312

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
code423n4 opened this issue Jan 17, 2023 · 2 comments
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-325 satisfactory satisfies C4 submission criteria; eligible for awards

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2023-01-ondo/blob/f3426e5b6b4561e09460b2e6471eb694efdd6c70/contracts/cash/CashManager.sol#L720

Vulnerability details

Impact

Function completeRedemptions() is used by admin account to distribute collateral to users and also to refund redemption requests if the redemption cannot be serviced.

function completeRedemptions(
  address[] calldata redeemers,
  address[] calldata refundees,
  uint256 collateralAmountToDist,
  uint256 epochToService,
  uint256 fees
) external override updateEpoch onlyRole(MANAGER_ADMIN) {
  _checkAddressesKYC(redeemers);
  _checkAddressesKYC(refundees);
  if (epochToService >= currentEpoch) {
    revert MustServicePastEpoch();
  }
  // Calculate the total quantity of shares tokens burned w/n an epoch
  
  // @audit Wrong value of quantityBurned if `refundees` list is empty
  uint256 refundedAmt = _processRefund(refundees, epochToService);
  uint256 quantityBurned = redemptionInfoPerEpoch[epochToService]
    .totalBurned - refundedAmt; 
  uint256 amountToDist = collateralAmountToDist - fees;
  _processRedemption(redeemers, amountToDist, quantityBurned, epochToService);
  collateral.safeTransferFrom(assetSender, feeRecipient, fees);
  emit RedemptionFeesCollected(feeRecipient, fees, epochToService);
}

Since in each epoch there might be many users send redemption requests, so to avoid breaking block gas limit, sponsor confirmed that each epoch will require multiple calls to function completeRedemptions() with collateralAmountToDist stay constant in every call.

If function completeRedemptions() is called with empty refundees in any TX, every redeemers in that call will receive less collateral back than expected

Proof of Concept

Consider the scenario

  1. Assuming Alice, Bob both sended redemption requests in epoch X with following amount: 100, 100. So totalBurned = 200.
  2. Admin does the redemption and only requests of Alice can be serviced, bob's request will be refunded. And let's assume exchange rate is 1-1 and fees = 0
  3. Admin call completeRedemptions([], [Bob], 100, X, 0) first to process all refuding. Bob will be minted 100 CASH back.
  4. Admin call completeRedemptions([Alice], [], 100, X, 0), in this calls, because refundees list is empty, so quantityBurned will be calculated wrongly
quantityBurned = totalBurned - 0 = 200
amountToDist = 100
Alice_received = (100 * 100 / 200) = 50

So Alice only receive 50 instead of 100 collateral token back.

Tools Used

Manual Review

Recommended Mitigation Steps

Consider adding a totalRefundAmt input param instead of calculating it using function _processRefund() in every call

@code423n4 code423n4 added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Jan 17, 2023
code423n4 added a commit that referenced this issue Jan 17, 2023
@c4-judge
Copy link
Contributor

trust1995 marked the issue as duplicate of #325

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Jan 23, 2023
@c4-judge
Copy link
Contributor

trust1995 marked the issue as satisfactory

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-325 satisfactory satisfies C4 submission criteria; eligible for awards
Projects
None yet
Development

No branches or pull requests

2 participants