hats-finance / VMEX-0x050183b53cf62bcd6c2a932632f8156953fd146f

LP token lending protocol
MIT License
2 stars 1 forks source link

The `calculate_lp_token_price` function in the `VelodromeOracle.sol` calculates the spot Price #17

Open hats-bug-reporter[bot] opened 1 year ago

hats-bug-reporter[bot] commented 1 year ago

Github username: -- Submission hash (on-chain): 0xdd8b44e1ca79e32073cd25eb4ebfbbe7b0f2632587ec730c898465caa571c654 Severity: high severity

Description:

Summary

The vulnerability arises from the dependence on the total_supply value within the calculate_lp_token_price function. By manipulating the totalSupply of the pool using a flash loan, an attacker could potentially distort the fair reserves used in the LP token price calculation.

Description

The calculate_lp_token_price function is responsible for calculating the LP token price based on the fair reserves of a Balancer pool. It takes several parameters including the totalSupply, price0, price1, reserve0, and reserve1 of the pool. The calculation involves dividing the fair reserves by the totalSupply to determine the LP token price.

However, the issue arises when the totalSupply value is manipulated through a flash loan attack. By artificially inflating the totalSupply using a flash loan, an attacker can distort the fair reserves used in the price calculation. This manipulation can result in incorrect LP token prices being calculated and returned by the calculate_lp_token_price function.

Furthermore, since the calculate_lp_token_price function is utilized within the get_lp_price function, any incorrect LP token prices generated due to the manipulation of total_supply can propagate through subsequent calculations and affect the overall pricing accuracy in the getVeloPrice() of VMEXOracle.sol contract.

Code snippet

function calculate_lp_token_price(
        uint256 total_supply,
        uint256 price0,
        uint256 price1,
        uint256 reserve0,
        uint256 reserve1
    ) internal pure returns (uint256) {
        uint256 a = vMath.nthroot(2, reserve0 * reserve1); //square root
        uint256 b = vMath.nthroot(2, price0 * price1); //this is in decimals of chainlink oracle
        //we want a and total supply to have same number of decimals so c has decimals of chainlink oracle
        uint256 c = 2 * a * b / total_supply; 

        return c; 
    }

Recommendation

use Twap price

ksyao2002 commented 1 year ago

Total supply cannot be manipulated to inflate the lp price, see this: https://ethereum.stackexchange.com/questions/144866/manipulating-uniswap-v2s-pair-totalsupply-via-flash-loan

Nabeel-javaid commented 1 year ago

Total supply cannot be manipulated to inflate the lp price, see this: https://ethereum.stackexchange.com/questions/144866/manipulating-uniswap-v2s-pair-totalsupply-via-flash-loan

Manipulating the totalSupply via a flash loan attack can be done by following these general steps:

Borrow a significant amount of the LP tokens using a flash loan. Perform actions that manipulate the totalSupply value, such as minting additional LP tokens or burning existing tokens. Exploit the distorted totalSupply value to influence the LP token price and potentially profit from it. Repay the flash loan along with any associated fees, ensuring the borrowed amount is returned.

ksyao2002 commented 1 year ago

Please read the post I linked. I agree that total supply can be manipulated, but what I was saying is that it doesn't affect the pricing. In the way that we price the tokens (following alpha's recs here: https://blog.alphaventuredao.io/fair-lp-token-pricing/), even if you do manipulate the total supply, "the price of the LP token does not change when new LP tokens are minted. A similar proof could be derived for when liquidity tokens are burned from the pool."

If you insist that you are correct, you should provide a POC in solidity that delineates a profitable attack.

Nabeel-javaid commented 1 year ago

Please read the post I linked. I agree that total supply can be manipulated, but what I was saying is that it doesn't affect the pricing. In the way that we price the tokens (following alpha's recs here: https://blog.alphaventuredao.io/fair-lp-token-pricing/), even if you do manipulate the total supply, "the price of the LP token does not change when new LP tokens are minted. A similar proof could be derived for when liquidity tokens are burned from the pool."

If you insist that you are correct, you should provide a POC in solidity that delineates a profitable attack.

I've read the fair lp token system, but if you look at the code

function calculate_lp_token_price(
        uint256 total_supply,
        uint256 price0,
        uint256 price1,
        uint256 reserve0,
        uint256 reserve1
    ) internal pure returns (uint256) {
        uint256 a = vMath.nthroot(2, reserve0 * reserve1); //square root
        uint256 b = vMath.nthroot(2, price0 * price1); //this is in decimals of chainlink oracle
        //we want a and total supply to have same number of decimals so c has decimals of chainlink oracle
        uint256 c = 2 * a * b / total_supply; 

        return c; 
    }

here we can see that this line

uint256 c = 2 * a * b / total_supply; 

we are doing calculation in the base of totalSupply so manipulating the totalSupply will surely affect the system

and regarding POC is that i can't write POC, but I don't think my inability to write POC should make these vulnerabilities invalid.

ksyao2002 commented 1 year ago

That's exactly how Alpha Homora v2 does it: image

You see they call totalSupply() and use it directly as a divisor.

Is there a reason you can't write a POC? Without a POC it isn't valid either, so you won't be able to receive the bounty.