Category: Coding Mistakes
The ReserveSnapshots are never updated
High Impact
High Severity
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↗.