Skip to content

Commit 9e815dc

Browse files
committed
disputes: fix and improve tests
1 parent cd2a657 commit 9e815dc

File tree

3 files changed

+119
-46
lines changed

3 files changed

+119
-46
lines changed

contracts/DisputeManager.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ contract DisputeManager is Governed {
408408

409409
// Get the indexer that created the channel and signed the attestation
410410
(address indexer, bytes32 subgraphID) = staking.channels(channelID);
411-
require(indexer != address(0), "Indexer cannot be found with the attestation");
411+
require(indexer != address(0), "Indexer cannot be found for the attestation");
412412
require(subgraphID == attestation.subgraphID, "Channel and attestation subgraph must match");
413413

414414
// Create a disputeID

test/disputes.test.js

Lines changed: 108 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const BN = web3.utils.BN
22
const { expect } = require('chai')
3-
const { constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers')
3+
const { constants, expectEvent, expectRevert, time } = require('@openzeppelin/test-helpers')
44
const { ZERO_ADDRESS } = constants
55

66
// helpers
@@ -12,9 +12,23 @@ const { defaults } = require('./lib/testHelpers')
1212
const MAX_PPM = 1000000
1313
const NON_EXISTING_DISPUTE_ID = '0x0'
1414

15+
function toGRT(value) {
16+
return new BN(web3.utils.toWei(value))
17+
}
18+
1519
contract(
1620
'Disputes',
1721
([me, other, governor, arbitrator, indexer, fisherman, otherIndexer, channelProxy]) => {
22+
before(async function() {
23+
// Helpers
24+
this.advanceToNextEpoch = async () => {
25+
const currentBlock = await time.latestBlock()
26+
const epochLength = await this.epochManager.epochLength()
27+
const nextEpochBlock = currentBlock.add(epochLength)
28+
await time.advanceBlockTo(nextEpochBlock)
29+
}
30+
})
31+
1832
beforeEach(async function() {
1933
// Channel keys for account #4
2034
this.indexerChannelPrivKey =
@@ -200,8 +214,8 @@ contract(
200214
describe('dispute lifecycle', function() {
201215
beforeEach(async function() {
202216
// Give some funds to the fisherman
203-
this.fishermanTokens = web3.utils.toWei(new BN('100000'))
204-
this.fishermanDeposit = web3.utils.toWei(new BN('1000'))
217+
this.fishermanTokens = toGRT('100000')
218+
this.fishermanDeposit = toGRT('1000')
205219
await this.grt.mint(fisherman, this.fishermanTokens, {
206220
from: governor,
207221
})
@@ -223,26 +237,77 @@ contract(
223237
)
224238
})
225239

226-
it('reject create a dispute', async function() {
240+
it('reject create a dispute if attestation does not refer to valid indexer', async function() {
227241
// Create dispute
228242
await expectRevert(
229243
this.disputeManager.createDispute(this.dispute.attestation, this.fishermanDeposit, {
230244
from: fisherman,
231245
}),
232-
'Indexer cannot be found with the attestation',
246+
'Indexer cannot be found for the attestation',
233247
)
234248
})
235249

236-
context('> when stake does exist', function() {
250+
it('reject create a dispute if indexer has no stake', async function() {
251+
// This tests reproduce the case when someones present a dispute after
252+
// an indexer removed his stake completely and find nothing to slash
253+
254+
const indexerTokens = toGRT('100000')
255+
const indexerAllocatedTokens = toGRT('10000')
256+
const indexerSettledTokens = toGRT('10')
257+
258+
// Give some funds to the indexer
259+
await this.grt.mint(indexer, indexerTokens, {
260+
from: governor,
261+
})
262+
await this.grt.approve(this.staking.address, indexerTokens, {
263+
from: indexer,
264+
})
265+
266+
// Give some funds to the channel
267+
await this.grt.mint(channelProxy, indexerSettledTokens, {
268+
from: governor,
269+
})
270+
await this.grt.approve(this.staking.address, indexerSettledTokens, {
271+
from: channelProxy,
272+
})
273+
274+
// Set the thawing period to zero to make the test easier
275+
await this.staking.setThawingPeriod(new BN('0'), { from: governor })
276+
277+
// Indexer stake funds, allocate, settle, unstake and withdraw the stake fully
278+
await this.staking.stake(indexerTokens, { from: indexer })
279+
await this.staking.allocate(
280+
this.dispute.receipt.subgraphID,
281+
indexerAllocatedTokens,
282+
this.indexerChannelPubKey,
283+
channelProxy,
284+
new BN('0'),
285+
{ from: indexer },
286+
)
287+
await this.advanceToNextEpoch() // wait the required one epoch to settle
288+
await this.staking.settle(indexerSettledTokens, { from: channelProxy })
289+
await this.staking.unstake(indexerTokens, { from: indexer })
290+
await this.staking.withdraw({ from: indexer }) // no thawing period so we are good
291+
292+
// Create dispute
293+
await expectRevert(
294+
this.disputeManager.createDispute(this.dispute.attestation, this.fishermanDeposit, {
295+
from: fisherman,
296+
}),
297+
'Dispute has no stake by the indexer',
298+
)
299+
})
300+
301+
context('> when indexer has staked', function() {
237302
beforeEach(async function() {
238303
// Dispute manager is allowed to slash
239304
await this.staking.setSlasher(this.disputeManager.address, true, {
240305
from: governor,
241306
})
242307

243308
// Stake
244-
this.indexerTokens = web3.utils.toWei(new BN('100000'))
245-
this.indexerAllocatedTokens = web3.utils.toWei(new BN('10000'))
309+
this.indexerTokens = toGRT('100000')
310+
this.indexerAllocatedTokens = toGRT('10000')
246311
const indexerList = [
247312
[indexer, this.indexerChannelPubKey],
248313
[otherIndexer, this.otherIndexerChannelPubKey],
@@ -319,6 +384,39 @@ contract(
319384
})
320385
})
321386

387+
describe('accept a dispute', function() {
388+
it('reject to accept a non-existing dispute', async function() {
389+
await expectRevert(
390+
this.disputeManager.acceptDispute(NON_EXISTING_DISPUTE_ID, {
391+
from: arbitrator,
392+
}),
393+
'Dispute does not exist',
394+
)
395+
})
396+
})
397+
398+
describe('reject a dispute', function() {
399+
it('reject to reject a non-existing dispute', async function() {
400+
await expectRevert(
401+
this.disputeManager.rejectDispute(NON_EXISTING_DISPUTE_ID, {
402+
from: arbitrator,
403+
}),
404+
'Dispute does not exist',
405+
)
406+
})
407+
})
408+
409+
describe('draw a dispute', function() {
410+
it('reject to draw a non-existing dispute', async function() {
411+
await expectRevert(
412+
this.disputeManager.drawDispute(NON_EXISTING_DISPUTE_ID, {
413+
from: arbitrator,
414+
}),
415+
'Dispute does not exist',
416+
)
417+
})
418+
})
419+
322420
context('> when dispute is created', function() {
323421
beforeEach(async function() {
324422
// Create dispute
@@ -330,7 +428,7 @@ contract(
330428
})
331429

332430
describe('create a dispute', function() {
333-
it('should create dispute if receipt is equal but for different indexer', async function() {
431+
it('should create dispute if receipt is equal but for other indexer', async function() {
334432
// Create dispute (same receipt but different indexer)
335433
const newDispute = await attestation.createDispute(
336434
this.dispute.receipt,
@@ -366,15 +464,6 @@ contract(
366464
})
367465

368466
describe('accept a dispute', function() {
369-
it('reject to accept a non-existing dispute', async function() {
370-
await expectRevert(
371-
this.disputeManager.acceptDispute(NON_EXISTING_DISPUTE_ID, {
372-
from: arbitrator,
373-
}),
374-
'Dispute does not exist',
375-
)
376-
})
377-
378467
it('reject to accept a dispute if not the arbitrator', async function() {
379468
await expectRevert(
380469
this.disputeManager.acceptDispute(this.dispute.id, {
@@ -448,15 +537,6 @@ contract(
448537
})
449538

450539
describe('reject a dispute', async function() {
451-
it('reject to reject a non-existing dispute', async function() {
452-
await expectRevert(
453-
this.disputeManager.rejectDispute(NON_EXISTING_DISPUTE_ID, {
454-
from: arbitrator,
455-
}),
456-
'Dispute does not exist',
457-
)
458-
})
459-
460540
it('reject to reject a dispute if not the arbitrator', async function() {
461541
await expectRevert(
462542
this.disputeManager.rejectDispute(this.dispute.id, {
@@ -481,7 +561,7 @@ contract(
481561

482562
// Burn fisherman deposit
483563
const totalSupplyAfter = await this.grt.totalSupply()
484-
const burnedTokens = web3.utils.toBN(this.fishermanDeposit)
564+
const burnedTokens = new BN(this.fishermanDeposit)
485565
expect(totalSupplyAfter).to.be.bignumber.eq(totalSupplyBefore.sub(burnedTokens))
486566

487567
// Event emitted
@@ -496,15 +576,6 @@ contract(
496576
})
497577

498578
describe('draw a dispute', async function() {
499-
it('reject to draw a non-existing dispute', async function() {
500-
await expectRevert(
501-
this.disputeManager.drawDispute(NON_EXISTING_DISPUTE_ID, {
502-
from: arbitrator,
503-
}),
504-
'Dispute does not exist',
505-
)
506-
})
507-
508579
it('reject to draw a dispute if not the arbitrator', async function() {
509580
await expectRevert(
510581
this.disputeManager.drawDispute(this.dispute.id, {

test/staking/general.test.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ function toGRT(value) {
2121
}
2222

2323
contract('Staking', ([me, other, governor, indexer, slasher, fisherman, channelProxy]) => {
24+
before(async function() {
25+
// Helpers
26+
this.advanceToNextEpoch = async () => {
27+
const currentBlock = await time.latestBlock()
28+
const epochLength = await this.epochManager.epochLength()
29+
const nextEpochBlock = currentBlock.add(epochLength)
30+
await time.advanceBlockTo(nextEpochBlock)
31+
}
32+
})
33+
2434
beforeEach(async function() {
2535
// Deploy epoch contract
2636
this.epochManager = await deployment.deployEpochManagerContract(governor, { from: me })
@@ -49,14 +59,6 @@ contract('Staking', ([me, other, governor, indexer, slasher, fisherman, channelP
4959

5060
// Set staking as distributor of funds to curation
5161
await this.curation.setStaking(this.staking.address, { from: governor })
52-
53-
// Helpers
54-
this.advanceToNextEpoch = async () => {
55-
const currentBlock = await time.latestBlock()
56-
const epochLength = await this.epochManager.epochLength()
57-
const nextEpochBlock = currentBlock.add(epochLength)
58-
await time.advanceBlockTo(nextEpochBlock)
59-
}
6062
})
6163

6264
describe('configuration', function() {

0 commit comments

Comments
 (0)