Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
df9a846
docs: update audit extracts for PR1301 v02 report
RembrandtK Apr 17, 2026
3ceb156
fix(collector): add gas overhead buffer to callback prechecks (TRST-L-9)
RembrandtK Apr 17, 2026
35f3456
fix(collector): cap returndata copy in payer callbacks (TRST-M-4)
RembrandtK Apr 17, 2026
46c3d94
docs: add response to TRST-L-10 EIP-7702 callback dispatch (won't fix)
RembrandtK Apr 17, 2026
5e2fa0a
feat(RAM): drop pair tracking below residual escrow threshold (TRST-M…
RembrandtK Apr 17, 2026
a76efa8
docs: add responses to TRST-L-6, TRST-R-7 (both won't fix)
RembrandtK Apr 19, 2026
4651d25
docs(audit): acknowledge TRST-R-3 cancelAgreement defensive check
RembrandtK Apr 20, 2026
eae04c9
fix(collector): remove dead oldHash guard (TRST-R-6)
RembrandtK Apr 20, 2026
94d2695
fix(collector): non-zero offer types, reserve OFFER_TYPE_NONE=0 senti…
RembrandtK Apr 19, 2026
9fa57f8
refactor(interfaces): drop unused state and offer-option flags, tight…
RembrandtK Apr 19, 2026
5345ec1
docs(audit): acknowledge trust-boundary correction in TRST-H-4
RembrandtK Apr 19, 2026
ac65e1f
docs(audit): acknowledge reclaim-reason change in TRST-R-13
RembrandtK Apr 19, 2026
8ed95e4
docs(ram): document collector replay-protection assumption (TRST-R-4)
RembrandtK Apr 19, 2026
6a65df7
docs(ram): document non-retroactive role-change semantics (TRST-R-10)
RembrandtK Apr 19, 2026
98ebd20
docs(ram): align pause-escalation prose with whenNotPaused scope (TRS…
RembrandtK Apr 19, 2026
879489d
docs(collector): note self-authorization auth-check obligation (TRST-…
RembrandtK Apr 19, 2026
244d49e
fix(subgraph-service): validate update terms against RCAU rate, not s…
RembrandtK Apr 21, 2026
498b174
refactor(collector): preparatory cleanups
RembrandtK Apr 22, 2026
747ddcb
refactor(collector): drop unreachable agreementId-zero check
RembrandtK Apr 21, 2026
4a286e1
refactor(collector): hoist dataService check from _validateAndStoreAg…
RembrandtK Apr 21, 2026
f9bdf46
refactor(collector): extract _requireValidTerms from duplicated valid…
RembrandtK Apr 21, 2026
4f93f8d
refactor(collector): split accept logic out of _validateAndStoreAgree…
RembrandtK Apr 21, 2026
85e4007
refactor(collector): split update apply out of _validateAndStoreUpdate
RembrandtK Apr 21, 2026
9111993
feat: idempotent accept/update/cancel with allocation rebinding
RembrandtK Apr 21, 2026
058bdb7
refactor(collector): hoist payer check from _offerNew/_offerUpdate in…
RembrandtK Apr 21, 2026
b869e25
refactor(collector): cleanup and reject expired offers at offer() time
RembrandtK Apr 22, 2026
c078589
fix(collector): validate offer terms against deadline, not block.time…
RembrandtK Apr 22, 2026
6cd4775
feat(collector): hash-keyed decoded terms with version-indexed views …
RembrandtK Apr 22, 2026
03038e1
feat(collector): compose cancel/settled flags in getAgreementDetails …
RembrandtK Apr 19, 2026
4a554f2
feat(collector): add SCOPE_SIGNED to cancel() for EOA offer revocatio…
RembrandtK Apr 19, 2026
a9c2737
feat(contracts): add getIssuanceAllocator to IIssuanceTarget interface
RembrandtK Apr 10, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ describe('RewardsManager interfaces', () => {
})

it('IIssuanceTarget should have stable interface ID', () => {
expect(IIssuanceTarget__factory.interfaceId).to.equal('0xaee4dc43')
expect(IIssuanceTarget__factory.interfaceId).to.equal('0x19f6601a')
})

it('IRewardsManager should have stable interface ID', () => {
expect(IRewardsManager__factory.interfaceId).to.equal('0x337b092e')
expect(IRewardsManager__factory.interfaceId).to.equal('0x8469b577')
})
})

Expand Down
17 changes: 9 additions & 8 deletions packages/contracts/contracts/rewards/RewardsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -173,24 +173,25 @@ contract RewardsManager is
* Note that the IssuanceAllocator can be set to the zero address to disable use of an allocator, and
* use the local `issuancePerBlock` variable instead to control issuance.
*/
function setIssuanceAllocator(address newIssuanceAllocator) external override onlyGovernor {
if (address(issuanceAllocator) != newIssuanceAllocator) {
function setIssuanceAllocator(IIssuanceAllocationDistribution newIssuanceAllocator) external override onlyGovernor {
if (issuanceAllocator != newIssuanceAllocator) {
// Update rewards calculation before changing the issuance allocator
updateAccRewardsPerSignal();

// Check that the contract supports the IIssuanceAllocationDistribution interface
// Allow zero address to disable the allocator
if (newIssuanceAllocator != address(0)) {
if (address(newIssuanceAllocator) != address(0)) {
// solhint-disable-next-line gas-small-strings
require(
IERC165(newIssuanceAllocator).supportsInterface(type(IIssuanceAllocationDistribution).interfaceId),
IERC165(address(newIssuanceAllocator)).supportsInterface(
type(IIssuanceAllocationDistribution).interfaceId
),
"Contract does not support IIssuanceAllocationDistribution interface"
);
}

address oldIssuanceAllocator = address(issuanceAllocator);
issuanceAllocator = IIssuanceAllocationDistribution(newIssuanceAllocator);
emit IssuanceAllocatorSet(oldIssuanceAllocator, newIssuanceAllocator);
emit IssuanceAllocatorSet(issuanceAllocator, newIssuanceAllocator);
issuanceAllocator = newIssuanceAllocator;
}
}

Expand Down Expand Up @@ -325,7 +326,7 @@ contract RewardsManager is
}

/**
* @inheritdoc IRewardsManager
* @inheritdoc IIssuanceTarget
*/
function getIssuanceAllocator() external view override returns (IIssuanceAllocationDistribution) {
return issuanceAllocator;
Expand Down
10 changes: 5 additions & 5 deletions packages/deployment/lib/abis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ function loadAbi(artifactPath: string): Abi {
return artifact.abi as Abi
}

// Interface IDs - these match the generated values from TypeChain factories
// Verified by tests: packages/issuance/testing/tests/allocate/InterfaceIdStability.test.ts
// and packages/contracts-test/tests/unit/rewards/rewards-interface.test.ts
// Interface IDs - these mirror the values the compiler derives from the
// corresponding ABI. Cross-checked by test/interface-id-stability.test.ts;
// update both together whenever an interface changes.
export const IERC165_INTERFACE_ID = '0x01ffc9a7' as const
export const IISSUANCE_TARGET_INTERFACE_ID = '0xaee4dc43' as const
export const IREWARDS_MANAGER_INTERFACE_ID = '0xa0a2f219' as const
export const IISSUANCE_TARGET_INTERFACE_ID = '0x19f6601a' as const
export const IREWARDS_MANAGER_INTERFACE_ID = '0x8469b577' as const

export const REWARDS_MANAGER_ABI = loadAbi(
'@graphprotocol/interfaces/artifacts/contracts/contracts/rewards/IRewardsManager.sol/IRewardsManager.json',
Expand Down
34 changes: 34 additions & 0 deletions packages/deployment/test/interface-id-stability.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect } from 'chai'
import type { Abi } from 'viem'
import { toFunctionSelector } from 'viem'

import {
IERC165_ABI,
IERC165_INTERFACE_ID,
IISSUANCE_TARGET_INTERFACE_ID,
IREWARDS_MANAGER_INTERFACE_ID,
ISSUANCE_TARGET_ABI,
REWARDS_MANAGER_ABI,
} from '../lib/abis.js'

function computeInterfaceId(abi: Abi): `0x${string}` {
const xor = abi
.filter((item): item is Extract<(typeof abi)[number], { type: 'function' }> => item.type === 'function')
.map((f) => Number.parseInt(toFunctionSelector(f).slice(2), 16) >>> 0)
.reduce((a, s) => (a ^ s) >>> 0, 0)
return `0x${xor.toString(16).padStart(8, '0')}`
}

describe('Interface ID Stability', function () {
it('IERC165_INTERFACE_ID matches the IERC165 ABI', function () {
expect(IERC165_INTERFACE_ID).to.equal(computeInterfaceId(IERC165_ABI))
})

it('IISSUANCE_TARGET_INTERFACE_ID matches the IIssuanceTarget ABI', function () {
expect(IISSUANCE_TARGET_INTERFACE_ID).to.equal(computeInterfaceId(ISSUANCE_TARGET_ABI))
})

it('IREWARDS_MANAGER_INTERFACE_ID matches the IRewardsManager ABI', function () {
expect(IREWARDS_MANAGER_INTERFACE_ID).to.equal(computeInterfaceId(REWARDS_MANAGER_ABI))
})
})
Loading
Loading