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

add_liquidity will revert in some cases #105

Open
hats-bug-reporter bot opened this issue Oct 14, 2024 · 1 comment
Open

add_liquidity will revert in some cases #105

hats-bug-reporter bot opened this issue Oct 14, 2024 · 1 comment
Labels
bug Something isn't working invalid This doesn't seem right

Comments

@hats-bug-reporter
Copy link

Github username: @MGF15
Twitter username: --
Submission hash (on-chain): 0xb0878f3292d893808b8ba4f6fe35c740369c807b459292c1589209f2c2f4239c
Severity: low

Description:
Description
the add_liquidity function that allow user to deposit coins into the pool, however in some cases the function will revert when transfer from the sender when an ERC-20 that revert on zero amount transfer like eg LEND because no check if amount in 0

for (uint256 i = 0; i < N_COINS; i++) {
            uint256 amount = amounts[i];
            address coin = coins[i];
            transfer_in(coin, amount); // @audit miss 0 amount check 
        }

Attachments

  1. Proof of Concept (PoC) File
function add_liquidity(uint256[N_COINS] memory amounts, uint256 min_mint_amount) external payable nonReentrant {
        //Amounts is amounts of c-tokens
        require(!is_killed, "Killed");
        if (!support_ROSE) {
            require(msg.value == 0, "Inconsistent quantity"); // Avoid sending ROSE by mistake.
        }
        uint256[N_COINS] memory fees;
        uint256 _fee = (fee * N_COINS) / (4 * (N_COINS - 1));
        uint256 _admin_fee = admin_fee;
        uint256 amp = get_A();

        uint256 token_supply = token.totalSupply();
        //Initial invariant
        uint256 D0;
        uint256[N_COINS] memory old_balances = balances;
        if (token_supply > 0) {
            D0 = get_D_mem(old_balances, amp);
        }
        uint256[N_COINS] memory new_balances = [old_balances[0], old_balances[1]];

        for (uint256 i = 0; i < N_COINS; i++) {
            if (token_supply == 0) {
                require(amounts[i] > 0, "Initial deposit requires all coins");
            }
            // balances store amounts of c-tokens
            new_balances[i] = old_balances[i] + amounts[i];
        }

        // Invariant after change
        uint256 D1 = get_D_mem(new_balances, amp);
        require(D1 > D0, "D1 must be greater than D0");

        // We need to recalculate the invariant accounting for fees
        // to calculate fair user's share
        uint256 D2 = D1;
        if (token_supply > 0) {
            // Only account for fees if we are not the first to deposit
            for (uint256 i = 0; i < N_COINS; i++) {
                uint256 ideal_balance = (D1 * old_balances[i]) / D0;
                uint256 difference;
                if (ideal_balance > new_balances[i]) {
                    difference = ideal_balance - new_balances[i];
                } else {
                    difference = new_balances[i] - ideal_balance;
                }

                fees[i] = (_fee * difference) / FEE_DENOMINATOR;
                balances[i] = new_balances[i] - ((fees[i] * _admin_fee) / FEE_DENOMINATOR);
                new_balances[i] -= fees[i];
            }
            D2 = get_D_mem(new_balances, amp);
        } else {
            balances = new_balances;
        }

        // Calculate, how much pool tokens to mint
        uint256 mint_amount;
        if (token_supply == 0) {
            mint_amount = D1; // Take the dust if there was any
        } else {
            mint_amount = (token_supply * (D2 - D0)) / D0;
        }
        require(mint_amount >= min_mint_amount, "Slippage screwed you");

        // Take coins from the sender
        for (uint256 i = 0; i < N_COINS; i++) {
            uint256 amount = amounts[i];
            address coin = coins[i];
            transfer_in(coin, amount); // @audit miss 0 amount check 
        }

        // Mint pool tokens
        token.mint(msg.sender, mint_amount);

        emit AddLiquidity(msg.sender, amounts, fees, D1, token_supply + mint_amount);
    }
@hats-bug-reporter hats-bug-reporter bot added the bug Something isn't working label Oct 14, 2024
@omega-audits omega-audits added the invalid This doesn't seem right label Oct 14, 2024
@omega-audits
Copy link

If the user deposits 0 there is no deposit regardless, and special tokens like these are usually not considered regardless.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

1 participant