Skip to content
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

Restless Magenta Mallard - Liquidator can acquire collateral assets for free or significantly less. #67

Open
sherlock-admin2 opened this issue Dec 10, 2024 · 0 comments

Comments

@sherlock-admin2
Copy link

sherlock-admin2 commented Dec 10, 2024

Restless Magenta Mallard

High

Liquidator can acquire collateral assets for free or significantly less.

Summary

Under function liquidateDefaultedLoanWithIncentive, the liquidator can pay zero due to the following code. Look at line 730, the value to transfer can be zero if tokensToGiveToSender is equal to amountDue.

File: LenderCommitmentGroup_Smart.sol
721:         } else { // if minamount difference is less than or equal to zero
722:           
723:            
724:             uint256 tokensToGiveToSender = abs(minAmountDifference);// returns 1 if x is negative 1, return zero if zero
725: 
726:            
727:             IERC20(principalToken).safeTransferFrom(
728:                 msg.sender,
729:                 address(this),
730:                 amountDue - tokensToGiveToSender // this can be zero if tokenstogivetosender is equal to amount due 
731:             );

Then, let's illustrate on how this can be possible. We need to first study the function of minamountdifference (see below) in which this will act as multiplier. As you can see, there is a chance this can result of -100% of amount due. Look at line 822-825. If amount due is 100, this function can result to -100.

File: LenderCommitmentGroup_Smart.sol
801:     function getMinimumAmountDifferenceToCloseDefaultedLoan(
802:         uint256 _amountOwed, // let say 1
803:         uint256 _loanDefaultedTimestamp
804:     ) public view virtual returns (int256 amountDifference_) {
805:         require(
806:             _loanDefaultedTimestamp > 0,
807:             "Loan defaulted timestamp must be greater than zero"
808:         );
809:         require(
810:             block.timestamp > _loanDefaultedTimestamp,
811:             "Loan defaulted timestamp must be in the past"
812:         );
813: 
814:         uint256 secondsSinceDefaulted = block.timestamp -
815:             _loanDefaultedTimestamp;
816: 
817:         //this starts at 764% and falls to -100% 
818:         int256 incentiveMultiplier = int256(86400 - 10000) -
819:             int256(secondsSinceDefaulted);
820: 
821:         if (incentiveMultiplier < -10000) {
822:             incentiveMultiplier = -10000;
823:         }
824: 
825:         amountDifference_ =
826:             (int256(_amountOwed) * incentiveMultiplier) /
827:             int256(10000); 
828:     }

Then let's go back again at this code snippet below, remember the result is -100 amount due for minamount difference, this can be turn positive in line 724, and then will deducted in line 730 (100-100 = 0). So the value of transfer is zero. Simply put the liquidator able to acquire collateral for free.

File: LenderCommitmentGroup_Smart.sol
721:         } else { // if minamount difference is less than or equal to zero
722:           
723:            
724:             uint256 tokensToGiveToSender = abs(minAmountDifference);// returns 1 if x is negative 1, return zero if zero
725: 
726:            
727:             IERC20(principalToken).safeTransferFrom(
728:                 msg.sender,
729:                 address(this),
730:                 amountDue - tokensToGiveToSender // this can be zero if tokenstogivetosender is equal to amount due 
731:             );

Root Cause

The root cause pertain to the formula below in line 730, it simply allows the amountdue to be reduce to zero and transfer zero tokens. The tokenstogivetosender computation should be revise also and not allow to deduct significantly to the amount due.

File: LenderCommitmentGroup_Smart.sol
721:         } else { // if minamount difference is less than or equal to zero
722:           
723:            
724:             uint256 tokensToGiveToSender = abs(minAmountDifference);// returns 1 if x is negative 1, return zero if zero
725: 
726:            
727:             IERC20(principalToken).safeTransferFrom(
728:                 msg.sender,
729:                 address(this),
730:                 amountDue - tokensToGiveToSender // this can be zero if tokenstogivetosender is equal to amount due 
731:             );

The getMinimumAmountDifferenceToCloseDefaultedLoan computation should also be revise and not allow to fall to -100%. The allowed discount should be minimal only like 1-10% of amount due.

817:         //this starts at 764% and falls to -100% 
818:         int256 incentiveMultiplier = int256(86400 - 10000) -
819:             int256(secondsSinceDefaulted);
820: 
821:         if (incentiveMultiplier < -10000) {
822:             incentiveMultiplier = -10000;
823:         }
824: 

Internal pre-conditions

  1. Liquidator need to execute liquidation at the point since default in which the value of minamountdifference is significant negative value of amount due. So execution can be at range of 85,400-86,400 seconds since default time. If the execution is at exact 86,400 seconds since default, 100% guaranteed that the value transfer or payment by liquidator is zero.

External pre-conditions

No response

Attack Path

This can be the scenario. Let's say the amount due is 100 tokens. Please be reminded i did not include here the protocol fees to simplify the liquidator payment
image

  1. At initial phase of liquidation, 864 is the total payment due to high multiplier
  2. Decrease of multiplier , decrease also of total payment due
  3. The amount difference is negative, so the else statement in liquidation function will trigger. This will give discount to total amount due.
  4. If the liquidator execute liquidation at final second of 86400, which means 100% negative of amount due, therefore zero payment.

Impact

The liquidator can acquire the collateral assets for free or significantly less in which the lenders will receive nothing or very minimal in exchange.

PoC

No response

Mitigation

Revise the formula in getMinimumAmountDifferenceToCloseDefaultedLoan which should not give significant discount to the amount due. The allowed discount should be minimal only like 1-10% of amount due.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant