code-423n4 / 2024-06-size-findings

0 stars 0 forks source link

BuyCreditMarket: Missing Fee Deduction from Buyer Payment (exactAmountIn=true) #388

Closed howlbot-integration[bot] closed 2 months ago

howlbot-integration[bot] commented 2 months ago

Lines of code

https://github.com/code-423n4/2024-06-size/blob/8850e25fb088898e9cf86f9be1c401ad155bea86/src/libraries/actions/BuyCreditMarket.sol#L195-L196 https://github.com/code-423n4/2024-06-size/blob/8850e25fb088898e9cf86f9be1c401ad155bea86/src/libraries/actions/SellCreditMarket.sol#L201-L203

Vulnerability details

Impact

1. SellCreditMarket applies the swap fee consistently

2. BuyCreditMarket lacks explicit fee handling for the buyer

Proof of Concept

1. Overpayment by Buyers // src\libraries\actions\BuyCreditMarket.sol

function executeBuyCreditMarket(...) external returns (uint256 cashAmountIn) {
    // ... (calculations for cashAmountIn, creditAmountOut, fees)

    // Funds transferred WITHOUT deducting fees:
    state.data.borrowAToken.transferFrom(msg.sender, borrower, cashAmountIn - fees); 
    state.data.borrowAToken.transferFrom(msg.sender, state.feeConfig.feeRecipient, fees);
}

2. Inconsistent Fee Distribution // src\libraries\actions\SellCreditMarket.sol

function executeSellCreditMarket(...) external returns (uint256 cashAmountOut) {
    // ... (calculations for cashAmountOut, creditAmountIn, fees)

    // Fees deducted BEFORE transferring to the seller:
    state.data.borrowAToken.transferFrom(params.lender, msg.sender, cashAmountOut); 
    state.data.borrowAToken.transferFrom(params.lender, state.feeConfig.feeRecipient, fees);
}

Comparison:

3. Further Considerations:

Initial

Test Case 1: Buyer Overpayment in BuyCreditMarket

function testBuyCreditMarketOverpayment() public {
    // 1. Record initial balances
    uint256 aliceBalanceBefore = size.data.borrowAToken.balanceOf(alice);

    // 2. Define buy parameters with a non-zero swap fee
    uint256 creditAmount = 100e6; // 100 USDC
    uint256 tenor = 30 days;
    // Assuming a swap fee that results in 1 USDC fee for this example
    uint256 expectedFee = 1e6; 

    // 3. Execute BuyCreditMarket
    size.buyCreditMarket(
        BuyCreditMarketParams({
            borrower: alice,
            creditPositionId: RESERVED_ID,
            amount: creditAmount,
            tenor: tenor,
            deadline: block.timestamp + 1 hours,
            minAPR: 0,
            exactAmountIn: true 
        })
    );

    // 4. Calculate expected final balance
    uint256 aliceBalanceExpected = aliceBalanceBefore - creditAmount; 

    // 5. Assert: Alice's balance should be reduced by the full creditAmount, NOT creditAmount - fee
    assertEq(size.data.borrowAToken.balanceOf(alice), aliceBalanceExpected, "Buyer overpaid!");
} 

Test Case 2: Correct Fee Deduction in SellCreditMarket

function testSellCreditMarketFeeDeduction() public {
    // 1. Record initial balances
    uint256 bobBalanceBefore = size.data.borrowAToken.balanceOf(bob);

    // 2. Define sell parameters (use same creditAmount and tenor as before)
    // ...

    // 3. Execute SellCreditMarket
    size.sellCreditMarket(
        // ... sell parameters
    );

    // 4. Calculate expected final balance (fee deducted)
    uint256 bobBalanceExpected = bobBalanceBefore + creditAmount - expectedFee;

    // 5. Assert: Bob's balance reflects the fee deduction
    assertEq(size.data.borrowAToken.balanceOf(bob), bobBalanceExpected, "Fee not deducted correctly!");
}

Expected Results & Analysis

Tools Used

Vs

Recommended Mitigation Steps

If the omission is unintentional, modify the BuyCreditMarket function to deduct the calculated fees from the cashAmountIn before transferring funds.

Assessed type

Error

c4-judge commented 2 months ago

hansfriese marked the issue as unsatisfactory: Out of scope

c4-judge commented 2 months ago

hansfriese marked the issue as not a duplicate

hansfriese commented 2 months ago

Invalid

c4-judge commented 2 months ago

hansfriese marked the issue as unsatisfactory: Invalid