Skip to content

Commit 1570a49

Browse files
authored
Merge pull request #766 from MercuricChloride/dev
feat: changed dispute manager to not delete bad actors disputes on re…
2 parents da62804 + a928e0b commit 1570a49

File tree

3 files changed

+71
-35
lines changed

3 files changed

+71
-35
lines changed

contracts/disputes/DisputeManager.sol

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
154154
_;
155155
}
156156

157+
modifier onlyPendingDispute(bytes32 _disputeID) {
158+
require(isDisputeCreated(_disputeID), "Dispute does not exist");
159+
require(
160+
disputes[_disputeID].status == IDisputeManager.DisputeStatus.Pending,
161+
"Dispute must be pending"
162+
);
163+
_;
164+
}
165+
157166
// -- Functions --
158167

159168
/**
@@ -290,7 +299,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
290299
* @param _disputeID True if dispute already exists
291300
*/
292301
function isDisputeCreated(bytes32 _disputeID) public view override returns (bool) {
293-
return disputes[_disputeID].fisherman != address(0);
302+
return disputes[_disputeID].status != DisputeStatus.Null;
294303
}
295304

296305
/**
@@ -479,7 +488,8 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
479488
_fisherman,
480489
_deposit,
481490
0, // no related dispute,
482-
DisputeType.QueryDispute
491+
DisputeType.QueryDispute,
492+
IDisputeManager.DisputeStatus.Pending
483493
);
484494

485495
emit QueryDisputeCreated(
@@ -546,7 +556,8 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
546556
_fisherman,
547557
_deposit,
548558
0,
549-
DisputeType.IndexingDispute
559+
DisputeType.IndexingDispute,
560+
IDisputeManager.DisputeStatus.Pending
550561
);
551562

552563
emit IndexingDisputeCreated(disputeID, alloc.indexer, _fisherman, _deposit, _allocationID);
@@ -562,8 +573,16 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
562573
* @notice Accept a dispute with ID `_disputeID`
563574
* @param _disputeID ID of the dispute to be accepted
564575
*/
565-
function acceptDispute(bytes32 _disputeID) external override onlyArbitrator {
566-
Dispute memory dispute = _resolveDispute(_disputeID);
576+
function acceptDispute(bytes32 _disputeID)
577+
external
578+
override
579+
onlyArbitrator
580+
onlyPendingDispute(_disputeID)
581+
{
582+
Dispute storage dispute = disputes[_disputeID];
583+
584+
// store the dispute status
585+
dispute.status = IDisputeManager.DisputeStatus.Accepted;
567586

568587
// Slash
569588
(, uint256 tokensToReward) = _slashIndexer(
@@ -575,8 +594,9 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
575594
// Give the fisherman their deposit back
576595
TokenUtils.pushTokens(graphToken(), dispute.fisherman, dispute.deposit);
577596

578-
// Resolve the conflicting dispute if any
579-
_resolveDisputeInConflict(dispute);
597+
if (_isDisputeInConflict(dispute)) {
598+
rejectDispute(dispute.relatedDisputeID);
599+
}
580600

581601
emit DisputeAccepted(
582602
_disputeID,
@@ -591,8 +611,16 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
591611
* @notice Reject a dispute with ID `_disputeID`
592612
* @param _disputeID ID of the dispute to be rejected
593613
*/
594-
function rejectDispute(bytes32 _disputeID) external override onlyArbitrator {
595-
Dispute memory dispute = _resolveDispute(_disputeID);
614+
function rejectDispute(bytes32 _disputeID)
615+
public
616+
override
617+
onlyArbitrator
618+
onlyPendingDispute(_disputeID)
619+
{
620+
Dispute storage dispute = disputes[_disputeID];
621+
622+
// store dispute status
623+
dispute.status = IDisputeManager.DisputeStatus.Rejected;
596624

597625
// Handle conflicting dispute if any
598626
require(
@@ -611,52 +639,48 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa
611639
* @notice Ignore a dispute with ID `_disputeID`
612640
* @param _disputeID ID of the dispute to be disregarded
613641
*/
614-
function drawDispute(bytes32 _disputeID) external override onlyArbitrator {
615-
Dispute memory dispute = _resolveDispute(_disputeID);
642+
function drawDispute(bytes32 _disputeID)
643+
public
644+
override
645+
onlyArbitrator
646+
onlyPendingDispute(_disputeID)
647+
{
648+
Dispute storage dispute = disputes[_disputeID];
616649

617650
// Return deposit to the fisherman
618651
TokenUtils.pushTokens(graphToken(), dispute.fisherman, dispute.deposit);
619652

620-
// Resolve the conflicting dispute if any
621-
_resolveDisputeInConflict(dispute);
622-
623-
emit DisputeDrawn(_disputeID, dispute.indexer, dispute.fisherman, dispute.deposit);
624-
}
625-
626-
/**
627-
* @dev Resolve a dispute by removing it from storage and returning a memory copy.
628-
* @param _disputeID ID of the dispute to resolve
629-
* @return Dispute
630-
*/
631-
function _resolveDispute(bytes32 _disputeID) private returns (Dispute memory) {
632-
require(isDisputeCreated(_disputeID), "Dispute does not exist");
653+
// resolve related dispute if any
654+
_drawDisputeInConflict(dispute);
633655

634-
Dispute memory dispute = disputes[_disputeID];
656+
// store dispute status
657+
dispute.status = IDisputeManager.DisputeStatus.Drawn;
635658

636-
// Resolve dispute
637-
delete disputes[_disputeID]; // Re-entrancy
638-
639-
return dispute;
659+
emit DisputeDrawn(_disputeID, dispute.indexer, dispute.fisherman, dispute.deposit);
640660
}
641661

642662
/**
643663
* @dev Returns whether the dispute is for a conflicting attestation or not.
644664
* @param _dispute Dispute
645665
* @return True conflicting attestation dispute
646666
*/
647-
function _isDisputeInConflict(Dispute memory _dispute) private pure returns (bool) {
648-
return _dispute.relatedDisputeID != 0;
667+
function _isDisputeInConflict(Dispute memory _dispute) private view returns (bool) {
668+
bytes32 relatedID = _dispute.relatedDisputeID;
669+
// this is so the check returns false when rejecting the related dispute.
670+
return
671+
relatedID != 0 && disputes[relatedID].status == IDisputeManager.DisputeStatus.Pending;
649672
}
650673

651674
/**
652675
* @dev Resolve the conflicting dispute if there is any for the one passed to this function.
653676
* @param _dispute Dispute
654677
* @return True if resolved
655678
*/
656-
function _resolveDisputeInConflict(Dispute memory _dispute) private returns (bool) {
679+
function _drawDisputeInConflict(Dispute memory _dispute) private returns (bool) {
657680
if (_isDisputeInConflict(_dispute)) {
658681
bytes32 relatedDisputeID = _dispute.relatedDisputeID;
659-
delete disputes[relatedDisputeID];
682+
Dispute storage relatedDispute = disputes[relatedDisputeID];
683+
relatedDispute.status = IDisputeManager.DisputeStatus.Drawn;
660684
return true;
661685
}
662686
return false;

contracts/disputes/IDisputeManager.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,22 @@ interface IDisputeManager {
1212
QueryDispute
1313
}
1414

15+
enum DisputeStatus {
16+
Null,
17+
Accepted,
18+
Rejected,
19+
Drawn,
20+
Pending
21+
}
22+
1523
// Disputes contain info necessary for the Arbitrator to verify and resolve
1624
struct Dispute {
1725
address indexer;
1826
address fisherman;
1927
uint256 deposit;
2028
bytes32 relatedDisputeID;
2129
DisputeType disputeType;
30+
DisputeStatus status;
2231
}
2332

2433
// -- Attestation --

test/disputes/query.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
} from '../lib/testHelpers'
2222

2323
import { Dispute, createQueryDisputeID, encodeAttestation, MAX_PPM } from './common'
24+
import { isExportDeclaration } from 'typescript'
2425

2526
const { AddressZero, HashZero } = constants
2627

@@ -528,8 +529,10 @@ describe('DisputeManager:Query', async () => {
528529
// Do
529530
await disputeManager.connect(arbitrator.signer).acceptDispute(dID1)
530531
// Check
532+
const mainDispute = await disputeManager.disputes(dID1)
533+
expect(mainDispute.status).to.eq(1) // 1 = DisputeStatus.Accepted
531534
const relatedDispute = await disputeManager.disputes(dID2)
532-
expect(relatedDispute.indexer).eq(AddressZero)
535+
expect(relatedDispute.status).to.eq(2) // 2 = DisputeStatus.Rejected
533536
})
534537

535538
it('should not allow to reject, user need to accept the related dispute ID to reject it', async function () {
@@ -549,7 +552,7 @@ describe('DisputeManager:Query', async () => {
549552
await disputeManager.connect(arbitrator.signer).drawDispute(dID1)
550553
// Check
551554
const relatedDispute = await disputeManager.disputes(dID2)
552-
expect(relatedDispute.indexer).eq(AddressZero)
555+
expect(relatedDispute.status).not.eq(4) // 4 = DisputeStatus.Pending
553556
})
554557
})
555558
})

0 commit comments

Comments
 (0)