Skip to content

Latest commit

 

History

History
79 lines (54 loc) · 3.48 KB

068.md

File metadata and controls

79 lines (54 loc) · 3.48 KB

Mini Plum Pike

Medium

The protocol and users will receive amounts of loan tokens lower than transferred when USDB rebase negatively

Summary

According to the README, 'on Blast it will be USDB and USDC on other prediction markets'. This means USDB will be accepted as loan tokens on Blast and USDC on other blockchains. USDB is a rebasing token and USDC is upgradeable, implying that USDC features can change if there is an upgrade.

PredictDotLoan is not confirming the amount received after every transfer, causing the protocol and the users to receive different amount of tokens from what is transferred if rebasing takes place during the transfer. The protocol will lose fees because of this.

Root Cause

PredictDotLoan::_transferLoanAmountAndProtocolFee and PredictDotLoan::_transferLoanAmountAndProtocolFeeWithoutDeductingFromLoanAmount do not confirm the loan token amount received after fee transfer to the PredictDotLoan::protocolFeeRecipient address and loan value transfer to the lenders and borrowers as shown in the functions below.

https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L889 and

https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L906

Internal pre-conditions

No response

External pre-conditions

USDB negative rebasing happening during any of the transfers. USDC, being upgradeable contract, gets upgraded to fee-on-transfer, rebasing token or any other unpredictable feature is added.

Attack Path

No response

Impact

Protocol will lose fees, lenders will get far less than amount borrowed and borrower will get less than the borrowed amount making it difficult for him to pay back the loan.

PoC

No response

Mitigation

Refactor PredictDotLoan::_transferLoanAmountAndProtocolFee and PredictDotLoan::_transferLoanAmountAndProtocolFeeWithoutDeductingFromLoanAmount as below.

    function _transferLoanAmountAndProtocolFee(
        address from,
        address to,
        uint256 loanAmount
    ) private returns (uint256 protocolFee) {
        protocolFee = (loanAmount * protocolFeeBasisPoints) / 10_000;
+       uint256 userBalanceBefore = LOAN_TOKEN.balanceOf(to);
        LOAN_TOKEN.safeTransferFrom(from, to, loanAmount - protocolFee);
+       require(LOAN_TOKEN.balanceOf(to) - userBalanceBefore == loanAmount - protocolFee, 'Invalid amount');
        if (protocolFee > 0) {
+           uint256 protocolBalanceBefore = LOAN_TOKEN.balanceOf(protocolFeeRecipient);
            LOAN_TOKEN.safeTransferFrom(from, protocolFeeRecipient, protocolFee);
+           require(LOAN_TOKEN.balanceOf(protocolFeeRecipient) - protocolBalanceBefore == protocolFee, 'Invalid amount');
        }
    }

    function _transferLoanAmountAndProtocolFeeWithoutDeductingFromLoanAmount(
        address from,
        address to,
        uint256 loanAmount,
        uint256 protocolFee
    ) private {
+       uint256 userBalanceBefore = LOAN_TOKEN.balanceOf(to);
        LOAN_TOKEN.safeTransferFrom(from, to, loanAmount);
+       require(LOAN_TOKEN.balanceOf(to) - userBalanceBefore == loanAmount, 'Invalid amount');
        if (protocolFee > 0) {
+           uint256 protocolBalanceBefore = LOAN_TOKEN.balanceOf(protocolFeeRecipient);
            LOAN_TOKEN.safeTransferFrom(from, protocolFeeRecipient, protocolFee);
+           require(LOAN_TOKEN.balanceOf(protocolFeeRecipient) - protocolBalanceBefore == protocolFee, 'Invalid amount');
        }
    }