From 7a98b22c2cfa66b0e7ee7ec6ceedb51fe423df3a Mon Sep 17 00:00:00 2001 From: Soil King <157099073+soilking@users.noreply.github.com> Date: Thu, 15 Aug 2024 11:48:12 -0700 Subject: [PATCH] FarmerGerminatingStalkBalanceChanged adjust for event bug --- projects/subgraph-beanstalk/schema.graphql | 13 +++++++ .../src/entities/Germinating.ts | 37 +++++++++++++++++-- .../src/handlers/GaugeHandler.ts | 19 ++++++++-- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/projects/subgraph-beanstalk/schema.graphql b/projects/subgraph-beanstalk/schema.graphql index 2fed33dd22..e486ed70c7 100644 --- a/projects/subgraph-beanstalk/schema.graphql +++ b/projects/subgraph-beanstalk/schema.graphql @@ -1472,6 +1472,19 @@ type Germinating @entity { bdv: BigInt! } +# This entity exists solely for resolving the issue in LibGerminate when deposits from multiple seasons +# complete their germination (the event emission itself has a bug) +type PrevFarmerGerminatingEvent @entity { + "Farmer address" + id: Bytes! + "The `block.number` of the `FarmerGerminatingStalkBalanceChanged` event" + eventBlock: BigInt! + "The `logIndex` of the `FarmerGerminatingStalkBalanceChanged` event" + logIndex: BigInt! + "The value for `deltaGerminatingStalk` from this previous `FarmerGerminatingStalkBalanceChanged` event." + deltaGerminatingStalk: BigInt! +} + type UnripeToken @entity { "Token Address" id: Bytes! diff --git a/projects/subgraph-beanstalk/src/entities/Germinating.ts b/projects/subgraph-beanstalk/src/entities/Germinating.ts index 32912d0149..8939dd6682 100644 --- a/projects/subgraph-beanstalk/src/entities/Germinating.ts +++ b/projects/subgraph-beanstalk/src/entities/Germinating.ts @@ -1,6 +1,6 @@ -import { Address, BigDecimal, BigInt, store } from "@graphprotocol/graph-ts"; -import { toDecimal, ZERO_BD, ZERO_BI } from "../../../subgraph-core/utils/Decimals"; -import { Germinating } from "../../generated/schema"; +import { Address, BigDecimal, BigInt, ethereum, store } from "@graphprotocol/graph-ts"; +import { ONE_BI, toDecimal, ZERO_BD, ZERO_BI } from "../../../subgraph-core/utils/Decimals"; +import { Germinating, PrevFarmerGerminatingEvent } from "../../generated/schema"; export function loadOrCreateGerminating(address: Address, season: i32, isFarmer: boolean): Germinating { const type = germinationSeasonCategory(season); @@ -42,6 +42,37 @@ export function deleteGerminating(germinating: Germinating): void { store.remove("Germinating", germinating.id); } +// This is the entity that exists to resolve the issue in LibGerminate when deposits from multiple seasons +// complete their germination (the event emission itself has a bug) +export function loadPrevFarmerGerminatingEvent(account: Address): PrevFarmerGerminatingEvent { + let savedEvent = PrevFarmerGerminatingEvent.load(account); + if (savedEvent == null) { + savedEvent = new PrevFarmerGerminatingEvent(account); + savedEvent.eventBlock = ZERO_BI; + savedEvent.logIndex = ZERO_BI; + savedEvent.deltaGerminatingStalk = ZERO_BI; + // No point in saving it + } + return savedEvent as PrevFarmerGerminatingEvent; +} + +export function savePrevFarmerGerminatingEvent(account: Address, event: ethereum.Event, deltaGerminatingStalk: BigInt): void { + const savedEvent = new PrevFarmerGerminatingEvent(account); + savedEvent.eventBlock = event.block.number; + savedEvent.logIndex = event.logIndex; + savedEvent.deltaGerminatingStalk = deltaGerminatingStalk; + savedEvent.save(); +} + +// Returns the stalk offset that should be applied to the encountered FarmerGerminatingStalkBalanceChanged event. +export function getFarmerGerminatingBugOffset(account: Address, event: ethereum.Event): BigInt { + const prevEvent = loadPrevFarmerGerminatingEvent(account); + if (prevEvent.eventBlock == event.block.number && prevEvent.logIndex == event.logIndex.minus(ONE_BI)) { + return prevEvent.deltaGerminatingStalk.neg(); + } + return ZERO_BI; +} + function germinationSeasonCategory(season: i32): string { return season % 2 == 0 ? "EVEN" : "ODD"; } diff --git a/projects/subgraph-beanstalk/src/handlers/GaugeHandler.ts b/projects/subgraph-beanstalk/src/handlers/GaugeHandler.ts index 30401b4dba..72038a6886 100644 --- a/projects/subgraph-beanstalk/src/handlers/GaugeHandler.ts +++ b/projects/subgraph-beanstalk/src/handlers/GaugeHandler.ts @@ -8,7 +8,13 @@ import { TotalGerminatingStalkChanged, TotalStalkChangedFromGermination } from "../../generated/Beanstalk-ABIs/SeedGauge"; -import { deleteGerminating, loadGerminating, loadOrCreateGerminating } from "../entities/Germinating"; +import { + deleteGerminating, + getFarmerGerminatingBugOffset, + loadGerminating, + loadOrCreateGerminating, + savePrevFarmerGerminatingEvent +} from "../entities/Germinating"; import { BI_10, ZERO_BI } from "../../../subgraph-core/utils/Decimals"; import { BEAN_WETH_CP2_WELL } from "../../../subgraph-core/utils/Constants"; import { Bytes4_emptyToNull } from "../../../subgraph-core/utils/Bytes"; @@ -71,9 +77,13 @@ export function handleFarmerGerminatingStalkBalanceChanged(event: FarmerGerminat farmerGerminating.stalk = farmerGerminating.stalk.plus(event.params.deltaGerminatingStalk); farmerGerminating.save(); } else { + // Adjusts for the event's inherent bug when both even/odd germination complete in the same txn + const bugfixStalkOffset = getFarmerGerminatingBugOffset(event.params.account, event); + const actualDeltaGerminatingStalk = event.params.deltaGerminatingStalk.plus(bugfixStalkOffset); + // Germinating stalk is being removed. It therefore must have created the entity already let farmerGerminating = loadGerminating(event.params.account, event.params.germinationState); - farmerGerminating.stalk = farmerGerminating.stalk.plus(event.params.deltaGerminatingStalk); + farmerGerminating.stalk = farmerGerminating.stalk.plus(actualDeltaGerminatingStalk); if (farmerGerminating.stalk == ZERO_BI) { deleteGerminating(farmerGerminating); } else { @@ -84,10 +94,13 @@ export function handleFarmerGerminatingStalkBalanceChanged(event: FarmerGerminat // If germination finished, need to subtract stalk from system silo. This stalk was already added // into system stalk upon sunrise for season - 2. let systemSilo = loadSilo(event.address); - systemSilo.stalk = systemSilo.stalk.plus(event.params.deltaGerminatingStalk); + systemSilo.stalk = systemSilo.stalk.plus(actualDeltaGerminatingStalk); takeSiloSnapshots(systemSilo, event.address, event.block.timestamp); systemSilo.save(); } + + // Also for the event bug adjustment + savePrevFarmerGerminatingEvent(event.params.account, event, event.params.deltaGerminatingStalk); } let farmerSilo = loadSilo(event.params.account);