exitPosition
in TapiocaOptionBroker
may incorrectly inflate position weights
#1623
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
H-02
primary issue
Highest quality submission among a set of duplicates
selected for report
This submission will be included/highlighted in the audit report
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Lines of code
https://github.com/Tapioca-DAO/tap-token-audit/blob/59749be5bc2286f0bdbf59d7ddc258ddafd49a9f/contracts/options/TapiocaOptionBroker.sol#L316
Vulnerability details
Impact
Users who
participate()
and place stakes with large magnitudes may have their weight removed prematurely frompool.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 theexitPosition()
function.Proof of Concept
This vulnerability stems from
exitPosition()
using the currentpool.AverageMagnitude
instead of the respective magnitudes of the user's weights to updatepool.cumulative
on line 316. Hence, when users callexitPosition()
, the amount thatpool.cumulative
is updated but may not be representative of the weight of the user's input.Imagine if we have three users, Alice, Bob, and Charlie who all decide to call
participate()
. Alice callsparticipate()
with a smaller amount and a smaller time, hence having a weight of 10. Bob callsparticipate()
with a larger amount and a larger time, hence having a weight of 50. Charlie callsparticipate()
with a weight of 20.Scenario
participate()
first at time 0 with the aforementioned amount and time. Thepool.cumulative
is now 10 and thepool.AverageMagnitude
is 10 as well. Alice's position will expire at time 10.participate()
at time 5. Thepool.cumulative
is now 10 + 50 = 60 and thepool.AverageMagnitude
is 50.exitPosition()
at time 10.pool.cumulative
is 60, butpool.AverageMagnitude
is still 50. Hence,pool.cumulative
will be decreased by 50, even though the weight of Alice's input is 10.participate
with weight 20. Charlie will have divergent power in the pool with both Bob and Charlie, since 20 >pool.cumulative
(10)....
If Alice does not participate at all, Charlie will not have divergent power in a pool with Bob and Charlie, since the
pool.cumulative
= Bob's weight = 50 > Charlie's 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.
Expected Output:
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 thepool.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, thepool.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.cumulative
increases to 60 ([B4] Both AB Cumulative
).The bug can be seen after the line beginning with
[!X!]
. Thepool.cumulative
labeled by "Just B Cumulative" is decreased by 60 - 10 = 50 when A exits, although the weight of A is only 10.Recommended Mitigation Steps
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 callsparticipate()
, the weight at that time is stored and removed whenexitPosition()
is called.Assessed type
Math
The text was updated successfully, but these errors were encountered: