Skip to content

Commit ada3155

Browse files
authored
Merge pull request #1279 from graphprotocol/issuance-audit
Update rewards reclaiming, audited
2 parents 3189519 + aa08230 commit ada3155

File tree

96 files changed

+4987
-1086
lines changed

Some content is hidden

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

96 files changed

+4987
-1086
lines changed

.github/actions/setup/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ runs:
1717
- name: Install Node.js
1818
uses: actions/setup-node@v4
1919
with:
20-
node-version: 20
20+
node-version: 22
2121
cache: 'pnpm'
2222
- name: Set up pnpm via Corepack
2323
shell: bash

docs/CompilerUpgrade0833.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Compiler Upgrade: Solidity 0.8.33 + viaIR
2+
3+
This document captures the bytecode size changes resulting from the compiler configuration upgrade in the `subgraph-service` and `issuance` packages.
4+
5+
## Configuration Changes
6+
7+
### subgraph-service
8+
9+
| Setting | Before | After |
10+
| ---------------- | ------- | ------- |
11+
| Solidity Version | 0.8.27 | 0.8.33 |
12+
| EVM Version | paris | cancun |
13+
| Optimizer | enabled | enabled |
14+
| Optimizer Runs | 10 | 100 |
15+
| viaIR | false | true |
16+
17+
### issuance
18+
19+
| Setting | Before | After |
20+
| ---------------- | ------- | ------- |
21+
| Solidity Version | 0.8.27 | 0.8.33 |
22+
| EVM Version | cancun | cancun |
23+
| Optimizer | enabled | enabled |
24+
| Optimizer Runs | 100 | 100 |
25+
| viaIR | false | true |
26+
27+
## Subgraph-Service Contract Bytecode Sizes
28+
29+
All contracts defined in `packages/subgraph-service/contracts/`:
30+
31+
| Contract | Source File | Before (KiB) | After (KiB) | Change (KiB) | Change (%) |
32+
| --------------------------- | ------------------------------------------------- | ------------ | ----------- | ------------ | ---------- |
33+
| **SubgraphService** | contracts/SubgraphService.sol | 24.455 | 23.110 | **-1.345** | -5.5% |
34+
| **DisputeManager** | contracts/DisputeManager.sol | 13.278 | 10.917 | **-2.361** | -17.8% |
35+
| Allocation | contracts/libraries/Allocation.sol | 0.084 | 0.056 | -0.028 | -33.3% |
36+
| Attestation | contracts/libraries/Attestation.sol | 0.084 | 0.056 | -0.028 | -33.3% |
37+
| LegacyAllocation | contracts/libraries/LegacyAllocation.sol | 0.084 | 0.056 | -0.028 | -33.3% |
38+
| SubgraphServiceV1Storage | contracts/SubgraphServiceStorage.sol | (abstract) | (abstract) | - | - |
39+
| DisputeManagerV1Storage | contracts/DisputeManagerStorage.sol | (abstract) | (abstract) | - | - |
40+
| AllocationManager | contracts/utilities/AllocationManager.sol | (abstract) | (abstract) | - | - |
41+
| AllocationManagerV1Storage | contracts/utilities/AllocationManagerStorage.sol | (abstract) | (abstract) | - | - |
42+
| AttestationManager | contracts/utilities/AttestationManager.sol | (abstract) | (abstract) | - | - |
43+
| AttestationManagerV1Storage | contracts/utilities/AttestationManagerStorage.sol | (abstract) | (abstract) | - | - |
44+
| Directory | contracts/utilities/Directory.sol | (abstract) | (abstract) | - | - |
45+
46+
### Initcode Size (Subgraph-Service Contracts)
47+
48+
| Contract | Before (KiB) | After (KiB) | Change (KiB) |
49+
| ------------------- | ------------ | ----------- | ------------ |
50+
| **SubgraphService** | 26.109 | 24.894 | **-1.215** |
51+
| **DisputeManager** | 14.649 | 12.342 | **-2.307** |
52+
53+
## Issuance Contract Bytecode Sizes
54+
55+
All contracts defined in `packages/issuance/contracts/`:
56+
57+
| Contract | Source File | Before (KiB) | After (KiB) | Change (KiB) | Change (%) |
58+
| ---------------------------- | -------------------------------------------------- | ------------ | ----------- | ------------ | ---------- |
59+
| **IssuanceAllocator** | contracts/allocate/IssuanceAllocator.sol | 10.444 | 10.250 | **-0.194** | -1.9% |
60+
| **RewardsEligibilityOracle** | contracts/eligibility/RewardsEligibilityOracle.sol | 4.316 | 4.554 | +0.238 | +5.5% |
61+
| **DirectAllocation** | contracts/allocate/DirectAllocation.sol | 2.978 | 3.393 | +0.415 | +13.9% |
62+
| BaseUpgradeable | contracts/common/BaseUpgradeable.sol | (abstract) | (abstract) | - | - |
63+
64+
### Initcode Size (Issuance Contracts)
65+
66+
| Contract | Before (KiB) | After (KiB) | Change (KiB) |
67+
| ---------------------------- | ------------ | ----------- | ------------ |
68+
| **IssuanceAllocator** | 10.817 | 10.601 | **-0.216** |
69+
| **RewardsEligibilityOracle** | 4.666 | 4.881 | +0.215 |
70+
| **DirectAllocation** | 3.330 | 3.723 | +0.393 |
71+
72+
### Test Contracts (Issuance)
73+
74+
| Contract | Before (KiB) | After (KiB) | Change (KiB) |
75+
| ---------------------------- | ------------ | ----------- | ------------ |
76+
| IssuanceAllocatorTestHarness | 10.641 | 10.331 | -0.310 |
77+
| MockReentrantTarget | 1.886 | 1.535 | -0.351 |
78+
| MockNotificationTracker | 0.495 | 0.438 | -0.057 |
79+
| MockRevertingTarget | 0.342 | 0.250 | -0.092 |
80+
| MockSimpleTarget | 0.293 | 0.237 | -0.056 |
81+
| MockERC165 | 0.188 | 0.141 | -0.047 |
82+
83+
## Dependency Library Sizes
84+
85+
Libraries from horizon and other packages compiled as part of subgraph-service:
86+
87+
### Horizon Libraries
88+
89+
| Library | Before (KiB) | After (KiB) | Change (KiB) |
90+
| ---------------- | ------------ | ----------- | ------------ |
91+
| LinkedList | 0.084 | 0.056 | -0.028 |
92+
| TokenUtils | 0.084 | 0.056 | -0.028 |
93+
| UintRange | 0.084 | 0.056 | -0.028 |
94+
| MathUtils | 0.084 | 0.056 | -0.028 |
95+
| PPMMath | 0.084 | 0.056 | -0.028 |
96+
| ProvisionTracker | 0.084 | 0.056 | -0.028 |
97+
98+
### OpenZeppelin Libraries
99+
100+
| Library | Before (KiB) | After (KiB) | Change (KiB) |
101+
| ---------------- | ------------ | ----------- | ------------ |
102+
| Address | 0.084 | 0.056 | -0.028 |
103+
| Panic | 0.084 | 0.056 | -0.028 |
104+
| Strings | 0.084 | 0.056 | -0.028 |
105+
| Errors | 0.084 | 0.056 | -0.028 |
106+
| MessageHashUtils | 0.084 | 0.056 | -0.028 |
107+
| SafeCast | 0.084 | 0.056 | -0.028 |
108+
| ECDSA | 0.084 | 0.056 | -0.028 |
109+
| SignedMath | 0.084 | 0.056 | -0.028 |
110+
| Math | 0.084 | 0.056 | -0.028 |
111+
112+
### Interfaces Package
113+
114+
| Contract | Before (KiB) | After (KiB) | Change (KiB) |
115+
| ---------------- | ------------ | ----------- | ------------ |
116+
| RewardsCondition | 0.458 | 0.520 | +0.062 |
117+
118+
## Key Observations
119+
120+
### subgraph-service
121+
122+
1. **SubgraphService now fits within mainnet limit**: The 24 KiB contract size limit was exceeded before (24.455 KiB). After the upgrade, it's safely under at 23.110 KiB.
123+
124+
2. **Significant savings on main contracts**: Despite increasing optimizer runs from 10 to 100 (which typically increases size for runtime gas savings), the viaIR pipeline produced smaller bytecode:
125+
- SubgraphService: -1.345 KiB (-5.5%)
126+
- DisputeManager: -2.361 KiB (-17.8%)
127+
128+
3. **Abstract contracts have no bytecode**: Storage contracts (e.g., `SubgraphServiceV1Storage`), utility contracts (`AllocationManager`, `AttestationManager`, `Directory`) are inherited by deployable contracts and have no standalone bytecode.
129+
130+
4. **Library stub sizes reduced**: All library stubs decreased from 0.084 KiB to 0.056 KiB (-33%), indicating more efficient metadata encoding.
131+
132+
### issuance
133+
134+
1. **IssuanceAllocator reduced**: The main contract decreased slightly (-0.194 KiB, -1.9%) with viaIR enabled.
135+
136+
2. **Smaller contracts increased**: DirectAllocation (+13.9%) and RewardsEligibilityOracle (+5.5%) increased in size. This is expected behavior as viaIR optimizations are more effective on larger contracts with complex inheritance patterns.
137+
138+
3. **Test contracts all decreased**: All mock/test contracts benefited from viaIR, showing -5% to -19% reductions.
139+
140+
## Why viaIR Reduces Size
141+
142+
The viaIR (Intermediate Representation) compilation pipeline:
143+
144+
- Uses Yul as an intermediate language
145+
- Enables more aggressive cross-function optimizations
146+
- Removes redundant code paths more effectively
147+
- Particularly beneficial for large contracts with complex inheritance
148+
149+
## Date
150+
151+
Comparison performed: 2026-01-25
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# IGraphProxyAdmin Interface Signature Fix
2+
3+
## Issue
4+
5+
The IGraphProxyAdmin interface in `packages/interfaces/contracts/contracts/upgrades/IGraphProxyAdmin.sol` had incorrect function signatures that didn't match the actual GraphProxyAdmin contract implementation.
6+
7+
### Understanding the Two Different `acceptProxy` Methods
8+
9+
There are **two different contracts** with similar-sounding methods, which can cause confusion:
10+
11+
1. **GraphUpgradeable** (base class for implementation contracts):
12+
13+
```solidity
14+
// Called ON the implementation contract
15+
function acceptProxy(IGraphProxy _proxy) external onlyProxyAdmin(_proxy) {
16+
_proxy.acceptUpgrade();
17+
}
18+
```
19+
20+
This is inherited by implementation contracts like RewardsManager, Staking, etc.
21+
22+
2. **GraphProxyAdmin** (admin contract that manages upgrades):
23+
24+
```solidity
25+
// Called ON the admin contract, which then calls the implementation
26+
function acceptProxy(GraphUpgradeable _implementation, IGraphProxy _proxy) external onlyGovernor {
27+
_implementation.acceptProxy(_proxy);
28+
}
29+
```
30+
31+
This is the admin contract that orchestrates upgrades.
32+
33+
**IGraphProxyAdmin represents the second one** - the GraphProxyAdmin admin contract, not the GraphUpgradeable base class.
34+
35+
### Incorrect Interface (Before)
36+
37+
The interface mistakenly used the single-parameter signature from GraphUpgradeable:
38+
39+
```solidity
40+
function acceptProxy(IGraphProxy proxy) external;
41+
42+
function acceptProxyAndCall(IGraphProxy proxy, bytes calldata data) external;
43+
```
44+
45+
### Actual GraphProxyAdmin Implementation
46+
47+
From `packages/contracts/contracts/upgrades/GraphProxyAdmin.sol`:
48+
49+
```solidity
50+
function acceptProxy(GraphUpgradeable _implementation, IGraphProxy _proxy) external onlyGovernor {
51+
_implementation.acceptProxy(_proxy);
52+
}
53+
54+
function acceptProxyAndCall(
55+
GraphUpgradeable _implementation,
56+
IGraphProxy _proxy,
57+
bytes calldata _data
58+
) external onlyGovernor {
59+
_implementation.acceptProxyAndCall(_proxy, _data);
60+
}
61+
```
62+
63+
The interface was **missing the first parameter** (`implementation` address) from both functions. It had copied the signature from GraphUpgradeable instead of using the correct GraphProxyAdmin signature.
64+
65+
## Impact
66+
67+
### Why This Mattered
68+
69+
The deployment package (`@graphprotocol/deployment`) needs to call `acceptProxy` with the correct signature to upgrade proxy contracts. The function requires TWO parameters:
70+
71+
1. The implementation contract address
72+
2. The proxy contract address
73+
74+
Because the interface was wrong, the deployment code had to work around it by loading the full contract ABI instead of using the cleaner interface ABI:
75+
76+
```typescript
77+
// packages/deployment/lib/abis.ts (old workaround)
78+
// Note: Load from actual contract, not interface, because IGraphProxyAdmin is outdated
79+
// Interface shows: acceptProxy(IGraphProxy proxy)
80+
// Contract has: acceptProxy(GraphUpgradeable _implementation, IGraphProxy _proxy)
81+
export const GRAPH_PROXY_ADMIN_ABI = loadAbi(
82+
'@graphprotocol/contracts/artifacts/contracts/upgrades/GraphProxyAdmin.sol/GraphProxyAdmin.json',
83+
)
84+
```
85+
86+
### Why Horizon is Not Affected
87+
88+
GraphDirectory in horizon (`packages/horizon/contracts/utilities/GraphDirectory.sol`) imports and uses IGraphProxyAdmin, but **only as a type reference**:
89+
90+
```solidity
91+
IGraphProxyAdmin private immutable GRAPH_PROXY_ADMIN;
92+
93+
constructor(address controller) {
94+
GRAPH_PROXY_ADMIN = IGraphProxyAdmin(_getContractFromController("GraphProxyAdmin"));
95+
}
96+
97+
function _graphProxyAdmin() internal view returns (IGraphProxyAdmin) {
98+
return GRAPH_PROXY_ADMIN;
99+
}
100+
```
101+
102+
GraphDirectory:
103+
104+
- Stores the address as an immutable reference
105+
- Returns it via a getter function
106+
- **Never calls any methods on IGraphProxyAdmin** (like `acceptProxy`)
107+
108+
Since horizon doesn't call the methods, fixing the interface signature doesn't break horizon.
109+
110+
## Fix Applied
111+
112+
### Updated Interface
113+
114+
```solidity
115+
/**
116+
* @notice Accept ownership of a proxy contract
117+
* @param implementation The implementation contract accepting the proxy
118+
* @param proxy The proxy contract to accept
119+
*/
120+
function acceptProxy(address implementation, IGraphProxy proxy) external;
121+
122+
/**
123+
* @notice Accept ownership of a proxy contract and call a function
124+
* @param implementation The implementation contract accepting the proxy
125+
* @param proxy The proxy contract to accept
126+
* @param data The calldata to execute after accepting
127+
*/
128+
function acceptProxyAndCall(address implementation, IGraphProxy proxy, bytes calldata data) external;
129+
```
130+
131+
**Notes on parameter type choice:**
132+
133+
- Used `address` instead of `GraphUpgradeable` for the implementation parameter
134+
- This avoids creating a dependency from interfaces package to contracts package
135+
- The actual contract uses `GraphUpgradeable`, but `address` is compatible (Solidity allows passing addresses for contract types)
136+
- The ABI encoding is identical - both produce the same function selector and parameter encoding
137+
138+
**Call flow for context:**
139+
140+
```
141+
Deployer/Governor
142+
→ GraphProxyAdmin.acceptProxy(implAddress, proxyAddress) ← IGraphProxyAdmin represents THIS
143+
→ implAddress.acceptProxy(proxyAddress) ← GraphUpgradeable provides this
144+
→ proxyAddress.acceptUpgrade()
145+
```
146+
147+
### Updated Deployment Code
148+
149+
Removed the workaround comment and switched to using the interface:
150+
151+
```typescript
152+
// packages/deployment/lib/abis.ts (now clean)
153+
export const GRAPH_PROXY_ADMIN_ABI = loadAbi(
154+
'@graphprotocol/interfaces/artifacts/contracts/contracts/upgrades/IGraphProxyAdmin.sol/IGraphProxyAdmin.json',
155+
)
156+
```
157+
158+
## Files Changed
159+
160+
1. `packages/interfaces/contracts/contracts/upgrades/IGraphProxyAdmin.sol`
161+
- Fixed `acceptProxy` signature
162+
- Fixed `acceptProxyAndCall` signature
163+
164+
2. `packages/deployment/lib/abis.ts`
165+
- Removed workaround comment
166+
- Changed to load from interface instead of full contract
167+
168+
## Testing
169+
170+
Build verification:
171+
172+
- ✅ interfaces package builds successfully
173+
- ✅ deployment package dependencies build successfully
174+
- ✅ No TypeScript compilation errors
175+
- ✅ Hardhat compilation successful
176+
177+
The deployment code in `packages/deployment/lib/upgrade-implementation.ts` already calls acceptProxy with both parameters:
178+
179+
```typescript
180+
const acceptData = encodeFunctionData({
181+
abi: GRAPH_PROXY_ADMIN_ABI,
182+
functionName: 'acceptProxy',
183+
args: [pendingImpl as `0x${string}`, proxyAddress as `0x${string}`],
184+
})
185+
```
186+
187+
This call now works with the corrected interface ABI.
188+
189+
## Recommendation
190+
191+
This fix should be safe to merge. The interface now accurately reflects the actual contract implementation, and no existing code is broken by the change since:
192+
193+
1. Deployment already expects the two-parameter signature
194+
2. Horizon only uses the type, never calls the methods
195+
3. The fix aligns the interface with reality, reducing confusion
196+
197+
## Questions for Team Review
198+
199+
1. Are there other consumers of IGraphProxyAdmin that might be affected?
200+
2. Should this be considered a breaking change requiring a major version bump of @graphprotocol/interfaces?
201+
3. Is there a reason the interface was historically wrong (legacy compatibility concerns)?

0 commit comments

Comments
 (0)