Category: Coding Mistakes
The ReserveSnapshots
are never updated
High Severity
High Impact
High Likelihood
Description
The perp module has an EndBlocker
, which is designed to create a snapshot of the AMM in order to calculate the TWAP prices:
// EndBlocker Called every block to store a snapshot of the perpamm.
func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate {
for _, amm := range k.AMMs.Iterate(ctx, collections.Range[asset.Pair]{}).Values() {
snapshot := types.ReserveSnapshot{
Amm: amm,
TimestampMs: ctx.BlockTime().UnixMilli(),
}
k.ReserveSnapshots.Insert(ctx, collections.Join(amm.Pair, ctx.BlockTime()), snapshot)
}
return []abci.ValidatorUpdate{}
}
The issue is that the EndBlocker
is not hooked up and is never called.
Impact
The ReserveSnapshots
are never updated and so anything relying on it (such as CalcTwap
) will be using whatever values were set during genesis.
Recommendations
The EndBlocker
should be called from the perp module's EndBlock
:
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
EndBlocker(ctx, am.keeper)
return []abci.ValidatorUpdate{}
}
Remediation
This issue has been acknowledged by Nibiru, and a fix was implemented in commit 7144cc96↗.