code-423n4 / 2024-01-curves-findings

0 stars 0 forks source link

Single token purchase restriction on curve creation enables sniping #243

Open c4-bot-8 opened 7 months ago

c4-bot-8 commented 7 months ago

Lines of code

https://github.com/code-423n4/2024-01-curves/blob/516aedb7b9a8d341d0d2666c23780d2bd8a9a600/contracts/Curves.sol#L184

Vulnerability details

Impact

The getPrice() function in the Curves contract is used to calculate the price of tokens when buying or selling. However, due to the order of arguments in the sum2 calculation within this function, subjects are restricted to buying only one token when initializing their curve.

The issue arises from the expression (supply - 1 + amount), which reverts when supply is greater than 1. However, if the expression was (supply + amount - 1), this issue would not occur. This restriction limits the functionality of the contract and makes it vulnerable to sniping on initialization and first-purchase frontrunning. This issue has spawned a small industry around friend.tech, with different companies offering sniping bots that can make instant automatic first purchases for accounts associated with a sizeable social media presence.

function getPrice(uint256 supply, uint256 amount) public pure returns (uint256) {    
    uint256 sum1 = supply == 0 ? 0 : ((supply - 1) * (supply) * (2 * (supply - 1) + 1)) / 6;
    uint256 sum2 = supply == 0 && amount == 1
        ? 0
        : ((supply - 1 + amount) * (supply + amount) * (2 * (supply - 1 + amount) + 1)) / 6;
    ...
}

Although the issue can be mitigated in the Curves implementation by the curve subject opening a presale, it is still present for curves initialized without presale.

Proof of Concept

  1. A user with a large social media following wants to initialize a curve and buy the first 10 tokens for future use, possibly for an airdrop to her followers.
  2. She does not want to create a presale and instead initializes the curve directly via buyCurvesToken().
  3. As soon as the curve is initialized, automated sniping bots start buying large numbers of tokens.
  4. She is now forced to purchase the tokens at a much higher price and may incur losses from bots realizing their profits.

Tools Used

Manual review

Recommended Mitigation Steps

To resolve this issue, the order of arguments in the sum2 calculation within the getPrice() function should be adjusted. Instead of (supply - 1 + amount), the expression should be (supply + amount - 1). This change will allow subjects to buy more than one token when initializing their curve, enhancing the contract's functionality and protecting the users.

Assessed type

Other

c4-pre-sort commented 7 months ago

raymondfam marked the issue as insufficient quality report

c4-pre-sort commented 7 months ago

raymondfam marked the issue as duplicate of #44

c4-judge commented 7 months ago

alcueca marked the issue as selected for report

c4-judge commented 7 months ago

alcueca marked the issue as satisfactory

stalinMacias commented 6 months ago

@alcueca The purpose of the current price's formula it is to allow the tokenSubject to initialize their curvesTokens. The first token is minted for free to the tokenSubject.

If the tokenSubject would like to purchase X amount of tokens for an airdrop, that is the purpose of the new presales functionality. The tokenSubject can simply initiate a pre-sale for himself so he can buy the X amount he'd like to airdrop in the future.

From the PoC of the report:

She does not want to create a presale and instead initializes the curve directly via buyCurvesToken().

  • Then the tokenSubject explicitly initiates the open sale for anybody (not only snipping bots).

This report is more of a user mistake rather than an issue with the code, because of that, I think this report should not be assessed as a medium severity, but instead, it should be a low.

AtanasDimulski commented 6 months ago

I completely agree with @stalinMacias, I would like to add that the Curves team has specified the following in the README of the contest:

Presale Feature: Learning from the pitfalls of friend.tech, particularly issues with frontrunners during token launches, Curves incorporates a presale phase. This allows creators to manage and stabilize their tokens prior to public trading, ensuring a more controlled and equitable distribution.

alcueca commented 6 months ago

I'm not convinced that the purpose of the presales functionality is to allow the token subject to create a presale for himself just so that he can buy more than one token (and then not being able to have a presale for other users).

If the token subject would choose to do a regular presale, using the regular community mechanisms from the NFT era, how would they ensure that they don't get a sniping bot registered for the presale?

The team might have intended to solve the issues with frontrunners, but to me it doesn't seem they succeeded.