diff --git a/abis/RewardsManagerStitched.json b/abis/RewardsManagerStitched.json index dd92f5e..4c58dd5 100644 --- a/abis/RewardsManagerStitched.json +++ b/abis/RewardsManagerStitched.json @@ -62,6 +62,31 @@ "name": "RewardsAssigned", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "indexer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "allocationID", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "HorizonRewardsAssigned", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/src/mappings/rewardsManager.ts b/src/mappings/rewardsManager.ts index e492b2b..9ea9d3d 100644 --- a/src/mappings/rewardsManager.ts +++ b/src/mappings/rewardsManager.ts @@ -2,6 +2,7 @@ import { Address, BigInt } from '@graphprotocol/graph-ts' import { Indexer, Allocation, SubgraphDeployment } from '../types/schema' import { RewardsAssigned, + HorizonRewardsAssigned, ParameterUpdated, RewardsManagerStitched as RewardsManager, RewardsDenylistUpdated, @@ -16,22 +17,109 @@ import { import { addresses } from '../../config/addresses' export function handleRewardsAssigned(event: RewardsAssigned): void { - let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address) - let indexerID = event.params.indexer.toHexString() + processRewardsAssigned( + event.params.indexer, + event.params.allocationID.toHexString(), + event.params.amount, + event.block.number, + event.block.timestamp, + event.address, + ) +} + +/** + * @dev handleHorizonRewardsAssigned + * - Handles the HorizonRewardsAssigned event emitted after Horizon upgrade + * - Only processes rewards for legacy allocations (created via old Staking contract) + * - New allocations (via SubgraphService) are handled by IndexingRewardsCollected instead + */ +export function handleHorizonRewardsAssigned(event: HorizonRewardsAssigned): void { let allocationID = event.params.allocationID.toHexString() + let allocation = Allocation.load(allocationID) + + // Skip if allocation doesn't exist or is not a legacy allocation + // New allocations have their rewards tracked via IndexingRewardsCollected from SubgraphService + if (allocation == null || !allocation.isLegacy) { + return + } + + processRewardsAssigned( + event.params.indexer, + allocationID, + event.params.amount, + event.block.number, + event.block.timestamp, + event.address, + ) +} + +/** + * @dev handleParameterUpdated + * - handlers updating all parameters + */ +export function handleParameterUpdated(event: ParameterUpdated): void { + let parameter = event.params.param + let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address) + let rewardsManager = RewardsManager.bind(event.address as Address) + + if (parameter == 'issuanceRate') { + graphNetwork.networkGRTIssuance = rewardsManager.issuanceRate() + } else if (parameter == 'issuancePerBlock') { + graphNetwork.networkGRTIssuancePerBlock = rewardsManager.issuancePerBlock() + } else if (parameter == 'subgraphAvailabilityOracle') { + graphNetwork.subgraphAvailabilityOracle = rewardsManager.subgraphAvailabilityOracle() + } + graphNetwork.save() +} + +// export function handleImplementationUpdated(event: ImplementationUpdated): void { +// let graphNetwork = GraphNetwork.load('1') +// let implementations = graphNetwork.rewardsManagerImplementations +// implementations.push(event.params.newImplementation) +// graphNetwork.rewardsManagerImplementations = implementations +// graphNetwork.save() +// } + +export function handleRewardsDenyListUpdated(event: RewardsDenylistUpdated): void { + let subgraphDeployment = SubgraphDeployment.load(event.params.subgraphDeploymentID.toHexString()) + if (subgraphDeployment != null) { + if (event.params.sinceBlock.toI32() == 0) { + subgraphDeployment.deniedAt = 0 + } else { + subgraphDeployment.deniedAt = event.params.sinceBlock.toI32() + } + subgraphDeployment.save() + } + // We might need to handle the case where the subgraph deployment doesn't exists later +} + +/** + * @dev processRewardsAssigned + * - Common logic for processing rewards assigned events (both legacy RewardsAssigned and HorizonRewardsAssigned) + */ +function processRewardsAssigned( + indexerAddress: Address, + allocationID: string, + amount: BigInt, + blockNumber: BigInt, + blockTimestamp: BigInt, + eventAddress: Address, +): void { + let graphNetwork = createOrLoadGraphNetwork(blockNumber, eventAddress) + let indexerID = indexerAddress.toHexString() // update indexer let indexer = Indexer.load(indexerID)! - indexer.rewardsEarned = indexer.rewardsEarned.plus(event.params.amount) + indexer.rewardsEarned = indexer.rewardsEarned.plus(amount) // If the delegation pool has zero tokens, the contracts don't give away any rewards let indexerIndexingRewards = indexer.delegatedTokens == BigInt.fromI32(0) - ? event.params.amount - : event.params.amount + ? amount + : amount .times(BigInt.fromI32(indexer.legacyIndexingRewardCut)) .div(BigInt.fromI32(1000000)) - let delegatorIndexingRewards = event.params.amount.minus(indexerIndexingRewards) + let delegatorIndexingRewards = amount.minus(indexerIndexingRewards) indexer.delegatorIndexingRewards = indexer.delegatorIndexingRewards.plus(delegatorIndexingRewards) indexer.indexerIndexingRewards = indexer.indexerIndexingRewards.plus(indexerIndexingRewards) @@ -46,7 +134,7 @@ export function handleRewardsAssigned(event: RewardsAssigned): void { // update allocation // no status updated, Claimed happens when RebateClaimed, and it is done let allocation = Allocation.load(allocationID)! - allocation.indexingRewards = allocation.indexingRewards.plus(event.params.amount) + allocation.indexingRewards = allocation.indexingRewards.plus(amount) allocation.indexingIndexerRewards = allocation.indexingIndexerRewards.plus(indexerIndexingRewards) allocation.indexingDelegatorRewards = allocation.indexingDelegatorRewards.plus( delegatorIndexingRewards, @@ -54,8 +142,8 @@ export function handleRewardsAssigned(event: RewardsAssigned): void { allocation.save() // Update epoch - let epoch = createOrLoadEpoch(addresses.isL1 ? event.block.number : graphNetwork.currentL1BlockNumber!, graphNetwork) - epoch.totalRewards = epoch.totalRewards.plus(event.params.amount) + let epoch = createOrLoadEpoch(addresses.isL1 ? blockNumber : graphNetwork.currentL1BlockNumber!, graphNetwork) + epoch.totalRewards = epoch.totalRewards.plus(amount) epoch.totalIndexerRewards = epoch.totalIndexerRewards.plus(indexerIndexingRewards) epoch.totalDelegatorRewards = epoch.totalDelegatorRewards.plus(delegatorIndexingRewards) epoch.save() @@ -64,12 +152,10 @@ export function handleRewardsAssigned(event: RewardsAssigned): void { let subgraphDeploymentID = allocation.subgraphDeployment let subgraphDeployment = createOrLoadSubgraphDeployment( subgraphDeploymentID, - event.block.timestamp, + blockTimestamp, graphNetwork, ) - subgraphDeployment.indexingRewardAmount = subgraphDeployment.indexingRewardAmount.plus( - event.params.amount, - ) + subgraphDeployment.indexingRewardAmount = subgraphDeployment.indexingRewardAmount.plus(amount) subgraphDeployment.indexingIndexerRewardAmount = subgraphDeployment.indexingIndexerRewardAmount.plus( indexerIndexingRewards, ) @@ -79,7 +165,7 @@ export function handleRewardsAssigned(event: RewardsAssigned): void { subgraphDeployment.save() // update graph network - graphNetwork.totalIndexingRewards = graphNetwork.totalIndexingRewards.plus(event.params.amount) + graphNetwork.totalIndexingRewards = graphNetwork.totalIndexingRewards.plus(amount) graphNetwork.totalIndexingIndexerRewards = graphNetwork.totalIndexingIndexerRewards.plus( indexerIndexingRewards, ) @@ -89,43 +175,3 @@ export function handleRewardsAssigned(event: RewardsAssigned): void { graphNetwork.totalDelegatedTokens = graphNetwork.totalDelegatedTokens.plus(delegatorIndexingRewards) graphNetwork.save() } - -/** - * @dev handleParameterUpdated - * - handlers updating all parameters - */ -export function handleParameterUpdated(event: ParameterUpdated): void { - let parameter = event.params.param - let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address) - let rewardsManager = RewardsManager.bind(event.address as Address) - - if (parameter == 'issuanceRate') { - graphNetwork.networkGRTIssuance = rewardsManager.issuanceRate() - } else if (parameter == 'issuancePerBlock') { - graphNetwork.networkGRTIssuancePerBlock = rewardsManager.issuancePerBlock() - } else if (parameter == 'subgraphAvailabilityOracle') { - graphNetwork.subgraphAvailabilityOracle = rewardsManager.subgraphAvailabilityOracle() - } - graphNetwork.save() -} - -// export function handleImplementationUpdated(event: ImplementationUpdated): void { -// let graphNetwork = GraphNetwork.load('1') -// let implementations = graphNetwork.rewardsManagerImplementations -// implementations.push(event.params.newImplementation) -// graphNetwork.rewardsManagerImplementations = implementations -// graphNetwork.save() -// } - -export function handleRewardsDenyListUpdated(event: RewardsDenylistUpdated): void { - let subgraphDeployment = SubgraphDeployment.load(event.params.subgraphDeploymentID.toHexString()) - if (subgraphDeployment != null) { - if (event.params.sinceBlock.toI32() == 0) { - subgraphDeployment.deniedAt = 0 - } else { - subgraphDeployment.deniedAt = event.params.sinceBlock.toI32() - } - subgraphDeployment.save() - } - // We might need to handle the case where the subgraph deployment doesn't exists later -} diff --git a/subgraph.template.yaml b/subgraph.template.yaml index 2913aca..1cbb05e 100644 --- a/subgraph.template.yaml +++ b/subgraph.template.yaml @@ -756,6 +756,8 @@ dataSources: eventHandlers: - event: RewardsAssigned(indexed address,indexed address,uint256,uint256) handler: handleRewardsAssigned + - event: HorizonRewardsAssigned(indexed address,indexed address,uint256) + handler: handleHorizonRewardsAssigned - event: RewardsDenylistUpdated(indexed bytes32,uint256) handler: handleRewardsDenyListUpdated # - event: ImplementationUpdated(address,address)