Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LP token price manipulation by first depositor #113

Closed
code423n4 opened this issue Dec 16, 2022 · 2 comments
Closed

LP token price manipulation by first depositor #113

code423n4 opened this issue Dec 16, 2022 · 2 comments
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-442 satisfactory satisfies C4 submission criteria; eligible for awards

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2022-12-caviar/blob/main/src/Pair.sol#L417-L428
https://github.com/code-423n4/2022-12-caviar/blob/main/src/Pair.sol#L63-L99

Vulnerability details

Impact

LP token price manipulation by first depositor. He can make price of 1 share to be very big and benefit on rounding when next depositor add liquidity.

Proof of Concept

When user add liquidity to the pool then addQuote function is called to calculate amount of LP tokens that will be minted for user.
https://github.com/code-423n4/2022-12-caviar/blob/main/src/Pair.sol#L417-L428

    function addQuote(uint256 baseTokenAmount, uint256 fractionalTokenAmount) public view returns (uint256) {
        uint256 lpTokenSupply = lpToken.totalSupply();
        if (lpTokenSupply > 0) {
            // calculate amount of lp tokens as a fraction of existing reserves
            uint256 baseTokenShare = (baseTokenAmount * lpTokenSupply) / baseTokenReserves();
            uint256 fractionalTokenShare = (fractionalTokenAmount * lpTokenSupply) / fractionalTokenReserves();
            return Math.min(baseTokenShare, fractionalTokenShare);
        } else {
            // if there is no liquidity then init
            return Math.sqrt(baseTokenAmount * fractionalTokenAmount);
        }
    }

In case if there is no liquidity yet then Math.sqrt(baseTokenAmount * fractionalTokenAmount) is used to calculate amount of shares.
Attacker first can wrap token to get fractional tokens. Then attacker deposits 1 base token and 1 fractional token and get minted 1 LP token.
After that he can send huge amount of base tokens to the Pool directly. He even don't need to send fractional tokens, because addQuote will return min amount from baseTokenShare and fractionalTokenShare, so it's enough to increase reserves of only 1 token and it's easier to do with base token.
As result we will have only 1 LP token and huge reserves of base and fractional tokens.

When next depositors will be providing liquidity that means that they should provide big amount of base token to get a share. Also because of rounding in calculations, all amount that is (nextDepositorAmount * lpSharesAmount) % baseTokenReserves will be distributed among depositors and first depositor will benefit from that.

As result next depositors will be loosing part of funds and attacker will be earning more funds.

Tools Used

VsCode

Recommended Mitigation Steps

Do not allow first depositor to mint small amount of LP tokens.

@code423n4 code423n4 added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Dec 16, 2022
code423n4 added a commit that referenced this issue Dec 16, 2022
@c4-judge
Copy link
Contributor

berndartmueller marked the issue as duplicate of #442

@c4-judge
Copy link
Contributor

berndartmueller marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Jan 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-442 satisfactory satisfies C4 submission criteria; eligible for awards
Projects
None yet
Development

No branches or pull requests

2 participants