hats-finance / Thorn-protocol-0x1286ecdac50215a366458a14968fbca4bd95067d

GNU General Public License v3.0
0 stars 0 forks source link

Incorrect calculation of LP fee when swapping tokens #90

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

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

Github username: -- Twitter username: -- Submission hash (on-chain): 0x3d426b4bbd2ae2007faae7ac4b9bee04bae2396d6d4533ad7cc74350bcee45f8 Severity: high

Description: Description\ LP fees are neither correctly calculated nor stored when swapping tokens via StableSwapTwoPool::exchange

Attack Scenario\ LP providers earn fees when Thorn exchange sells tokens to swapping customers. The function responsible for swapping, StableSwapTwoPool::exchange, does not correctly calculate LP fee and neither does it provide a mechanism to store this value. Attachments

  1. Proof of Concept (PoC) File Consider the fee calucation via StableSwapTwoPool::exchange:
 uint256 dy = xp[j] - y - 1; //  -1 just in case there were some rounding errors 1e18 * (10**(18 - coinDecimal) ) - y - 1
        uint256 dy_fee = (dy * fee) / FEE_DENOMINATOR;

        // Convert all to real units
        dy = ((dy - dy_fee) * PRECISION) / RATES[j];// * 1e18 / (bal * (10**(18 - coinDecimal) );)
        require(dy >= min_dy, "Exchange resulted in fewer coins than expected");

        uint256 dy_admin_fee = (dy_fee * admin_fee) / FEE_DENOMINATOR;
        dy_admin_fee = (dy_admin_fee * PRECISION) / RATES[j];

        // Change balances exactly in same way as we change actual ERC20 coin amounts
        balances[i] = old_balances[i] + dx;
        // When rounding errors happen, we undercharge admin fee in favor of LP
        balances[j] = old_balances[j] - dy - dy_admin_fee;

        address iAddress = coins[i];
        if (iAddress == ROSE_ADDRESS) {
            require(dx == msg.value, "Inconsistent quantity");
        } else {
            IERC20(iAddress).safeTransferFrom(msg.sender, address(this), dx);
        }
        address jAddress = coins[j];
        transfer_out(jAddress, dy);
        emit TokenExchange(msg.sender, i, dx, j, dy);

There's no place where this fee is calculated nor saved in storage.

  1. Revised Code File (Optional) Consider providing a storage variable for storing calculated LP fee