Skip to content

Allow anyone to close allocation after max allocation period #543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 3 additions & 5 deletions contracts/staking/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ contract Staking is StakingV2Storage, GraphUpgradeable, IStaking {
* An amount of `tokens` get unallocated from `subgraphDeploymentID`.
* The `effectiveAllocation` are the tokens allocated from creation to closing.
* This event also emits the POI (proof of indexing) submitted by the indexer.
* `isDelegator` is true if the sender was one of the indexer's delegators.
* `isPublic` is true if the sender was someone other than the indexer.
*/
event AllocationClosed(
address indexed indexer,
Expand All @@ -145,7 +145,7 @@ contract Staking is StakingV2Storage, GraphUpgradeable, IStaking {
uint256 effectiveAllocation,
address sender,
bytes32 poi,
bool isDelegator
bool isPublic
);

/**
Expand Down Expand Up @@ -1176,9 +1176,7 @@ contract Staking is StakingV2Storage, GraphUpgradeable, IStaking {
// Indexer or operator can close an allocation
// Delegators are also allowed but only after maxAllocationEpochs passed
bool isIndexer = _isAuth(alloc.indexer);
if (epochs > maxAllocationEpochs) {
require(isIndexer || isDelegator(alloc.indexer, msg.sender), "!auth-or-del");
} else {
if (epochs <= maxAllocationEpochs) {
require(isIndexer, "!auth");
}

Expand Down
6 changes: 6 additions & 0 deletions test/lib/testHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ export const advanceToNextEpoch = async (epochManager: EpochManager): Promise<vo
await advanceBlockTo(nextEpochBlock)
}

export const advanceEpochs = async (epochManager: EpochManager, n: number): Promise<void> => {
for (let i = 0; i < n + 1; i++) {
await advanceToNextEpoch(epochManager)
}
}

export const evmSnapshot = async (): Promise<number> => provider().send('evm_snapshot', [])
export const evmRevert = async (id: number): Promise<boolean> => provider().send('evm_revert', [id])

Expand Down
18 changes: 8 additions & 10 deletions test/staking/allocation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
toBN,
toGRT,
Account,
advanceEpochs,
} from '../lib/testHelpers'

const { AddressZero, HashZero } = constants
Expand Down Expand Up @@ -581,16 +582,14 @@ describe('Staking:Allocation', () => {
await staking.connect(me.signer).closeAllocation(allocationID, poi)
})

it('should close an allocation (by delegator)', async function () {
it('should close an allocation (by public)', async function () {
// Reject to close if public address and under max allocation epochs
const tx1 = staking.connect(me.signer).closeAllocation(allocationID, poi)
await expect(tx1).revertedWith('<epochs')

// Move max allocation epochs to close by delegator
const maxAllocationEpochs = await staking.maxAllocationEpochs()
for (let i = 0; i < maxAllocationEpochs + 1; i++) {
await advanceToNextEpoch(epochManager)
}

// Reject to close if the address is not delegator
const tx1 = staking.connect(me.signer).closeAllocation(allocationID, poi)
await expect(tx1).revertedWith('!auth')
await advanceEpochs(epochManager, maxAllocationEpochs)

// Calculations
const beforeAlloc = await staking.getAllocation(allocationID)
Expand All @@ -605,9 +604,8 @@ describe('Staking:Allocation', () => {
// Setup
await grt.connect(governor.signer).mint(me.address, toGRT('1'))
await grt.connect(me.signer).approve(staking.address, toGRT('1'))
await staking.connect(me.signer).delegate(indexer.address, toGRT('1'))

// Should close by delegator
// Should close by public
const tx = staking.connect(me.signer).closeAllocation(allocationID, poi)
await expect(tx)
.emit(staking, 'AllocationClosed')
Expand Down