code-423n4/2024-08-phi-validation

Exploitation of Bonding Curve - Underpricing Due to Low Initial Supply.

c4-bot-10 opened this issue · 0 comments

Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/Cred.sol#L611-L612
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/curve/BondingCurve.sol#L63
https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/curve/BondingCurve.sol#L47-L49

Vulnerability details

Impact

The vulnerability arises from the bonding curve mechanism used to calculate the price of a credential in scenarios where the supply is low. When a new credential is issued with a low initial supply, the price determined by the bonding curve may be significantly undervalued. Malicious actors can exploit this by purchasing large quantities of the credential at these artificially low prices. As the supply increases and demand grows, the price naturally rises according to the bonding curve, allowing these actors to sell their holdings at a much higher price, leading to disproportionate profits. This can result in financial losses for other participants who buy at the inflated prices and destabilize the market for the credential.

Proof of Concept

The vulnerability lies in the bonding curve logic, particularly in the following sections of the code:

1. Relevant Code Sections:

Price Calculation - The price is calculated using the getPrice function, which applies the bonding curve formula:

function getPrice(uint256 supply_, uint256 amount_) public pure returns (uint256) {
    return _curve((supply_ + amount_) * 1 ether) - _curve(supply_ * 1 ether);
}

Curve Calculation - The _curve function uses the following formula to determine the price based on the supply:

function _curve(uint256 targetAmount_) private pure returns (uint256) {
    return (TOTAL_SUPPLY_FACTOR * CURVE_FACTOR * 1 ether) / (TOTAL_SUPPLY_FACTOR - targetAmount_)
        - CURVE_FACTOR * 1 ether - INITIAL_PRICE_FACTOR * targetAmount_ / 1000;
}

2. Example Scenario:

  • TOTAL_SUPPLY_FACTOR = 1000 ether
  • CURVE_FACTOR = 10
  • INITIAL_PRICE_FACTOR = 9
    If the initial supply is 1 ether, the price will be extremely low due to the high total supply factor and the small initial supply. This allows a malicious actor to buy a large amount at this low price.

3. Exploitation Example:

  • Initial Supply: 1 ether
  • Amount Purchased: 70 ether
  • Price Before Purchase: Calculated using getPrice(1, 70)
  • Price After Purchase: Substantially higher due to the increased supply.
    This creates an opportunity for the attacker to profit from the price difference by selling the purchased amount after the price has increased.

Tools Used

VScode, Manual review.

Recommended Mitigation Steps

1. Initial Price Floor: Implement an initial price floor to prevent the price from being too low, even when the supply is minimal. This could be a fixed minimum price or dynamically adjusted based on demand.

uint256 private constant INITIAL_PRICE_FLOOR = 1 ether; // Or an appropriate price floor

function getPrice(uint256 supply_, uint256 amount_) public pure returns (uint256) {
    uint256 price = _curve((supply_ + amount_) * 1 ether) - _curve(supply_ * 1 ether);
    if (price < INITIAL_PRICE_FLOOR) {
        return INITIAL_PRICE_FLOOR;
    }
    return price;
}

2. Trading Restrictions: Implement restrictions on how quickly assets can be sold after being purchased, such as time locks or gradually releasing the ability to sell, which would mitigate rapid price manipulation.

Assessed type

Invalid Validation