Platform: Code4rena
Start Date: 20/01/2023
Pot Size: $90,500 USDC
Total HM: 10
Participants: 59
Period: 7 days
Judge: Picodes
Total Solo HM: 4
Id: 206
League: ETH
Rank: 5/59
Findings: 1
Award: $4,626.00
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: 0Kage
4626.0034 USDC - $4,626.00
https://github.com/code-423n4/2023-01-timeswap/blob/ef4c84fb8535aad8abd6b67cc45d994337ec4514/packages/v2-pool/src/structs/Pool.sol#L302 https://github.com/code-423n4/2023-01-timeswap/blob/ef4c84fb8535aad8abd6b67cc45d994337ec4514/packages/v2-pool/src/structs/LiquidityPosition.sol#L60
When a LP mints V2 Pool tokens, mint
function in PoolLibrary gets called. Inside this function, updateDurationWeightBeforeMaturity
updates global short
, long0
and long1
fee growth.
Change in global fee growth necessitates an update to LiquidityPosition
state of caller (specifically updating fees & fee growth rates) when there are state changes made to that position (in this case, increasing liquidity). This principle is followed in functions such as burn
, transferLiquidity
, transferFees
. However when calling mint
, this update is missing. As a result, growth
& fee
levels in liquidity position of caller are inconsistent with global fee growth rates.
Inconsistent state leads to incorrect calculations of long0/long1 and short fees of LP holders which inturn can lead to loss of fees. Since this impacts actual rewards for users, I've marked it as MEDIUM risk
Let's say, Bob has following sequence of events
MINT at T0: Bob is a LP who mints N pool tokens at T0
MINT at T1: Bob mints another M pool tokens at T1. At this point, had the protocol correctly updated fees before minting new pool tokens, Bob's fees & growth rate would be a function of current liquidity (N), global updated short fee growth rate at t1 (s_t1) and Bob's previous growth rate at t_0 (b_t0)
BURN at T2: Bob burns N + M tokens at T2. At this point, Bob's fees should be a function of previous liquidity (N+M), global short fee growth rate (s_t2) and Bob's previous growth rate at t_1(b_t1) -> since this update never happened, Bob's previous growth rate is wrongly referenced b_t0 instead of b_t1.
Bob could collect a lower fees because of this state inconsistency
Update the liquidity position state right before minting.
After line 302 of Pool.sol, update the LiquidityPosition by adding
liquidityPosition.update(pool.long0FeeGrowth, pool.long1FeeGrowth, pool.shortFeeGrowth);
#0 - c4-sponsor
2023-02-08T13:00:33Z
vhawk19 marked the issue as sponsor confirmed
#1 - c4-judge
2023-02-12T22:28:54Z
Picodes marked the issue as satisfactory