Skip to content

Commit 07137fd

Browse files
Merge branch 'dev' into fix/separate-batchers
2 parents 9616df8 + 4954a10 commit 07137fd

File tree

75 files changed

+948
-413
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+948
-413
lines changed

kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,19 @@ export enum QuestionType {
3333
export const QuestionTypeSchema = z.nativeEnum(QuestionType);
3434

3535
export const AnswerSchema = z.object({
36-
id: z
37-
.string()
38-
.regex(/^0x[0-9a-fA-F]+$/)
39-
.optional(),
36+
id: z.string().regex(/^0x[0-9a-fA-F]+$/),
4037
title: z.string(),
4138
description: z.string(),
4239
reserved: z.boolean().optional(),
4340
});
4441

42+
export const RefuseToArbitrateAnswer = {
43+
id: "0x0",
44+
title: "Refuse to Arbitrate / Invalid",
45+
description: "Refuse to Arbitrate / Invalid",
46+
reserved: true,
47+
};
48+
4549
export const AttachmentSchema = z.object({
4650
label: z.string(),
4751
uri: z.string(),

kleros-sdk/src/dataMappings/utils/populateTemplate.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import mustache from "mustache";
22
import { DisputeDetails } from "./disputeDetailsTypes";
3-
import DisputeDetailsSchema from "./disputeDetailsSchema";
3+
import DisputeDetailsSchema, { RefuseToArbitrateAnswer } from "./disputeDetailsSchema";
44

55
export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDetails => {
66
const render = mustache.render(mustacheTemplate, data);
@@ -11,5 +11,11 @@ export const populateTemplate = (mustacheTemplate: string, data: any): DisputeDe
1111
throw validation.error;
1212
}
1313

14+
// Filter out any existing answer with id 0 and add our standard Refuse to Arbitrate option
15+
(dispute as DisputeDetails).answers = [
16+
RefuseToArbitrateAnswer,
17+
...((dispute as DisputeDetails).answers.filter((answer) => answer.id && BigInt(answer.id) !== BigInt(0)) || []),
18+
];
19+
1420
return dispute;
1521
};

kleros-sdk/src/utils/getDispute.ts

-11
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,5 @@ export const getDispute = async (disputeParameters: GetDisputeParameters): Promi
5656

5757
const populatedTemplate = populateTemplate(templateData, data);
5858

59-
// Filter out any existing answer with id 0 and add our standard Refuse to Arbitrate option
60-
populatedTemplate.answers = [
61-
{
62-
id: "0x0",
63-
title: "Refuse to Arbitrate / Invalid",
64-
description: "Refuse to Arbitrate / Invalid",
65-
reserved: true,
66-
},
67-
...(populatedTemplate.answers?.filter((answer) => answer.id && Number(answer.id) !== 0) || []),
68-
];
69-
7059
return populatedTemplate;
7160
};

subgraph/core/schema.graphql

+13-2
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,14 @@ interface Evidence {
6363
fileTypeExtension: String
6464
}
6565

66+
6667
############
6768
# Entities #
6869
############
6970

7071
type User @entity {
7172
id: ID! # address
73+
userAddress: String!
7274
tokens: [JurorTokensPerCourt!]! @derivedFrom(field: "juror")
7375
totalStake: BigInt!
7476
totalDelayed: BigInt!
@@ -237,6 +239,7 @@ type Counter @entity {
237239
casesVoting: BigInt!
238240
casesRuled: BigInt!
239241
casesAppealing: BigInt!
242+
totalLeaderboardJurors: BigInt!
240243
}
241244

242245
type FeeToken @entity {
@@ -265,17 +268,25 @@ type ClassicDispute implements DisputeKitDispute @entity {
265268
extraData: Bytes!
266269
}
267270

271+
type Answer @entity {
272+
id: ID! # classicRound.id-answerId
273+
answerId: BigInt!
274+
count: BigInt!
275+
paidFee: BigInt!
276+
funded: Boolean!
277+
localRound: ClassicRound!
278+
}
279+
268280
type ClassicRound implements DisputeKitRound @entity {
269281
id: ID! # disputeKit.id-coreDispute-dispute.rounds.length
270282
localDispute: DisputeKitDispute!
271283
votes: [Vote!]! @derivedFrom(field: "localRound")
284+
answers: [Answer!]! @derivedFrom(field: "localRound")
272285

273286
winningChoice: BigInt!
274-
counts: [BigInt!]!
275287
tied: Boolean!
276288
totalVoted: BigInt!
277289
totalCommited: BigInt!
278-
paidFees: [BigInt!]!
279290
contributions: [ClassicContribution!]! @derivedFrom(field: "localRound")
280291
feeRewards: BigInt!
281292
totalFeeDispersed: BigInt!

subgraph/core/src/DisputeKitClassic.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ensureClassicContributionFromEvent } from "./entities/ClassicContributi
1414
import { createClassicDisputeFromEvent } from "./entities/ClassicDispute";
1515
import {
1616
createClassicRound,
17+
ensureAnswer,
1718
updateChoiceFundingFromContributionEvent,
1819
updateCountsAndGetCurrentRuling,
1920
} from "./entities/ClassicRound";
@@ -101,11 +102,16 @@ export function handleChoiceFunded(event: ChoiceFunded): void {
101102
const localRound = ClassicRound.load(roundID);
102103
if (!localRound) return;
103104

105+
const answer = ensureAnswer(roundID, choice);
106+
104107
const currentFeeRewards = localRound.feeRewards;
105-
const deltaFeeRewards = localRound.paidFees[choice.toI32()];
108+
const deltaFeeRewards = answer.paidFee;
106109
localRound.feeRewards = currentFeeRewards.plus(deltaFeeRewards);
107110
localRound.fundedChoices = localRound.fundedChoices.concat([choice]);
108111

112+
answer.funded = true;
113+
answer.save();
114+
109115
if (localRound.fundedChoices.length > 1) {
110116
const disputeKitClassic = DisputeKitClassic.bind(event.address);
111117
const klerosCore = KlerosCore.bind(disputeKitClassic.core());

subgraph/core/src/KlerosCore.ts

+22-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ import { createCourtFromEvent } from "./entities/Court";
1818
import { createDisputeKitFromEvent, filterSupportedDisputeKits } from "./entities/DisputeKit";
1919
import { createDisputeFromEvent } from "./entities/Dispute";
2020
import { createRoundFromRoundInfo, updateRoundTimeline } from "./entities/Round";
21-
import { updateCases, updateCasesAppealing, updateCasesRuled, updateCasesVoting } from "./datapoint";
21+
import {
22+
updateCases,
23+
updateCasesAppealing,
24+
updateCasesRuled,
25+
updateCasesVoting,
26+
updateTotalLeaderboardJurors,
27+
} from "./datapoint";
2228
import { addUserActiveDispute, computeCoherenceScore, ensureUser } from "./entities/User";
2329
import { updateJurorStake } from "./entities/JurorTokensPerCourt";
2430
import { createDrawFromEvent } from "./entities/Draw";
@@ -139,13 +145,23 @@ export function handleNewPeriod(event: NewPeriod): void {
139145
const draw = Draw.load(draws[j].id);
140146
if (!draw) continue;
141147

148+
const juror = ensureUser(draw.juror);
149+
juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);
150+
151+
// Increment totalLeaderboardJurors in the Counter entity if this is the first resolved vote for the juror
152+
if (juror.totalResolvedVotes.equals(ONE)) {
153+
updateTotalLeaderboardJurors(ONE, event.block.timestamp);
154+
}
155+
142156
// Since this is a ClassicVote entity, this will only work for the Classic DisputeKit (which has ID "1").
143157
const vote = ClassicVote.load(`${round.disputeKit}-${draw.id}`);
144158

145-
if (!vote) continue;
146-
147-
const juror = ensureUser(draw.juror);
148-
juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);
159+
if (!vote) {
160+
// Recalculate coherenceScore
161+
juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
162+
juror.save();
163+
continue;
164+
}
149165

150166
if (vote.choice === null) continue;
151167

@@ -155,9 +171,7 @@ export function handleNewPeriod(event: NewPeriod): void {
155171
}
156172

157173
// Recalculate coherenceScore
158-
if (juror.totalResolvedVotes.gt(ZERO)) {
159-
juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
160-
}
174+
juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
161175

162176
juror.save();
163177
}

subgraph/core/src/datapoint.ts

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const VARIABLES = [
1515
"casesVoting",
1616
"casesRuled",
1717
"casesAppealing",
18+
"totalLeaderboardJurors",
1819
];
1920

2021
function updateDataPoint(delta: BigInt, timestamp: BigInt, variable: string): void {
@@ -43,6 +44,7 @@ function checkFirstDayActivity(): void {
4344
counter.casesVoting = ZERO;
4445
counter.casesRuled = ZERO;
4546
counter.casesAppealing = ZERO;
47+
counter.totalLeaderboardJurors = ZERO;
4648
counter.save();
4749
}
4850
}
@@ -86,3 +88,7 @@ export function updateCasesRuled(delta: BigInt, timestamp: BigInt): void {
8688
export function updateCasesAppealing(delta: BigInt, timestamp: BigInt): void {
8789
updateDataPoint(delta, timestamp, "casesAppealing");
8890
}
91+
92+
export function updateTotalLeaderboardJurors(delta: BigInt, timestamp: BigInt): void {
93+
updateDataPoint(delta, timestamp, "totalLeaderboardJurors");
94+
}

subgraph/core/src/entities/ClassicContribution.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { ClassicContribution } from "../../generated/schema";
22
import { Contribution as ContributionEvent, Withdrawal } from "../../generated/DisputeKitClassic/DisputeKitClassic";
33
import { DISPUTEKIT_ID } from "../DisputeKitClassic";
4+
import { ensureUser } from "./User";
45

56
export function ensureClassicContributionFromEvent<T>(event: T): ClassicContribution | null {
67
if (!(event instanceof ContributionEvent) && !(event instanceof Withdrawal)) return null;
78
const coreDisputeID = event.params._coreDisputeID.toString();
89
const coreRoundIndex = event.params._coreRoundID.toString();
910
const roundID = `${DISPUTEKIT_ID}-${coreDisputeID}-${coreRoundIndex}`;
11+
ensureUser(event.params._contributor.toHexString());
1012
const contributor = event.params._contributor.toHexString();
1113
const choice = event.params._choice;
1214

+30-27
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import { BigInt } from "@graphprotocol/graph-ts";
22
import { Contribution } from "../../generated/DisputeKitClassic/DisputeKitClassic";
3-
import { ClassicRound } from "../../generated/schema";
4-
import { ONE, ZERO } from "../utils";
3+
import { Answer, ClassicRound } from "../../generated/schema";
4+
import { ZERO } from "../utils";
55

66
export function createClassicRound(disputeID: string, numberOfChoices: BigInt, roundIndex: BigInt): void {
7-
const choicesLength = numberOfChoices.plus(ONE);
87
const localDisputeID = `1-${disputeID}`;
98
const id = `${localDisputeID}-${roundIndex.toString()}`;
109
const classicRound = new ClassicRound(id);
1110
classicRound.localDispute = localDisputeID;
1211
classicRound.winningChoice = ZERO;
13-
classicRound.counts = new Array<BigInt>(choicesLength.toI32()).fill(ZERO);
1412
classicRound.tied = true;
1513
classicRound.totalVoted = ZERO;
1614
classicRound.totalCommited = ZERO;
17-
classicRound.paidFees = new Array<BigInt>(choicesLength.toI32()).fill(ZERO);
1815
classicRound.feeRewards = ZERO;
1916
classicRound.appealFeesDispersed = false;
2017
classicRound.totalFeeDispersed = ZERO;
@@ -27,21 +24,31 @@ class CurrentRulingInfo {
2724
tied: boolean;
2825
}
2926

27+
export function ensureAnswer(localRoundId: string, answerId: BigInt): Answer {
28+
const id = `${localRoundId}-${answerId}`;
29+
let answer = Answer.load(id);
30+
if (answer) return answer;
31+
answer = new Answer(id);
32+
answer.answerId = answerId;
33+
answer.count = ZERO;
34+
answer.paidFee = ZERO;
35+
answer.funded = false;
36+
answer.localRound = localRoundId;
37+
return answer;
38+
}
39+
3040
export function updateCountsAndGetCurrentRuling(id: string, choice: BigInt, delta: BigInt): CurrentRulingInfo {
3141
const round = ClassicRound.load(id);
3242
if (!round) return { ruling: ZERO, tied: false };
33-
const choiceNum = choice.toI32();
34-
const newChoiceCount = round.counts[choiceNum].plus(delta);
35-
let newCounts: BigInt[] = [];
36-
for (let i = 0; i < round.counts.length; i++) {
37-
if (BigInt.fromI32(i).equals(choice)) {
38-
newCounts.push(newChoiceCount);
39-
} else {
40-
newCounts.push(round.counts[i]);
41-
}
42-
}
43-
round.counts = newCounts;
44-
const currentWinningCount = round.counts[round.winningChoice.toI32()];
43+
const answer = ensureAnswer(id, choice);
44+
45+
answer.count = answer.count.plus(delta);
46+
47+
const newChoiceCount = answer.count;
48+
49+
const winningAnswer = ensureAnswer(id, round.winningChoice);
50+
const currentWinningCount = winningAnswer.count;
51+
4552
if (choice.equals(round.winningChoice)) {
4653
if (round.tied) round.tied = false;
4754
} else {
@@ -53,6 +60,8 @@ export function updateCountsAndGetCurrentRuling(id: string, choice: BigInt, delt
5360
}
5461
}
5562
round.totalVoted = round.totalVoted.plus(delta);
63+
64+
answer.save();
5665
round.save();
5766
return { ruling: round.winningChoice, tied: round.tied };
5867
}
@@ -68,15 +77,9 @@ export function updateChoiceFundingFromContributionEvent(event: Contribution): v
6877

6978
const choice = event.params._choice;
7079
const amount = event.params._amount;
71-
const currentPaidFees = classicRound.paidFees[choice.toI32()];
72-
let newPaidFees: BigInt[] = [];
73-
for (let i = 0; i < classicRound.paidFees.length; i++) {
74-
if (BigInt.fromI32(i).equals(choice)) {
75-
newPaidFees.push(currentPaidFees.plus(amount));
76-
} else {
77-
newPaidFees.push(classicRound.paidFees[i]);
78-
}
79-
}
80-
classicRound.paidFees = newPaidFees;
80+
const answer = ensureAnswer(roundID, choice);
81+
answer.paidFee = answer.paidFee.plus(amount);
82+
83+
answer.save();
8184
classicRound.save();
8285
}

subgraph/core/src/entities/User.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export function ensureUser(id: string): User {
2727

2828
export function createUserFromAddress(id: string): User {
2929
const user = new User(id);
30+
user.userAddress = id.toLowerCase();
3031
user.totalStake = ZERO;
3132
user.totalDelayed = ZERO;
3233
user.activeDisputes = ZERO;

subgraph/package.json

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "@kleros/kleros-v2-subgraph",
3-
"version": "0.10.1",
3+
"version": "0.11.0",
4+
"drtVersion": "0.11.0",
45
"license": "MIT",
56
"scripts": {
67
"update:core:arbitrum-sepolia-devnet": "./scripts/update.sh arbitrumSepoliaDevnet arbitrum-sepolia core/subgraph.yaml",
@@ -11,9 +12,9 @@
1112
"build:core": "graph build --output-dir core/build/ core/subgraph.yaml",
1213
"test:core": "cd core && graph test",
1314
"clean:core": "graph clean --codegen-dir core/generated/ --build-dir core/build/ ; rm core/subgraph.yaml.bak.*",
14-
"deploy:core:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-core-devnet -l v$npm_package_version core/subgraph.yaml",
15-
"deploy:core:arbitrum-sepolia": "graph deploy --product subgraph-studio kleros-v2-core-testnet -l v$npm_package_version core/subgraph.yaml",
16-
"deploy:core:arbitrum": "graph deploy --product subgraph-studio kleros-v2-core-mainnet -l v$npm_package_version core/subgraph.yaml",
15+
"deploy:core:arbitrum-sepolia-devnet": "graph deploy kleros-v2-core-devnet -l v$npm_package_version core/subgraph.yaml",
16+
"deploy:core:arbitrum-sepolia": "graph deploy kleros-v2-core-testnet -l v$npm_package_version core/subgraph.yaml",
17+
"deploy:core:arbitrum": "graph deploy kleros-v2-core-mainnet -l v$npm_package_version core/subgraph.yaml",
1718
"deploy:core:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-core-local --version-label v$(date +%s) core/subgraph.yaml",
1819
"rebuild-deploy:core:local": "yarn update:core:local && yarn codegen:core && yarn build:core && yarn create:local kleros/kleros-v2-core-local && yarn deploy:core:local",
1920
"": "------------------------------------------------------------------------------------------",
@@ -24,8 +25,8 @@
2425
"build:core-neo": "graph build --output-dir core-neo/build/ core-neo/subgraph.yaml",
2526
"test:core-neo": "cd core-neo && graph test",
2627
"clean:core-neo": "graph clean --codegen-dir core-neo/generated/ --build-dir core-neo/build/ ; rm core-neo/subgraph.yaml.bak.*",
27-
"deploy:core-neo:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-coreneo-devnet -l v$npm_package_version core-neo/subgraph.yaml",
28-
"deploy:core-neo:arbitrum": "graph deploy --product subgraph-studio kleros-v2-coreneo -l v$npm_package_version core-neo/subgraph.yaml",
28+
"deploy:core-neo:arbitrum-sepolia-devnet": "graph deploy kleros-v2-coreneo-devnet -l v$npm_package_version core-neo/subgraph.yaml",
29+
"deploy:core-neo:arbitrum": "graph deploy kleros-v2-coreneo -l v$npm_package_version core-neo/subgraph.yaml",
2930
"deploy:core-neo:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-coreneo-local --version-label v$(date +%s) core-neo/subgraph.yaml",
3031
"rebuild-deploy:core-neo:local": "yarn update:core-neo:local && yarn codegen:core-neo && yarn build:core-neo && yarn create:local kleros/kleros-v2-coreneo-local && yarn deploy:core-neo:local",
3132
"-": "------------------------------------------------------------------------------------------",
@@ -35,7 +36,7 @@
3536
"build:core-university": "graph build --output-dir core-university/build/ core-university/subgraph.yaml",
3637
"test:core-university": "cd core-university && graph test",
3738
"clean:core-university": "graph clean --codegen-dir core-university/generated/ --build-dir core-university/build/ ; rm core-university/subgraph.yaml.bak.*",
38-
"deploy:core-university:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-coreuni-devnet -l v$npm_package_version core-university/subgraph.yaml",
39+
"deploy:core-university:arbitrum-sepolia-devnet": "graph deploy kleros-v2-coreuni-devnet -l v$npm_package_version core-university/subgraph.yaml",
3940
"deploy:core-university:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-coreuni-local --version-label v$(date +%s) core-university/subgraph.yaml",
4041
"rebuild-deploy:core-university:local": "yarn update:core-university:local && yarn codegen:core-university && yarn build:core-university && yarn create:local kleros/kleros-v2-coreuni-local && yarn deploy:core-university:local",
4142
"--": "-----------------------------------------------------------------------------------------",
@@ -47,9 +48,9 @@
4748
"build:drt": "graph build --output-dir dispute-template-registry/generated/ dispute-template-registry/subgraph.yaml",
4849
"test:drt": "cd dispute-template-registry && graph test ",
4950
"clean:drt": "graph clean --codegen-dir dispute-template-registry/generated/ --build-dir dispute-template-registry/build/ ; rm dispute-template-registry/subgraph.yaml.bak.*",
50-
"deploy:drt:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-drt-arbisep-devnet -l v$npm_package_version dispute-template-registry/subgraph.yaml",
51-
"deploy:drt:arbitrum-sepolia": "graph deploy --product subgraph-studio kleros-v2-drt-arbisep-testnet -l v$npm_package_version dispute-template-registry/subgraph.yaml",
52-
"deploy:drt:arbitrum": "graph deploy --product subgraph-studio kleros-v2-drt -l v$npm_package_version dispute-template-registry/subgraph.yaml",
51+
"deploy:drt:arbitrum-sepolia-devnet": "graph deploy kleros-v2-drt-arbisep-devnet -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
52+
"deploy:drt:arbitrum-sepolia": "graph deploy kleros-v2-drt-arbisep-testnet -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
53+
"deploy:drt:arbitrum": "graph deploy kleros-v2-drt -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
5354
"deploy:drt:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-drt-local --version-label v$(date +%s) dispute-template-registry/subgraph.yaml",
5455
"rebuild-deploy:drt:local": "yarn update:drt:local && yarn codegen:drt && yarn build:drt && yarn create:local kleros/kleros-v2-drt-local && yarn deploy:drt:local",
5556
"---": "----------------------------------------------------------------------------------------",

web/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<p align="center">
2-
<b style="font-size: 32px;">Kleros Court v2</b>
2+
<b style="font-size: 32px;">Kleros Court v2 </b>
33
</p>
44

55
<p align="center">

0 commit comments

Comments
 (0)