Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions abis/IssuanceAllocator.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[
{
"anonymous": false,
"inputs": [
{ "indexed": true, "internalType": "address", "name": "target", "type": "address" },
{ "indexed": false, "internalType": "uint256", "name": "newAllocatorMintingRate", "type": "uint256" },
{ "indexed": false, "internalType": "uint256", "name": "newSelfMintingRate", "type": "uint256" }
],
"name": "TargetAllocationUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "uint256", "name": "oldIssuancePerBlock", "type": "uint256" },
{ "indexed": false, "internalType": "uint256", "name": "newIssuancePerBlock", "type": "uint256" }
],
"name": "IssuancePerBlockUpdated",
"type": "event"
},
{
"inputs": [],
"name": "getIssuancePerBlock",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "target", "type": "address" }],
"name": "getTargetAllocation",
"outputs": [
{
"components": [
{ "internalType": "uint256", "name": "totalAllocationRate", "type": "uint256" },
{ "internalType": "uint256", "name": "allocatorMintingRate", "type": "uint256" },
{ "internalType": "uint256", "name": "selfMintingRate", "type": "uint256" }
],
"internalType": "struct IIssuanceAllocationStatus.Allocation",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
}
]
28 changes: 27 additions & 1 deletion abis/RewardsManagerStitched.json
Original file line number Diff line number Diff line change
Expand Up @@ -603,5 +603,31 @@
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getAllocatedIssuancePerBlock",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getIssuanceAllocator",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]
]
2 changes: 2 additions & 0 deletions config/addresses.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class Addresses {
l2GraphTokenGateway: string
ethereumDIDRegistry: string
subgraphService: string
issuanceAllocator: string
graphPayments: string
paymentsEscrow: string
graphTallyCollector: string
Expand Down Expand Up @@ -52,6 +53,7 @@ export let addresses: Addresses = {
l2GraphTokenGateway: '{{l2GraphTokenGateway}}',
ethereumDIDRegistry: '{{ethereumDIDRegistry}}',
subgraphService: '{{subgraphService}}',
issuanceAllocator: '{{issuanceAllocator}}',
graphPayments: '{{graphPayments}}',
paymentsEscrow: '{{paymentsEscrow}}',
graphTallyCollector: '{{graphTallyCollector}}',
Expand Down
9 changes: 8 additions & 1 deletion config/arbitrumSepoliaAddressScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Addresses } from './addresses.template'

const horizonAddresses = require('@graphprotocol/address-book/horizon/addresses.json')
const subgraphServiceAddresses = require('@graphprotocol/address-book/subgraph-service/addresses.json')
const issuanceAddresses = require('@graphprotocol/address-book/issuance/addresses.json')

// mustache doesn't like numbered object keys
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -15,10 +16,15 @@ renameHorizonAddresses['arbsep'] = horizonAddresses['421614']
let renameSubgraphServiceAddresses: any = subgraphServiceAddresses
renameSubgraphServiceAddresses['arbsep'] = subgraphServiceAddresses['421614']

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let renameIssuanceAddresses: any = issuanceAddresses
renameIssuanceAddresses['arbsep'] = issuanceAddresses['421614'] || {}

const combinedAddresses = {
arbsep: {
...renameHorizonAddresses['arbsep'],
...renameSubgraphServiceAddresses['arbsep']
...renameSubgraphServiceAddresses['arbsep'],
...renameIssuanceAddresses['arbsep']
}
}

Expand All @@ -45,6 +51,7 @@ export let addresses: Addresses = {
l2GraphTokenGateway: '{{arbsep.L2GraphTokenGateway.address}}',
ethereumDIDRegistry: '{{arbsep.EthereumDIDRegistry.address}}',
subgraphService: '{{arbsep.SubgraphService.address}}',
issuanceAllocator: '{{arbsep.IssuanceAllocator.address}}',
graphPayments: '{{arbsep.GraphPayments.address}}',
paymentsEscrow: '{{arbsep.PaymentsEscrow.address}}',
graphTallyCollector: '{{arbsep.GraphTallyCollector.address}}',
Expand Down
1 change: 1 addition & 0 deletions config/localNetworkAddressScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Addresses } from './addresses.template'
let renameAddresses: any = {
horizon: horizonAddresses['1337'],
subgraphService: subgraphServiceAddresses['1337'],
issuanceAllocator: '0x0000000000000000000000000000000000000000', // IssuanceAllocator is only deployed on Arbitrum
}

export let addresses: Addresses = {
Expand Down
9 changes: 8 additions & 1 deletion config/mainnetArbitrumAddressScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Addresses } from './addresses.template'

const horizonAddresses = require('@graphprotocol/address-book/horizon/addresses.json')
const subgraphServiceAddresses = require('@graphprotocol/address-book/subgraph-service/addresses.json')
const issuanceAddresses = require('@graphprotocol/address-book/issuance/addresses.json')

// mustache doesn't like numbered object keys
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -14,10 +15,15 @@ renameHorizonAddresses['arbitrum'] = horizonAddresses['42161'] || {}
let renameSubgraphServiceAddresses: any = subgraphServiceAddresses
renameSubgraphServiceAddresses['arbitrum'] = subgraphServiceAddresses['42161'] || {}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let renameIssuanceAddresses: any = issuanceAddresses
renameIssuanceAddresses['arbitrum'] = issuanceAddresses['42161'] || {}

const combinedAddresses = {
arbitrum: {
...renameHorizonAddresses['arbitrum'],
...renameSubgraphServiceAddresses['arbitrum']
...renameSubgraphServiceAddresses['arbitrum'],
...renameIssuanceAddresses['arbitrum']
}
}

Expand All @@ -44,6 +50,7 @@ export let addresses: Addresses = {
l2GraphTokenGateway: '{{arbitrum.L2GraphTokenGateway.address}}',
ethereumDIDRegistry: '{{arbitrum.IEthereumDIDRegistry.address}}',
subgraphService: '{{arbitrum.SubgraphService.address}}',
issuanceAllocator: '{{arbitrum.IssuanceAllocator.address}}',
graphPayments: '{{arbitrum.GraphPayments.address}}',
paymentsEscrow: '{{arbitrum.PaymentsEscrow.address}}',
graphTallyCollector: '{{arbitrum.GraphTallyCollector.address}}',
Expand Down
1 change: 1 addition & 0 deletions config/testAddressesL1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export let addresses: Addresses = {
l2GraphTokenGateway: '',
ethereumDIDRegistry: '0x0000000000000000000000000000000000000000',
subgraphService: '0x0000000000000000000000000000000000000000',
issuanceAllocator: '0x0000000000000000000000000000000000000000',
graphPayments: '0x0000000000000000000000000000000000000000',
paymentsEscrow: '0x0000000000000000000000000000000000000000',
graphTallyCollector: '0x0000000000000000000000000000000000000000',
Expand Down
1 change: 1 addition & 0 deletions config/testAddressesL2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export let addresses: Addresses = {
l2GraphTokenGateway: '0x0000000000000000000000000000000000000000',
ethereumDIDRegistry: '0x0000000000000000000000000000000000000000',
subgraphService: '0x0000000000000000000000000000000000000000',
issuanceAllocator: '0x0000000000000000000000000000000000000000',
graphPayments: '0x0000000000000000000000000000000000000000',
paymentsEscrow: '0x0000000000000000000000000000000000000000',
graphTallyCollector: '0x0000000000000000000000000000000000000000',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"prepare:test-l2": "yarn && yarn prep:addresses:test:l2 && mustache ./config/generatedAddresses.json subgraph.template.yaml > subgraph.yaml && graph codegen --output-dir src/types/"
},
"devDependencies": {
"@graphprotocol/address-book": "1.1.0",
"@graphprotocol/address-book": "^1.3.0",
"@graphprotocol/contracts": "6.2.0",
"@graphprotocol/graph-cli": "0.97.0",
"@graphprotocol/graph-ts": "0.36.0",
Expand Down
34 changes: 34 additions & 0 deletions src/mappings/issuanceAllocator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { TargetAllocationUpdated } from '../types/IssuanceAllocator/IssuanceAllocator'
import { createOrLoadGraphNetwork } from './helpers/helpers'
import { addresses } from '../../config/addresses'
import { Address } from '@graphprotocol/graph-ts'

/**
* @dev handleTargetAllocationUpdated
* - Keeps GraphNetwork.networkGRTIssuancePerBlock in step with the share of
* issuance the RewardsManager actually receives.
*
* Since GIP-0076/GIP-0088 the RewardsManager no longer owns the issuance rate:
* the IssuanceAllocator splits total issuance across targets and the
* RewardsManager mints only its own allocation. GIP-0089 exercised that for the
* first time on 2026-09-01, moving 24.146 GRT/block (20%) to the Foundation's
* Innovation Allocation and leaving the RewardsManager 96.584 of the unchanged
* 120.73 total.
*
* That change is invisible to the RewardsManager's own ParameterUpdated event,
* so without this handler networkGRTIssuancePerBlock stays at whatever the
* legacy `issuancePerBlock` storage slot last held — 120.73 — and every
* downstream APR calculation built on it overstates indexing rewards by 25%.
*
* The RewardsManager is an allocator target that mints its own issuance, so
* `newSelfMintingRate` is the rate it will issue at. The event carries it, so
* no contract call is needed here.
*/
export function handleTargetAllocationUpdated(event: TargetAllocationUpdated): void {
if (event.params.target != Address.fromString(addresses.rewardsManager)) {
return
}
let graphNetwork = createOrLoadGraphNetwork(event.block.number, event.address)
graphNetwork.networkGRTIssuancePerBlock = event.params.newSelfMintingRate
graphNetwork.save()
}
11 changes: 10 additions & 1 deletion src/mappings/rewardsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,16 @@ export function handleParameterUpdated(event: ParameterUpdated): void {
if (parameter == 'issuanceRate') {
graphNetwork.networkGRTIssuance = rewardsManager.issuanceRate()
} else if (parameter == 'issuancePerBlock') {
graphNetwork.networkGRTIssuancePerBlock = rewardsManager.issuancePerBlock()
// Read the allocator-aware rate, not the legacy `issuancePerBlock` slot.
// Since the IssuanceAllocator was wired up (GIP-0088) the RewardsManager
// issues only its own allocation, and the legacy slot is no longer that
// number — on Arbitrum it still reads 120.73 while the allocated rate is
// 96.584. try_ so the call is safe on deployments predating the upgrade,
// where the getter does not exist.
let allocated = rewardsManager.try_getAllocatedIssuancePerBlock()
graphNetwork.networkGRTIssuancePerBlock = allocated.reverted
? rewardsManager.issuancePerBlock()
: allocated.value
} else if (parameter == 'subgraphAvailabilityOracle') {
graphNetwork.subgraphAvailabilityOracle = rewardsManager.subgraphAvailabilityOracle()
}
Expand Down
25 changes: 25 additions & 0 deletions subgraph.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,31 @@ dataSources:
EpochManager.blockNum: EpochManager[{{epochManager}}].blockNum()
- event: AllowedLockedVerifierSet(indexed address,bool)
handler: handleAllowedLockedVerifierSet
# The IssuanceAllocator owns the split of protocol issuance across targets
# (GIP-0076, deployed by GIP-0088). The RewardsManager is one target and mints
# only its own allocation, so this is the only place a change to the indexing
# reward rate is observable — the RewardsManager itself emits nothing when the
# split moves. Arbitrum only; the address resolves empty elsewhere.
- kind: ethereum/contract
name: IssuanceAllocator
network: {{network}}
source:
address: "{{issuanceAllocator}}"
abi: IssuanceAllocator
startBlock: {{blockNumber}}
mapping:
kind: ethereum/events
apiVersion: 0.0.9
language: wasm/assemblyscript
file: ./src/mappings/issuanceAllocator.ts
entities:
- GraphNetwork
abis:
- name: IssuanceAllocator
file: ./abis/IssuanceAllocator.json
eventHandlers:
- event: TargetAllocationUpdated(indexed address,uint256,uint256)
handler: handleTargetAllocationUpdated
- kind: ethereum/contract
name: SubgraphService
network: {{network}}
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -818,10 +818,10 @@
graphql-import-node "^0.0.5"
js-yaml "^4.1.0"

"@graphprotocol/address-book@1.1.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@graphprotocol/address-book/-/address-book-1.1.0.tgz"
integrity sha512-38NiutGOWdDIYgB/3kGp/7LxPRCNomipjo1hGlaj6RvyydySooVSmb3A+j84faUso+uhYxt8+9y1EFN7XVnT7Q==
"@graphprotocol/address-book@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@graphprotocol/address-book/-/address-book-1.3.0.tgz#234de18cd3931c309cf0385d46f88cc6d3a14355"
integrity sha512-rkrgBOOxM5WLNsoVrr6Gvg6DYvDes+P13vL5k1/QYWc5/z/G6pt4DBgzR/7wJV5xhIMevCumpg6L7ZuVQwS0ug==

"@graphprotocol/common-ts@^2.0.7":
version "2.0.11"
Expand Down
Loading