Skip to content
Merged
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
17 changes: 16 additions & 1 deletion subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,11 @@ type TokenAndETHShift @entity {
id: ID! # user.id-dispute.id
juror: User!
dispute: Dispute!
tokenAmount: BigInt!
pnkAmount: BigInt!
ethAmount: BigInt!
isNativeCurrency: Boolean!
feeTokenAmount: BigInt!
feeToken: FeeToken
}

type JurorTokensPerCourt @entity {
Expand Down Expand Up @@ -159,6 +162,7 @@ type Round @entity {
penalties: BigInt!
drawnJurors: [Draw!]! @derivedFrom(field: "round")
dispute: Dispute!
feeToken: FeeToken
}

type Draw @entity {
Expand Down Expand Up @@ -191,6 +195,17 @@ type Counter @entity {
casesRuled: BigInt!
}

type FeeToken @entity {
id: ID! # The address of the ERC20 token.
accepted: Boolean!
rateInEth: BigInt!
rateDecimals: Int!
totalPaid: BigInt!
totalPaidInETH: BigInt!
rounds: [Round!] @derivedFrom(field: "feeToken")
tokenAndETHShift: [TokenAndETHShift!] @derivedFrom(field: "feeToken")
}

#####################
# ClassicDisputeKit #
#####################
Expand Down
21 changes: 9 additions & 12 deletions subgraph/src/KlerosCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ import {
TokenAndETHShift as TokenAndETHShiftEvent,
Ruling,
StakeDelayed,
AcceptedFeeToken,
} from "../generated/KlerosCore/KlerosCore";
import { ZERO, ONE } from "./utils";
import { createCourtFromEvent, getFeeForJuror } from "./entities/Court";
import { createDisputeKitFromEvent, filterSupportedDisputeKits } from "./entities/DisputeKit";
import { createDisputeFromEvent } from "./entities/Dispute";
import { createRoundFromRoundInfo } from "./entities/Round";
import { updateCases, updatePaidETH, updateRedistributedPNK, updateCasesRuled, updateCasesVoting } from "./datapoint";
import { updateCases, updateCasesRuled, updateCasesVoting } from "./datapoint";
import { addUserActiveDispute, ensureUser } from "./entities/User";
import { updateJurorDelayedStake, updateJurorStake } from "./entities/JurorTokensPerCourt";
import { createDrawFromEvent } from "./entities/Draw";
import { updateTokenAndEthShiftFromEvent } from "./entities/TokenAndEthShift";
import { updateArbitrableCases } from "./entities/Arbitrable";
import { Court, Dispute } from "../generated/schema";
import { Court, Dispute, FeeToken } from "../generated/schema";
import { BigInt } from "@graphprotocol/graph-ts";
import { updatePenalty } from "./entities/Penalty";
import { ensureFeeToken } from "./entities/FeeToken";

function getPeriodName(index: i32): string {
const periodArray = ["evidence", "commit", "vote", "appeal", "execution"];
Expand Down Expand Up @@ -156,22 +158,17 @@ export function handleStakeDelayed(event: StakeDelayed): void {
}

export function handleTokenAndETHShift(event: TokenAndETHShiftEvent): void {
updatePenalty(event);
updateTokenAndEthShiftFromEvent(event);
const jurorAddress = event.params._account.toHexString();
const disputeID = event.params._disputeID.toString();
const pnkAmount = event.params._pnkAmount;
const feeAmount = event.params._feeAmount;
const dispute = Dispute.load(disputeID);
if (!dispute) return;
const court = Court.load(dispute.court);
if (!court) return;
updateJurorStake(jurorAddress, court.id, KlerosCore.bind(event.address), event.block.timestamp);
court.paidETH = court.paidETH.plus(feeAmount);
if (pnkAmount.gt(ZERO)) {
court.paidPNK = court.paidPNK.plus(pnkAmount);
updateRedistributedPNK(pnkAmount, event.block.timestamp);
}
updatePaidETH(feeAmount, event.block.timestamp);
updatePenalty(event);
court.save();
}

export function handleAcceptedFeeToken(event: AcceptedFeeToken): void {
ensureFeeToken(event.params._token, event.address);
}
53 changes: 53 additions & 0 deletions subgraph/src/entities/FeeToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { BigInt, Address } from "@graphprotocol/graph-ts";
import { FeeToken } from "../../generated/schema";
import { KlerosCore } from "../../generated/KlerosCore/KlerosCore";
import { ZERO } from "../utils";

export function ensureFeeToken(tokenAddress: Address, klerosCoreAddress: Address): FeeToken {
const hexTokenAddress = tokenAddress.toHexString();
let feeToken = FeeToken.load(hexTokenAddress);
if (!feeToken) {
feeToken = new FeeToken(hexTokenAddress);
feeToken.totalPaid = ZERO;
feeToken.totalPaidInETH = ZERO;
}
const contract = KlerosCore.bind(klerosCoreAddress);
const currencyRate = contract.currencyRates(tokenAddress);
feeToken.accepted = currencyRate.value0;
feeToken.rateInEth = currencyRate.value1;
feeToken.rateDecimals = currencyRate.value2;
feeToken.save();
return feeToken;
}

export function updateFeeTokenRate(tokenAddress: Address, klerosCoreAddress: Address): void {
const feeToken = ensureFeeToken(tokenAddress, klerosCoreAddress);
const contract = KlerosCore.bind(klerosCoreAddress);
const currencyRate = contract.currencyRates(tokenAddress);
feeToken.accepted = currencyRate.value0;
feeToken.rateInEth = currencyRate.value1;
feeToken.rateDecimals = currencyRate.value2;
feeToken.save();
}

export function updateFeeTokenPaid(tokenAddress: Address, klerosCoreAddress: Address, amount: BigInt): void {
const feeToken = ensureFeeToken(tokenAddress, klerosCoreAddress);
const ethAmount = convertTokenAmountToEth(tokenAddress, amount, klerosCoreAddress);
feeToken.totalPaid = feeToken.totalPaid.plus(amount);
feeToken.totalPaidInETH = feeToken.totalPaidInETH.plus(ethAmount);
feeToken.save();
}

export function convertEthToTokenAmount(tokenAddress: Address, eth: BigInt, klerosCoreAddress: Address): BigInt {
const feeToken = ensureFeeToken(tokenAddress, klerosCoreAddress);
return eth.times(BigInt.fromI32(10 ** feeToken.rateDecimals)).div(feeToken.rateInEth);
}

export function convertTokenAmountToEth(
tokenAddress: Address,
tokenAmount: BigInt,
klerosCoreAddress: Address
): BigInt {
const feeToken = ensureFeeToken(tokenAddress, klerosCoreAddress);
return tokenAmount.times(feeToken.rateInEth).div(BigInt.fromI32(10 ** feeToken.rateDecimals));
}
3 changes: 3 additions & 0 deletions subgraph/src/entities/Round.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ export function createRoundFromRoundInfo(
): void {
const roundID = `${disputeID.toString()}-${roundIndex.toString()}`;
const round = new Round(roundID);
const feeToken = roundInfo.getFeeToken();
round.disputeKit = roundInfo.getDisputeKitID.toString();
round.tokensAtStakePerJuror = roundInfo.getPnkAtStakePerJuror();
round.totalFeesForJurors = roundInfo.getTotalFeesForJurors();
round.nbVotes = roundInfo.getNbVotes();
round.repartitions = roundInfo.getRepartitions();
round.penalties = roundInfo.getPnkPenalties();
round.dispute = disputeID.toString();
round.feeToken =
feeToken.toHexString() === "0x0000000000000000000000000000000000000000" ? null : feeToken.toHexString();
round.save();
}
84 changes: 58 additions & 26 deletions subgraph/src/entities/TokenAndEthShift.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,68 @@
import { Address, BigInt } from "@graphprotocol/graph-ts";
import { TokenAndETHShift as TokenAndETHShiftEvent } from "../../generated/KlerosCore/KlerosCore";
import { TokenAndETHShift } from "../../generated/schema";
import { Court, Dispute, TokenAndETHShift } from "../../generated/schema";
import { updatePaidETH, updateRedistributedPNK } from "../datapoint";
import { ZERO } from "../utils";
import { convertTokenAmountToEth, updateFeeTokenPaid } from "./FeeToken";
import { resolveUserDispute } from "./User";

export function updateTokenAndEthShiftFromEvent(event: TokenAndETHShiftEvent): void {
const jurorAddress = event.params._account.toHexString();
const disputeID = event.params._disputeID.toString();
const shiftID = `${jurorAddress}-${disputeID}`;
const shift = TokenAndETHShift.load(shiftID);

if (!shift) {
createTokenAndEthShiftFromEvent(event);
resolveUserDispute(jurorAddress, ZERO, event.params._feeAmount, disputeID);
return;
const jurorAddress = event.params._account;
const disputeID = event.params._disputeID;
const dispute = Dispute.load(disputeID.toString());
if (!dispute) return;
const court = Court.load(dispute.court);
if (!court) return;
const roundIndex = event.params._roundID;
const feeTokenAddress = event.params._feeToken;
let shift = ensureTokenAndEthShift(jurorAddress, disputeID, roundIndex, feeTokenAddress);
const feeAmount = event.params._feeAmount;
const pnkAmount = event.params._pnkAmount;
let ethAmount: BigInt;
if (feeTokenAddress.toHexString() === "0x0000000000000000000000000000000000000000") {
updateFeeTokenPaid(feeTokenAddress, event.address, feeAmount);
ethAmount = convertTokenAmountToEth(feeTokenAddress, feeAmount, event.address);
shift.feeTokenAmount = shift.feeTokenAmount.plus(feeAmount);
} else {
ethAmount = feeAmount;
}

shift.tokenAmount = shift.tokenAmount.plus(event.params._pnkAmount);
const previousFeeAmount = shift.ethAmount;
const newFeeAmount = shift.ethAmount.plus(event.params._feeAmount);
shift.ethAmount = newFeeAmount;
const previousEthAmount = shift.ethAmount;
const newEthAmount = previousEthAmount.plus(ethAmount);
shift.ethAmount = newEthAmount;
resolveUserDispute(jurorAddress.toHexString(), previousEthAmount, newEthAmount, disputeID.toString());
court.paidETH = court.paidETH.plus(ethAmount);
updatePaidETH(ethAmount, event.block.timestamp);
if (pnkAmount.gt(ZERO)) {
court.paidPNK = court.paidPNK.plus(pnkAmount);
updateRedistributedPNK(pnkAmount, event.block.timestamp);
}
shift.pnkAmount = shift.pnkAmount.plus(pnkAmount);
shift.save();
resolveUserDispute(jurorAddress, previousFeeAmount, newFeeAmount, disputeID);
court.save();
}

export function createTokenAndEthShiftFromEvent(event: TokenAndETHShiftEvent): void {
const jurorAddress = event.params._account.toHexString();
const disputeID = event.params._disputeID.toString();
const shiftID = `${jurorAddress}-${disputeID}`;
const shift = new TokenAndETHShift(shiftID);
shift.juror = jurorAddress;
shift.dispute = disputeID;
shift.tokenAmount = event.params._pnkAmount;
shift.ethAmount = event.params._feeAmount;
shift.save();
export function ensureTokenAndEthShift(
jurorAddress: Address,
disputeID: BigInt,
roundIndex: BigInt,
feeTokenAddress: Address
): TokenAndETHShift {
const shiftID = `${jurorAddress.toHexString()}-${disputeID.toString()}-${roundIndex.toString()}`;
let shift = TokenAndETHShift.load(shiftID);
if (!shift) {
shift = new TokenAndETHShift(shiftID);
if (feeTokenAddress !== Address.fromI32(0)) {
shift.isNativeCurrency = false;
shift.feeToken = feeTokenAddress.toHexString();
} else {
shift.isNativeCurrency = true;
}
shift.feeTokenAmount = ZERO;
shift.ethAmount = ZERO;
shift.juror = jurorAddress.toHexString();
shift.dispute = disputeID.toString();
shift.pnkAmount = ZERO;
shift.save();
}
return shift;
}
2 changes: 2 additions & 0 deletions subgraph/subgraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ dataSources:
handler: handleTokenAndETHShift
- event: Ruling(indexed address,indexed uint256,uint256)
handler: handleRuling
- event: AcceptedFeeToken(indexed address,indexed bool)
handler: handleAcceptedFeeToken
file: ./src/KlerosCore.ts
- kind: ethereum
name: PolicyRegistry
Expand Down