diff --git a/packages/contracts/CHANGELOG.md b/packages/contracts/CHANGELOG.md index 802cff94c..388f30b1f 100644 --- a/packages/contracts/CHANGELOG.md +++ b/packages/contracts/CHANGELOG.md @@ -1,5 +1,11 @@ # @graphprotocol/contracts +## 6.3.0 + +### Minor Changes + +- Remove restriction that prevented closing allocations older than 1 epoch. + ## 6.2.1 ### Patch Changes diff --git a/packages/contracts/addresses-staging.json b/packages/contracts/addresses-staging.json index 8f67d8e2b..11a912d43 100644 --- a/packages/contracts/addresses-staging.json +++ b/packages/contracts/addresses-staging.json @@ -134,12 +134,12 @@ "txHash": "0x5ae51383f5ad1e434a78c2a6d5393d497be315c40287d827c63c4ca48cc66aca", "proxy": true, "implementation": { - "address": "0xC4Cfde877Bc77fD93378D33Ec26330127Ed93bbE", - "creationCodeHash": "0x9319aaf6b70b423fa04ad747f004961123e7833b269f69ecff902db13b010fa2", - "runtimeCodeHash": "0x9a3f54b5f61709d40a71892f241f61fc72cf95346e5d928f1d699ea57065efc4", - "txHash": "0x1e53eadecdb33a8e90e5c9bc3d02d438dd21217c5017b596b3e51f64be4501e2", + "address": "0x0a6b1efb7b2e9A27Cf7C5ED1bdF1Bd03bF8F5600", + "creationCodeHash": "0x60bc1fda6913ef750a1d931e87068d0f6cd62b8b42a4fff13b304b9c0c278557", + "runtimeCodeHash": "0xd8bbd97b94f8ac45a479c55c0416e7b0ebef6a99da8ef7580bebaaad1d8d74d9", + "txHash": "0x5d9276e47f3d1fa1fe5c6d826534722aa73d47f5a114e844de73a3cf0cb22d6b", "libraries": { - "LibExponential": "0x6f6Db03f7F3bBE43669F81FD954Bd083FEdBb4a5" + "LibExponential": "0xb7fB963257d4f31F88021d2D7Ee53688e38A0938" } } }, diff --git a/packages/contracts/addresses.json b/packages/contracts/addresses.json index ae66613a2..076ee8cb0 100644 --- a/packages/contracts/addresses.json +++ b/packages/contracts/addresses.json @@ -705,12 +705,12 @@ "txHash": "0xa33c0d58ddaed7e3f7381a33e3d5f63e39219863019f00d54ce2fd2446076ac7", "proxy": true, "implementation": { - "address": "0x4a886d3E44C7731Dcf888Da704CA5C51ed63DfC8", - "creationCodeHash": "0xa9796308a637b0bfe091f32c1019e4db8efe4bab80788c052fa334e6810c3a98", - "runtimeCodeHash": "0x19d3491cab54b2aae04d05525a532200e946ce9b55573b58f2e3e1606b4514be", - "txHash": "0xc3235306a51c20b28a8b05da69859e03a081a84c9914156c79da07dcc45b3b4e", + "address": "0x0Dae36adCbE384a31309269448E09465B2288429", + "creationCodeHash": "0x7bd2944ba001c51a42d88f89b10eb894e11be62ee96e76331309ff6a8e9b20ff", + "runtimeCodeHash": "0x0808fafef220cfddb64a51f680a18e455d5b7c6b9c0c7aad8f8067f4775dd204", + "txHash": "0x6bdee0f03f74df2b7e6141075b06a88b201cbc78a131aa0fe6bb1ef1da1e2dc1", "libraries": { - "LibExponential": "0x208f638d8804e4ccc874ec39e240feea3dc289ee" + "LibExponential": "0x6F436161bBa439FB7D0A6192D22dd8fcE4C26Fb5" } } }, @@ -1146,12 +1146,12 @@ "txHash": "0x326cf1f2849da4bb4d7e39f2783779e3c99fa48e4ee8ef004cfdd50c62e775df", "proxy": true, "implementation": { - "address": "0xD07dFD514dc1b57020e6C1F49e05c48d0658C99f", - "creationCodeHash": "0x6a763345e5f166ea4e73ce9a116a49c9fc0833d9ea235a86fa5a997e91cf09e5", - "runtimeCodeHash": "0xb4c31859ac132241f04c802d4add70a94c7f2c6eb9dfd4bf224048d249dbc7bc", - "txHash": "0x68b34eda64287b84582c8f005c4e96162252d36c9c5c9b84332336a7c2e3d6d3", + "address": "0x64Ed77b164d3B22339DA4DB6d56a1C1d8A051c0A", + "creationCodeHash": "0x56a3dd587f3f4ae38dd782e9c35125fa7015c708394950de90bc190204502438", + "runtimeCodeHash": "0x9040ccf84a89ba2e7a32eb297f0da148827e7e272b20d9e57b1acf749baa35da", + "txHash": "0xbfec14a2dd1a571612076b71b4f2e78ea18f95d7d80e14cd1456ecaa7466db54", "libraries": { - "LibExponential": "0xd844116f6d79a280b117Bb6d9EBf4121D4e8B44b" + "LibExponential": "0x413d16eF53d3dd8b7e769570115ee5419CF77C98" } } }, diff --git a/packages/contracts/audits/OpenZeppelin/2024-02-graph-availability-manager-minimum-allocation-removal.pdf b/packages/contracts/audits/OpenZeppelin/2024-02-graph-availability-manager-minimum-allocation-removal.pdf new file mode 100644 index 000000000..d41a64e75 Binary files /dev/null and b/packages/contracts/audits/OpenZeppelin/2024-02-graph-availability-manager-minimum-allocation-removal.pdf differ diff --git a/packages/contracts/contracts/staking/Staking.sol b/packages/contracts/contracts/staking/Staking.sol index e9da34440..f00097de2 100644 --- a/packages/contracts/contracts/staking/Staking.sol +++ b/packages/contracts/contracts/staking/Staking.sol @@ -775,18 +775,18 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M // Get allocation Allocation memory alloc = __allocations[_allocationID]; - // Validate that an allocation cannot be closed before one epoch alloc.closedAtEpoch = epochManager().currentEpoch(); + + // Allocation duration in epochs uint256 epochs = MathUtils.diffOrZero(alloc.closedAtEpoch, alloc.createdAtEpoch); - require(epochs > 0, " 0) { // Distribute rewards if proof of indexing was presented by the indexer or operator - if (isIndexer && _poi != 0) { + // and the allocation is at least one epoch old (most indexed chains require the EBO + // posting epoch block numbers to produce a valid POI which happens once per epoch) + if (isIndexerOrOperator && _poi != 0 && epochs > 0) { _distributeRewards(_allocationID, alloc.indexer); } else { _updateRewards(alloc.subgraphDeploymentID); @@ -821,7 +823,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M _allocationID, msg.sender, _poi, - !isIndexer + !isIndexerOrOperator ); } diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 4e95a8f3c..d35c4d33c 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@graphprotocol/contracts", - "version": "6.2.1", + "version": "6.3.0", "description": "Contracts for the Graph Protocol", "directories": { "test": "test" diff --git a/packages/contracts/tasks/contract/deploy.ts b/packages/contracts/tasks/contract/deploy.ts index 3571444d0..33de96863 100644 --- a/packages/contracts/tasks/contract/deploy.ts +++ b/packages/contracts/tasks/contract/deploy.ts @@ -1,4 +1,4 @@ -import { confirm, deploy, DeployType, GraphNetworkAddressBook } from '@graphprotocol/sdk' +import { confirm, deploy, DeployType } from '@graphprotocol/sdk' import { greTask } from '@graphprotocol/sdk/gre' greTask('contract:deploy', 'Deploy a contract') @@ -37,7 +37,7 @@ greTask('contract:deploy', 'Deploy a contract') name: taskArgs.contract, args: taskArgs.init?.split(',') || [], }, - new GraphNetworkAddressBook(taskArgs.addressBook, graph.chainId), + graph.addressBook, ) console.log(`Contract deployed at ${deployment.contract.address}`) }) diff --git a/packages/contracts/test/unit/staking/allocation.test.ts b/packages/contracts/test/unit/staking/allocation.test.ts index 92afedca4..bd930eaba 100644 --- a/packages/contracts/test/unit/staking/allocation.test.ts +++ b/packages/contracts/test/unit/staking/allocation.test.ts @@ -19,6 +19,7 @@ import { toGRT, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { IRewardsManager } from '../../../build/types' const { AddressZero } = constants @@ -93,6 +94,7 @@ describe('Staking:Allocation', () => { let epochManager: EpochManager let grt: GraphToken let staking: IStaking + let rewardsManager: IRewardsManager let libExponential: LibExponential // Test values @@ -375,6 +377,7 @@ describe('Staking:Allocation', () => { epochManager = contracts.EpochManager grt = contracts.GraphToken as GraphToken staking = contracts.Staking as IStaking + rewardsManager = contracts.RewardsManager as IRewardsManager const stakingName = isGraphL1ChainId(graph.chainId) ? 'L1Staking' : 'L2Staking' const entry = graph.addressBook.getEntry(stakingName) @@ -875,9 +878,24 @@ describe('Staking:Allocation', () => { await expect(tx).revertedWith('!active') }) - it('reject close before at least one epoch has passed', async function () { + it('allow close before one epoch has passed', async function () { + const currentEpoch = await epochManager.currentEpoch() + const beforeAlloc = await staking.getAllocation(allocationID) + const tx = staking.connect(indexer).closeAllocation(allocationID, poi) - await expect(tx).revertedWith(' { it('should close an allocation (by public) only if allocation is non-zero', async function () { // Reject to close if public address and under max allocation epochs const tx1 = staking.connect(me).closeAllocation(allocationID, poi) - await expect(tx1).revertedWith('