Skip to content

Commit 1f975c9

Browse files
authored
Merge pull request #1345 from graphprotocol/deployment/testnet/2026-06-09/gip-0088
GIP-0088 2026-06-09 testnet deployment
2 parents 3393327 + 14823af commit 1f975c9

76 files changed

Lines changed: 4474 additions & 1487 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/require-audit-label.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ jobs:
2121
per_page: 100
2222
});
2323
24-
// Filter for .sol files, excluding tests
24+
// Filter for .sol files, excluding tests and mocks.
25+
// /mocks/ holds non-production test doubles only (e.g.
26+
// horizon/contracts/mocks, issuance .../eligibility/mocks) — never
27+
// audit scope. Do not place production contracts under a mocks/ dir.
2528
const solFiles = files
2629
.map(f => f.filename)
2730
.filter(f => f.endsWith('.sol'))
2831
.filter(f => !f.includes('/test/'))
2932
.filter(f => !f.includes('/tests/'))
33+
.filter(f => !f.includes('/mocks/'))
3034
.filter(f => !f.endsWith('.t.sol'));
3135
3236
console.log('Non-test Solidity files changed:', solFiles);

.prettierignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ yarn.lock
66
# Dependencies (from .gitignore)
77
node_modules/
88

9-
# Third-party libraries in lib directories
10-
**/lib/
11-
129
# Build outputs (from .gitignore)
1310
**/build/
1411
**/dist/

eslint.config.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ const eslintConfig = [
188188
caughtErrorsIgnorePattern: '^_',
189189
},
190190
],
191+
'no-redeclare': 'off', // Base rule misreads TS function overloads
192+
'@typescript-eslint/no-redeclare': 'error',
191193
},
192194
},
193195

@@ -252,8 +254,6 @@ const eslintConfig = [
252254
// Autogenerated GraphClient files (committed but should not be linted)
253255
'**/.graphclient-extracted/**',
254256
'**/.graphclient/**',
255-
// Third-party dependencies (Forge libraries, etc.)
256-
'**/lib/**',
257257
],
258258
},
259259

packages/contracts-test/tests/unit/lib/fixtures.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
21
import { Controller } from '@graphprotocol/contracts'
32
import { DisputeManager } from '@graphprotocol/contracts'
43
import { EpochManager } from '@graphprotocol/contracts'

packages/deployment/CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Before modifying any deployment scripts in `deploy/`, read:
1919

2020
## Additional Documentation
2121

22+
- [Gip0088.md](docs/Gip0088.md) - GIP-0088 reference guide: scripts, tags, preconditions
23+
- [Gip0088Runbook.md](docs/Gip0088Runbook.md) - GIP-0088 operational runbook: staged, gated execution plan
2224
- [GovernanceWorkflow.md](docs/GovernanceWorkflow.md) - Governance TX generation and execution
2325
- [LocalForkTesting.md](docs/LocalForkTesting.md) - Fork mode testing workflow
2426
- [Architecture.md](docs/Architecture.md) - Package architecture

