Skip to content

Commit bac9bdc

Browse files
committed
feat(subgraph): dispute-archive-mapping
1 parent 46b212b commit bac9bdc

11 files changed

Lines changed: 260 additions & 24 deletions

File tree

bots/dispute-archival-bot/abi/DisputeArchive.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ export const disputeArchiveAbi = [
3333
name: "id",
3434
type: "uint256",
3535
},
36+
{
37+
indexed: false,
38+
internalType: "uint96",
39+
name: "courtId",
40+
type: "uint96",
41+
},
3642
{
3743
indexed: false,
3844
internalType: "string",
@@ -130,6 +136,11 @@ export const disputeArchiveAbi = [
130136
name: "id",
131137
type: "uint256",
132138
},
139+
{
140+
internalType: "uint96",
141+
name: "courtId",
142+
type: "uint96",
143+
},
133144
{
134145
internalType: "string",
135146
name: "cid",

bots/dispute-archival-bot/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ async function main() {
2626

2727
const cid = await uploadToIpfs(id, snapshot);
2828

29-
const hash = await registerCid(id, cid);
29+
const courtID = snapshot.dispute.court.id;
30+
31+
const hash = await registerCid(id, courtID, cid);
3032

3133
console.log(`Dispute ${id} archived with cid: ${cid}. Transaction hash: ${hash}`);
3234
}

bots/dispute-archival-bot/utils/contract.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const getClients = () => {
2727
};
2828
};
2929

30-
export async function registerCid(disputeId: string, cid: string) {
30+
export async function registerCid(disputeId: string, courtId: string, cid: string) {
3131
const { publicClient, walletClient, account } = getClients();
3232
const config = getEnvConfig();
3333

@@ -36,7 +36,7 @@ export async function registerCid(disputeId: string, cid: string) {
3636
address: config.disputeArchiveAddress as Address,
3737
abi: disputeArchiveAbi,
3838
functionName: "register",
39-
args: [BigInt(disputeId), cid],
39+
args: [BigInt(disputeId), BigInt(courtId), cid],
4040
});
4141

4242
const hash = await walletClient.writeContract(request);

contracts/deployments/arbitrumSepoliaDevnet/DisputeArchive.json

Lines changed: 31 additions & 18 deletions
Large diffs are not rendered by default.

contracts/src/archive/DisputeArchive.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ contract DisputeArchive {
1010

1111
/**
1212
* @param id Id of the archived dispute
13+
* @param courtId Id of the court in which the dispute initiated
1314
* @param cid Ipfs cid containing the populated dispute + dispute evidences + kleros core subgraph data
1415
*/
15-
event ArchivedDispute(uint256 indexed id, string cid);
16+
event ArchivedDispute(uint256 indexed id, uint96 courtId, string cid);
1617

1718
/**
1819
* @param id Id of the amended archived dispute
@@ -61,13 +62,14 @@ contract DisputeArchive {
6162

6263
/// @notice Stores archived dispute's ipfs cid.
6364
/// @param id ID of dispute to be archived.
65+
/// @param courtId Id of the court in which the dispute initiated
6466
/// @param cid Archived dispute data's ipfs cid.
65-
function register(uint256 id, string calldata cid) external onlyOwner {
67+
function register(uint256 id, uint96 courtId, string calldata cid) external onlyOwner {
6668
require(bytes(archivedDisputeToCid[id]).length == 0, DisputeAlreadyArchived());
6769
require(bytes(cid).length > 0, CIDCannotBeEmpty());
6870

6971
archivedDisputeToCid[id] = cid;
70-
emit ArchivedDispute(id, cid);
72+
emit ArchivedDispute(id, courtId, cid);
7173
}
7274

7375
/// @notice Amends archived dispute's ipfs cid.

subgraph/core/schema.graphql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ type Dispute @entity(immutable: false) {
185185
# required to keep evidence unique
186186
evidenceCount: BigInt!
187187
evidences: [ClassicEvidence!]! @derivedFrom(field: "dispute")
188+
isArchived: Boolean!
189+
archiveCid: String
188190
}
189191

190192
type PeriodIndexCounter @entity(immutable: false) {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { BigInt, Bytes, log } from "@graphprotocol/graph-ts";
2+
import { ArchivedDispute, ArchivedDisputeAmended } from "../generated/DisputeArchive/DisputeArchive";
3+
import { Dispute } from "../generated/schema";
4+
import { createArchiveOnlyDispute } from "./archive/disputeArchiveStubs";
5+
import { ONE } from "./utils";
6+
7+
function createArchiveDispute(
8+
disputeId: BigInt,
9+
courtId: BigInt,
10+
cid: string,
11+
reason: string | null,
12+
timestamp: BigInt,
13+
blockNumber: BigInt,
14+
transactionHash: Bytes
15+
): void {
16+
const dispute = Dispute.load(disputeId.toString());
17+
18+
// if dispute is present, then it is an amend event
19+
if (dispute) {
20+
dispute.isArchived = true;
21+
dispute.archiveCid = cid;
22+
dispute.save();
23+
return;
24+
}
25+
26+
createArchiveOnlyDispute(disputeId, courtId, cid, reason, timestamp, blockNumber, transactionHash);
27+
}
28+
29+
export function handleDisputeArchived(event: ArchivedDispute): void {
30+
createArchiveDispute(
31+
event.params.id,
32+
event.params.courtId,
33+
event.params.cid,
34+
null,
35+
event.block.timestamp,
36+
event.block.number,
37+
event.transaction.hash
38+
);
39+
}
40+
41+
export function handleDisputeAmended(event: ArchivedDisputeAmended): void {
42+
createArchiveDispute(
43+
event.params.id,
44+
ONE, // this is placeholder, will not be used
45+
event.params.cid,
46+
event.params.reason,
47+
event.block.timestamp,
48+
event.block.number,
49+
event.transaction.hash
50+
);
51+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { BigInt, Bytes } from "@graphprotocol/graph-ts";
2+
import { Arbitrable, Court, Dispute, DisputeKit, Round } from "../../generated/schema";
3+
import { ONE, ZERO } from "../utils";
4+
import { updateCases, updateCasesRuled, updateCourtCumulativeMetric } from "../datapoint";
5+
6+
const ARCHIVE_STUB_DISPUTE_KIT_ID = "archive-stub-dispute-kit";
7+
const ARCHIVE_STUB_ARBITRABLE_ID = "0x0000000000000000000000000000000000000000";
8+
9+
function ensureArchiveStubDisputeKit(): void {
10+
if (DisputeKit.load(ARCHIVE_STUB_DISPUTE_KIT_ID) != null) {
11+
return;
12+
}
13+
const disputeKit = new DisputeKit(ARCHIVE_STUB_DISPUTE_KIT_ID);
14+
disputeKit.address = null;
15+
disputeKit.needsFreezing = false;
16+
disputeKit.save();
17+
}
18+
19+
function ensureArchiveStubArbitrable(): void {
20+
if (Arbitrable.load(ARCHIVE_STUB_ARBITRABLE_ID) != null) {
21+
return;
22+
}
23+
const arbitrable = new Arbitrable(ARCHIVE_STUB_ARBITRABLE_ID);
24+
arbitrable.totalDisputes = ZERO;
25+
arbitrable.save();
26+
}
27+
28+
// creates placeholder entities
29+
export function ensureArchiveStubEntities(): void {
30+
ensureArchiveStubDisputeKit();
31+
ensureArchiveStubArbitrable();
32+
}
33+
34+
export function createArchiveOnlyDispute(
35+
disputeId: BigInt,
36+
courtId: BigInt,
37+
cid: string,
38+
reason: string | null,
39+
blockTimestamp: BigInt,
40+
blockNumber: BigInt,
41+
transactionHash: Bytes
42+
): void {
43+
ensureArchiveStubEntities();
44+
updateCases(ONE, blockTimestamp);
45+
updateCasesRuled(ONE, blockTimestamp);
46+
47+
// placeholder for currentRound, actual data is fetched from ipfs
48+
const currentRoundId = disputeId.toString() + "-0";
49+
const currentRound = Round.load(currentRoundId);
50+
51+
if (!currentRound) {
52+
const round = new Round(currentRoundId);
53+
round.dispute = disputeId.toString();
54+
round.court = courtId.toString();
55+
round.disputeKit = ARCHIVE_STUB_DISPUTE_KIT_ID;
56+
round.tokensAtStakePerJuror = ZERO;
57+
round.totalFeesForJurors = ZERO;
58+
round.nbVotes = ZERO;
59+
round.isCurrentRound = true;
60+
round.repartitions = ZERO;
61+
round.penalties = ZERO;
62+
round.timeline = [ZERO, ZERO, ZERO, ZERO];
63+
round.jurorsDrawn = false;
64+
round.jurorRewardsDispersed = false;
65+
round.timesPerPeriod = [ZERO, ZERO, ZERO, ZERO];
66+
round.hiddenVotes = false;
67+
round.jurorsForCourtJump = ZERO;
68+
round.feeToken = null;
69+
round.save();
70+
}
71+
72+
const dispute = new Dispute(disputeId.toString());
73+
dispute.disputeID = disputeId;
74+
dispute.court = courtId.toString();
75+
dispute.createdAt = blockTimestamp;
76+
dispute.transactionHash = transactionHash.toHexString();
77+
dispute.arbitrated = ARCHIVE_STUB_ARBITRABLE_ID;
78+
dispute.period = "execution";
79+
dispute.ruled = true;
80+
dispute.executed = true;
81+
dispute.currentRuling = ZERO;
82+
dispute.tied = false;
83+
dispute.overridden = false;
84+
dispute.periodDeadline = blockTimestamp;
85+
dispute.periodNotificationIndex = ZERO;
86+
dispute.lastPeriodChange = blockTimestamp;
87+
dispute.lastPeriodChangeBlockNumber = blockNumber;
88+
dispute.currentRound = currentRoundId;
89+
dispute.currentRoundIndex = ZERO;
90+
dispute.evidenceCount = ZERO;
91+
dispute.isArchived = true;
92+
dispute.archiveCid = cid;
93+
dispute.save();
94+
95+
const court = Court.load(courtId.toString());
96+
if (!court) return;
97+
court.numberDisputes = court.numberDisputes.plus(ONE);
98+
// archived dispute is closed already
99+
court.numberClosedDisputes = court.numberClosedDisputes.plus(ONE);
100+
updateCourtCumulativeMetric(courtId.toString(), ONE, blockTimestamp, "numberDisputes");
101+
}

subgraph/core/src/entities/Dispute.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export function createDisputeFromEvent(event: DisputeCreation): void {
2424
dispute.periodNotificationIndex = getAndIncrementPeriodCounter(dispute.period);
2525
dispute.transactionHash = event.transaction.hash.toHexString();
2626
dispute.evidenceCount = ZERO;
27+
dispute.isArchived = false;
28+
dispute.archiveCid = null;
2729
const court = Court.load(courtID);
2830
if (!court) return;
2931
// Note: It's okay to use `timesPerPeriod` from court here since, at this point, both are the same.

subgraph/core/subgraph.template.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,29 @@ dataSources:
390390
- event: NewCurrencyRate(indexed address,uint64,uint8)
391391
handler: handleNewCurrencyRate
392392
file: ./src/RatesConverter.ts
393+
- kind: ethereum
394+
name: DisputeArchive
395+
network: _PLACEHOLDER_
396+
source:
397+
address: "_PLACEHOLDER_"
398+
abi: DisputeArchive
399+
startBlock: _PLACEHOLDER_
400+
mapping:
401+
kind: ethereum/events
402+
apiVersion: 0.0.7
403+
language: wasm/assemblyscript
404+
entities:
405+
- Arbitrable
406+
- Court
407+
- DisputeKit
408+
- Dispute
409+
- Round
410+
abis:
411+
- name: DisputeArchive
412+
file: ../../contracts/deployments/_PLACEHOLDER_/DisputeArchive.json
413+
eventHandlers:
414+
- event: ArchivedDispute(indexed uint256,uint96,string)
415+
handler: handleDisputeArchived
416+
- event: ArchivedDisputeAmended(indexed uint256,string,string)
417+
handler: handleDisputeAmended
418+
file: ./src/DisputeArchive.ts

0 commit comments

Comments
 (0)