Submitted by ItsNio, also found by KIntern_NA
Users who participate() and place stakes with large magnitudes may have their weight removed prematurely from pool.cumulative, hence causing the weight logic of participation to be wrong. pool.cumulative will have an incomplete image of the actual pool hence allowing future users to have divergent power when they should not. In particular, this occurs during the exitPosition() function.
This vulnerability stems from exitPosition() using the current pool.AverageMagnitude instead of the respective magnitudes of the users weights to update pool.cumulative on line 316. Hence, when users call exitPosition(), the amount that pool.cumulative is updated but may not be representative of the weight of the users input.
Imagine if we have three users, Alice, Bob, and Charlie who all decide to call participate(). Alice calls participate() with a smaller amount and a smaller time, hence having a weight of 10. Bob calls participate() with a larger amount and a larger time, hence having a weight of 50. Charlie calls participate() with a weight of 20.
If Alice does not participate at all, Charlie will not have divergent power in a pool with Bob and Charlie, since the pool.cumulative = Bobs weight = 50 > Charlies weight (20).
We have provided a test to demonstrate the pool.cumulative inflation. Copy the following code intotap-token-audit/test/oTAP/tOB.test.ts as one of the tests.
This test runs the aforementioned scenario.
The POC is split into two parts:
The first part starting with Just A Participation is when just A enters and exits. This is correct, with the pool.cumulative increasing by 10 (the weight of A) and then being decreased by 10 when A exits.
The second part starting with Run both participation--- describes the scenario mentioned by the bullet points. In particular, the pool.cumulative starts as 0 ([IN] Initial Cumulative).
Then, A enters the pool, and the pool.cumulative is increased to 10 ([B4] Both A Cumulative) similar to the first part.
Then, B enters the pool, before A exits. B has a weight of 50, thus the pool.cumulativeincreases to 60 ([B4] Both AB Cumulative).
The bug can be seen after the line beginning with [!X!]. The pool.cumulative labeled by Just B Cumulative is decreased by 60 - 10 = 50 when A exits, although the weight of A is only 10.
There may be a need to store weights at the time of adding a weight instead of subtracting the last computed weight in exitPosition(). For example, when Alice calls participate(), the weight at that time is stored and removed when exitPosition() is called.
0xRektora (Tapioca) confirmed