packages/deployment/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,37 @@ packages/deployment/
5151
│ ├── agreement/ # RecurringAgreementManager
5252
│ ├── rewards/ # RewardsEligibilityOracle, Reclaim
5353
│ └── gip/0088/ # GIP-0088 goal orchestration
54+
├── config/ # Per-network deployment configuration (see Configuration)
5455
├── lib/ # Shared utilities (preconditions, registry, tags, ABIs)
5556
├── tasks/ # Hardhat tasks (deploy:*)
5657
├── docs/ # Documentation
5758
└── test/ # Unit tests
5859
```
5960

61+
## Configuration
62+
63+
Per-network settings live in `config/<network>.json5` (`arbitrumOne.json5`,
64+
`arbitrumSepolia.json5`, `localNetwork.json5`). Each file only contains the
65+
keys that need to differ from defaults; everything else is resolved at
66+
runtime from `DEFAULT_SETTINGS` in [lib/deployment-config.ts](lib/deployment-config.ts).
67+
68+
For the full surface — every available key, its purpose, and its default —
69+
see [config/\_template.json5](config/_template.json5). That file is never
70+
loaded as a real config (no chain matches its basename); it's documentation
71+
and a copy-paste starting point.
72+
73+
The TypeScript schema (`DeploymentConfigFile` and `ResolvedSettings` in
74+
`lib/deployment-config.ts`) is the source of truth — keep the template in
75+
sync when adding new keys.
76+
6077
## Available Tasks
6178

6279
```bash
6380
npx hardhat deploy:status --network arbitrumOne # Show deployment and integration status
6481
npx hardhat deploy:list-pending --network arbitrumOne # List pending implementations
6582
npx hardhat deploy:reset-fork --network localhost # Reset fork state (for testing)
6683
npx hardhat deploy --tags sync --network arbitrumOne # Sync address books with on-chain state
84+
npx hardhat ia:status --network arbitrumOne # Show IssuanceAllocator allocations per target (incl. RAM)
6785
```
6886

6987
## Testing
@@ -77,6 +95,8 @@ FORK_NETWORK=arbitrumSepolia ARBITRUM_SEPOLIA_RPC=<url> pnpm test
7795

7896
## See Also
7997

98+
- [docs/Gip0088.md](./docs/Gip0088.md) - GIP-0088 reference guide: scripts, tags, preconditions
99+
- [docs/Gip0088Runbook.md](./docs/Gip0088Runbook.md) - GIP-0088 operational runbook: staged, gated execution plan
80100
- [docs/deploy/ImplementationPrinciples.md](./docs/deploy/ImplementationPrinciples.md) - Core design principles and patterns
81101
- [docs/Architecture.md](./docs/Architecture.md) - Package structure and tags
82102
- [docs/GovernanceWorkflow.md](./docs/GovernanceWorkflow.md) - Detailed governance workflow
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{
2+
// Per-network deployment configuration template.
3+
//
4+
// Copy this to `<network>.json5` (file name = hardhat network name, see
5+
// CHAIN_CONFIG_MAP in lib/deployment-config.ts) and override only the keys
6+
// that need to differ from the defaults shown below. Anything you omit is
7+
// resolved from `DEFAULT_SETTINGS` at runtime — this file just shows the
8+
// full surface so you don't have to read the TypeScript schema.
9+
//
10+
// This file itself is NEVER loaded as a real config (no chain matches its
11+
// basename); it lives here purely as documentation + a starting point.
12+
//
13+
// Source of truth for shape and defaults: lib/deployment-config.ts.
14+
15+
// ------------------------------------------------------------------------
16+
// IssuanceAllocator — total issuance and per-target allocation table.
17+
// ------------------------------------------------------------------------
18+
IssuanceAllocator: {
19+
// Expected total issuance per block, in GRT, as a string. Scripts
20+
// cross-check this against RM's on-chain `issuancePerBlock()` and error
21+
// on mismatch — config NEVER sets the rate. Omit if no allocations
22+
// are declared. No default.
23+
issuancePerBlock: '6.0365',
24+
25+
// Per-target allocation map, keyed by full contract name. Each rate is a
26+
// string of GRT/block (parsed via parseUnits at 1e18). Unspecified rates
27+
// default to '0'. The values MUST sum to `issuancePerBlock` exactly.
28+
// Targets must be known allocation-target contracts (see
29+
// ALLOCATION_TARGET_CONTRACTS in lib/contract-registry.ts):
30+
// RewardsManager, RecurringAgreementManager, DefaultAllocation,
31+
// ReclaimedRewards, …
32+
// Default: {} (no allocations configured — issuance-allocate is a no-op).
33+
allocations: {
34+
RewardsManager: { selfGrtPerBlock: '5.5365' },
35+
RecurringAgreementManager: { allocatorGrtPerBlock: '0.5' },
36+
// DefaultAllocation: { allocatorGrtPerBlock: '0', selfGrtPerBlock: '0' },
37+
},
38+
},
39+
40+
// ------------------------------------------------------------------------
41+
// RewardsManager — eligibility wiring + revert switch.
42+
// ------------------------------------------------------------------------
43+
RewardsManager: {
44+
// Whether to revert reward claims by ineligible indexers. Applied in
45+
// 04_upgrade's bundled governance batch.
46+
// Default: true.
47+
revertOnIneligible: true,
48+
49+
// Full name of the REO contract RM points at. Omit for no oracle.
50+
// Valid values: 'RewardsEligibilityOracleA' | 'RewardsEligibilityOracleB'
51+
// | 'RewardsEligibilityOracleMock'
52+
// (see ELIGIBILITY_ORACLE_CONTRACTS in lib/contract-registry.ts).
53+
// Default: undefined (no oracle).
54+
eligibilityOracle: 'RewardsEligibilityOracleA',
55+
},
56+
57+
// ------------------------------------------------------------------------
58+
// RecurringAgreementManager — eligibility wiring.
59+
// ------------------------------------------------------------------------
60+
RecurringAgreementManager: {
61+
// Full name of the REO contract RAM points at. Omit for no oracle.
62+
// Valid values: same as RewardsManager.eligibilityOracle above.
63+
// Default: undefined (no oracle).
64+
eligibilityOracle: 'RewardsEligibilityOracleA',
65+
},
66+
67+
// ------------------------------------------------------------------------
68+
// RecurringCollector — constructor + initializer args.
69+
// ------------------------------------------------------------------------
70+
// These are immutable after deployment (constructor / initializer args),
71+
// so a change here only affects fresh deployments.
72+
RecurringCollector: {
73+
// Signer revocation thaw period in seconds, as a string.
74+
// Default: '28800' (≈8 hours at 3s blocks).
75+
revokeSignerThawingPeriod: '28800',
76+
77+
// EIP-712 domain name (initializer arg).
78+
// Default: 'RecurringCollector'.
79+
eip712Name: 'RecurringCollector',
80+
81+
// EIP-712 domain version (initializer arg).
82+
// Default: '1'.
83+
eip712Version: '1',
84+
},
85+
86+
// ------------------------------------------------------------------------
87+
// RewardsEligibilityOracle — duration parameters written at configure time.
88+
// ------------------------------------------------------------------------
89+
// Applied via `getREOConditions(env)` to each deployed REO instance during
90+
// `GIP-0088:RewardsEligibilityOracleA:configure` (and …B). Re-configurable
91+
// later by governance via setEligibilityPeriod / setOracleUpdateTimeout.
92+
RewardsEligibilityOracle: {
93+
// Eligibility period in seconds, as a string. Indexers fall out of
94+
// eligibility this long after their last positive attestation.
95+
// Default: '1209600' (14 days).
96+
eligibilityPeriod: '1209600',
97+
98+
// Oracle update timeout in seconds, as a string. All indexers go
99+
// ineligible after this long without any oracle update.
100+
// Default: '604800' (7 days).
101+
oracleUpdateTimeout: '604800',
102+
},
103+
104+
// ------------------------------------------------------------------------
105+
// SubgraphService — optional close-guard switch.
106+
// ------------------------------------------------------------------------
107+
SubgraphService: {
108+
// When true, allocations with active indexing agreements cannot be
109+
// closed. Applied by the `GIP-0088:issuance-close-guard` optional goal;
110+
// not part of the mandatory rollout (`GIP-0088,all`).
111+
// Default: true.
112+
blockClosingAllocationWithActiveAgreement: true,
113+
},
114+
}
Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
{
22
// Deployment configuration for Arbitrum One (mainnet)
3-
// Values here are committed for reference and reproducibility.
3+
4+
RewardsManager: {
5+
eligibilityOracle: 'RewardsEligibilityOracleA',
6+
},
47

58
IssuanceAllocator: {
6-
// RAM allocation: how much issuance flows to RecurringAgreementManager
7-
// ramAllocatorMintingGrtPerBlock: GRT per block minted by IA and sent to RAM
8-
// ramSelfMintingGrtPerBlock: 0 (RAM does not self-mint)
9-
ramAllocatorMintingGrtPerBlock: '6',
10-
ramSelfMintingGrtPerBlock: '0',
9+
// Explicit issuance allocation table, by target contract name. The rates must
10+
// sum to issuancePerBlock, which must equal RM's on-chain issuance rate — the
11+
// scripts error on mismatch and never set the rate from config.
12+
//
13+
// issuancePerBlock is RM's live on-chain rate (120.73 GRT/block). RAM keeps
14+
// its intended 6; RM self-mints the remainder (120.73 - 6 = 114.73).
15+
issuancePerBlock: '120.73',
16+
allocations: {
17+
RewardsManager: { selfGrtPerBlock: '114.73' },
18+
RecurringAgreementManager: { allocatorGrtPerBlock: '6' },
19+
},
1120
},
1221
}
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
{
22
// Deployment configuration for Arbitrum Sepolia (testnet)
3-
// Values here are committed for reference and reproducibility.
3+
4+
RewardsManager: {
5+
eligibilityOracle: 'RewardsEligibilityOracleMock',
6+
},
47

58
IssuanceAllocator: {
6-
// RAM allocation: how much issuance flows to RecurringAgreementManager
7-
// ramAllocatorMintingGrtPerBlock: GRT per block minted by IA and sent to RAM
8-
// ramSelfMintingGrtPerBlock: GRT per block (0 = RAM does not self-mint)
9-
ramAllocatorMintingGrtPerBlock: '0.5',
10-
ramSelfMintingGrtPerBlock: '0',
9+
// Explicit issuance allocation table, by target contract name. The rates must
10+
// sum to issuancePerBlock, which must equal RM's on-chain issuance rate — the
11+
// scripts error on mismatch and never set the rate from config.
12+
issuancePerBlock: '6.0365',
13+
allocations: {
14+
RewardsManager: { selfGrtPerBlock: '5.5365' },
15+
RecurringAgreementManager: { allocatorGrtPerBlock: '0.5' },
16+
},
1117
},
1218
}

packages/deployment/config/localNetwork.json5

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,25 @@
22
// Deployment configuration for local-network (docker-compose dev stack)
33
// Local network uses generous rates for fast iteration and testing.
44

5+
RewardsManager: {
6+
eligibilityOracle: 'RewardsEligibilityOracleMock',
7+
},
8+
59
IssuanceAllocator: {
6-
// RAM allocation: how much issuance flows to RecurringAgreementManager
7-
// Local network uses a high rate so agreements accumulate meaningful rewards quickly
8-
ramAllocatorMintingGrtPerBlock: '6',
9-
ramSelfMintingGrtPerBlock: '0',
10+
// Explicit issuance allocation table, by target contract name. The rates must
11+
// sum to issuancePerBlock, which must equal RM's on-chain issuance rate — the
12+
// scripts error on mismatch and never set the rate from config.
13+
//
14+
// TODO(local): set issuancePerBlock to the running local stack's actual RM
15+
// rate — read it with `cast call <RM> "issuancePerBlock()(uint256)"` against
16+
// the local node (the repo's graph.*localhost*.yml candidates disagree:
17+
// 6.0365 vs 114.6935, so don't assume). Then add the RewardsManager self
18+
// allocation so the table sums to it. Until both are filled, issuance-allocate
19+
// errors by design rather than allocating partially.
20+
// issuancePerBlock: '<RM issuancePerBlock>',
21+
allocations: {
22+
RecurringAgreementManager: { allocatorGrtPerBlock: '6' },
23+
// RewardsManager: { selfGrtPerBlock: '<issuancePerBlock - 6>' },
24+
},
1025
},
1126
}

0 commit comments

Comments
 (0)