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
32 changes: 9 additions & 23 deletions subgraph/core/src/KlerosCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { createDisputeFromEvent } from "./entities/Dispute";
import { createRoundFromRoundInfo } from "./entities/Round";
import { updateCases, updateCasesAppealing, updateCasesRuled, updateCasesVoting } from "./datapoint";
import { addUserActiveDispute, ensureUser } from "./entities/User";
import { updateJurorDelayedStake, updateJurorStake } from "./entities/JurorTokensPerCourt";
import { updateJurorStake } from "./entities/JurorTokensPerCourt";
import { createDrawFromEvent } from "./entities/Draw";
import { updateTokenAndEthShiftFromEvent } from "./entities/TokenAndEthShift";
import { updateArbitrableCases } from "./entities/Arbitrable";
Expand All @@ -29,6 +29,7 @@ import { BigInt } from "@graphprotocol/graph-ts";
import { updatePenalty } from "./entities/Penalty";
import { ensureFeeToken } from "./entities/FeeToken";
import { getAndIncrementPeriodCounter } from "./entities/PeriodIndexCounter";
import { SortitionModule } from "../generated/SortitionModule/SortitionModule";

function getPeriodName(index: i32): string {
const periodArray = ["evidence", "commit", "vote", "appeal", "execution"];
Expand Down Expand Up @@ -177,31 +178,14 @@ export function handleDraw(event: DrawEvent): void {
const disputeID = event.params._disputeID.toString();
const dispute = Dispute.load(disputeID);
if (!dispute) return;
const contract = KlerosCore.bind(event.address);
const klerosCore = KlerosCore.bind(event.address);
const sortitionModule = SortitionModule.bind(klerosCore.sortitionModule());

const jurorAddress = event.params._address.toHexString();
updateJurorStake(jurorAddress, dispute.court, contract, event.block.timestamp);
updateJurorStake(jurorAddress, dispute.court, sortitionModule, event.block.timestamp);
addUserActiveDispute(jurorAddress, disputeID);
}

// TODO: index the sortition module and handle these events there
// export function handleStakeSet(event: StakeSet): void {
// const jurorAddress = event.params._address.toHexString();
// ensureUser(jurorAddress);
// const courtID = event.params._courtID.toString();

// updateJurorStake(jurorAddress, courtID.toString(), KlerosCore.bind(event.address), event.block.timestamp);

// // Check if the transaction the event comes from is executeDelayedStakes
// if (event.transaction.input.toHexString().substring(0, 10) === "0x35975f4a") {
// updateJurorDelayedStake(jurorAddress, courtID, ZERO.minus(event.params._amount));
// }
// }

// TODO: index the sortition module and handle these events there
// export function handleStakeDelayedNotTransferred(event: StakeDelayedNotTransferred): void {
// updateJurorDelayedStake(event.params._address.toHexString(), event.params._courtID.toString(), event.params._amount);
// }

export function handleTokenAndETHShift(event: TokenAndETHShiftEvent): void {
updatePenalty(event);
updateTokenAndEthShiftFromEvent(event);
Expand All @@ -211,7 +195,9 @@ export function handleTokenAndETHShift(event: TokenAndETHShiftEvent): void {
if (!dispute) return;
const court = Court.load(dispute.court);
if (!court) return;
updateJurorStake(jurorAddress, court.id, KlerosCore.bind(event.address), event.block.timestamp);
const klerosCore = KlerosCore.bind(event.address);
const sortitionModule = SortitionModule.bind(klerosCore.sortitionModule());
updateJurorStake(jurorAddress, court.id, sortitionModule, event.block.timestamp);
}

export function handleAcceptedFeeToken(event: AcceptedFeeToken): void {
Expand Down
48 changes: 48 additions & 0 deletions subgraph/core/src/SortitionModule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
SortitionModule,
StakeDelayedAlreadyTransferred,
StakeDelayedAlreadyTransferredWithdrawn,
StakeDelayedNotTransferred,
StakeLocked,
StakeSet,
} from "../generated/SortitionModule/SortitionModule";

import { updateJurorDelayedStake, updateJurorStake } from "./entities/JurorTokensPerCourt";
import { ensureUser } from "./entities/User";
import { ZERO } from "./utils";

export function handleStakeDelayedAlreadyTransferred(event: StakeDelayedAlreadyTransferred): void {
const jurorAddress = event.params._address.toHexString();
ensureUser(jurorAddress);
const courtID = event.params._courtID.toString();

updateJurorStake(jurorAddress, courtID.toString(), SortitionModule.bind(event.address), event.block.timestamp);

//stake is updated instantly so no delayed amount, set delay amount to zero
updateJurorDelayedStake(jurorAddress, courtID, ZERO);
}

export function handleStakeDelayedAlreadyTransferredWithdrawn(event: StakeDelayedAlreadyTransferredWithdrawn): void {
const jurorAddress = event.params._address.toHexString();
ensureUser(jurorAddress);
const courtID = event.params._courtID.toString();

updateJurorStake(jurorAddress, courtID.toString(), SortitionModule.bind(event.address), event.block.timestamp);

updateJurorDelayedStake(jurorAddress, courtID, ZERO);
}

export function handleStakeDelayedNotTransferred(event: StakeDelayedNotTransferred): void {
updateJurorDelayedStake(event.params._address.toHexString(), event.params._courtID.toString(), event.params._amount);
}

export function handleStakeSet(event: StakeSet): void {
const jurorAddress = event.params._address.toHexString();
ensureUser(jurorAddress);
const courtID = event.params._courtID.toString();

updateJurorStake(jurorAddress, courtID.toString(), SortitionModule.bind(event.address), event.block.timestamp);
//stake is updated instantly so no delayed amount, set delay amount to zero
updateJurorDelayedStake(jurorAddress, courtID, ZERO);
}
export function handleStakeLocked(event: StakeLocked): void {}
18 changes: 13 additions & 5 deletions subgraph/core/src/entities/JurorTokensPerCourt.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BigInt, Address } from "@graphprotocol/graph-ts";
import { KlerosCore } from "../../generated/KlerosCore/KlerosCore";
import { Court, JurorTokensPerCourt } from "../../generated/schema";
import { updateActiveJurors, getDelta, updateStakedPNK } from "../datapoint";
import { ensureUser } from "./User";
import { ONE, ZERO } from "../utils";
import { SortitionModule } from "../../generated/SortitionModule/SortitionModule";

export function ensureJurorTokensPerCourt(jurorAddress: string, courtID: string): JurorTokensPerCourt {
const id = `${jurorAddress}-${courtID}`;
Expand All @@ -30,7 +30,12 @@ export function createJurorTokensPerCourt(jurorAddress: string, courtID: string)
return jurorTokens;
}

export function updateJurorStake(jurorAddress: string, courtID: string, contract: KlerosCore, timestamp: BigInt): void {
export function updateJurorStake(
jurorAddress: string,
courtID: string,
contract: SortitionModule,
timestamp: BigInt
): void {
const juror = ensureUser(jurorAddress);
const court = Court.load(courtID);
if (!court) return;
Expand Down Expand Up @@ -61,9 +66,12 @@ export function updateJurorDelayedStake(jurorAddress: string, courtID: string, a
const court = Court.load(courtID);
if (!court) return;
const jurorTokens = ensureJurorTokensPerCourt(jurorAddress, courtID);
jurorTokens.delayed = jurorTokens.delayed.plus(amount);
juror.totalDelayed = juror.totalDelayed.plus(amount);
court.delayedStake = court.stake.plus(amount);
let lastDelayedAmount = jurorTokens.delayed;

jurorTokens.delayed = amount;
//since we need to track only the latest delay amount now, subtract the previous amount and add the new amount
juror.totalDelayed = juror.totalDelayed.plus(amount).minus(lastDelayedAmount);
court.delayedStake = court.stake.plus(amount).minus(lastDelayedAmount);
jurorTokens.save();
juror.save();
court.save();
Expand Down
33 changes: 28 additions & 5 deletions subgraph/core/subgraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ dataSources:
handler: handleDisputeKitCreated
- event: DisputeKitEnabled(indexed uint96,indexed uint256,indexed bool)
handler: handleDisputeKitEnabled
# TODO: index the sortition module and handle these events there
# - event: StakeSet(indexed address,uint256,uint256)
# handler: handleStakeSet
# - event: StakeDelayedNotTransferred(indexed address,uint256,uint256)
# handler: handleStakeDelayedNotTransferred
- event: TokenAndETHShift(indexed address,indexed uint256,indexed uint256,uint256,int256,int256,address)
handler: handleTokenAndETHShift
- event: Ruling(indexed address,indexed uint256,uint256)
Expand Down Expand Up @@ -136,3 +131,31 @@ dataSources:
- event: Evidence(indexed uint256,indexed address,string)
handler: handleEvidenceEvent
file: ./src/EvidenceModule.ts
- kind: ethereum
name: SortitionModule
network: arbitrum-sepolia
source:
address: "0xf327200420F21BAafce8F1C03B1EEdF926074B95"
abi: SortitionModule
startBlock: 3084593
mapping:
kind: ethereum/events
apiVersion: 0.0.6
language: wasm/assemblyscript
entities:
- JurorTokensPerCourt
abis:
- name: SortitionModule
file: ../../contracts/deployments/arbitrumSepoliaDevnet/SortitionModule.json
eventHandlers:
- event: StakeDelayedAlreadyTransferred(indexed address,uint256,uint256)
handler: handleStakeDelayedAlreadyTransferred
- event: StakeDelayedAlreadyTransferredWithdrawn(indexed address,indexed uint96,uint256)
handler: handleStakeDelayedAlreadyTransferredWithdrawn
- event: StakeDelayedNotTransferred(indexed address,uint256,uint256)
handler: handleStakeDelayedNotTransferred
- event: StakeLocked(indexed address,uint256,bool)
handler: handleStakeLocked
- event: StakeSet(indexed address,uint256,uint256)
handler: handleStakeSet
file: ./src/SortitionModule.ts
101 changes: 101 additions & 0 deletions subgraph/core/tests/sortition-module-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { newMockEvent } from "matchstick-as";
import { ethereum, BigInt, Address } from "@graphprotocol/graph-ts";
import {
StakeDelayedAlreadyTransferred,
StakeDelayedAlreadyTransferredWithdrawn,
StakeDelayedNotTransferred,
StakeLocked,
StakeSet,
} from "../generated/SortitionModule/SortitionModule";

export function createStakeDelayedAlreadyTransferredEvent(
_address: Address,
_courtID: BigInt,
_amount: BigInt
): StakeDelayedAlreadyTransferred {
let stakeDelayedAlreadyTransferredEvent: StakeDelayedAlreadyTransferred = newMockEvent();

stakeDelayedAlreadyTransferredEvent.parameters = new Array();

stakeDelayedAlreadyTransferredEvent.parameters.push(
new ethereum.EventParam("_address", ethereum.Value.fromAddress(_address))
);
stakeDelayedAlreadyTransferredEvent.parameters.push(
new ethereum.EventParam("_courtID", ethereum.Value.fromUnsignedBigInt(_courtID))
);
stakeDelayedAlreadyTransferredEvent.parameters.push(
new ethereum.EventParam("_amount", ethereum.Value.fromUnsignedBigInt(_amount))
);

return stakeDelayedAlreadyTransferredEvent;
}

export function createStakeDelayedAlreadyTransferredWithdrawnEvent(
_address: Address,
_courtID: BigInt,
_amount: BigInt
): StakeDelayedAlreadyTransferredWithdrawn {
let stakeDelayedAlreadyTransferredWithdrawnEvent = newMockEvent();

stakeDelayedAlreadyTransferredWithdrawnEvent.parameters = new Array();

stakeDelayedAlreadyTransferredWithdrawnEvent.parameters.push(
new ethereum.EventParam("_address", ethereum.Value.fromAddress(_address))
);
stakeDelayedAlreadyTransferredWithdrawnEvent.parameters.push(
new ethereum.EventParam("_courtID", ethereum.Value.fromUnsignedBigInt(_courtID))
);
stakeDelayedAlreadyTransferredWithdrawnEvent.parameters.push(
new ethereum.EventParam("_amount", ethereum.Value.fromUnsignedBigInt(_amount))
);

return stakeDelayedAlreadyTransferredWithdrawnEvent;
}

export function createStakeDelayedNotTransferredEvent(
_address: Address,
_courtID: BigInt,
_amount: BigInt
): StakeDelayedNotTransferred {
let stakeDelayedNotTransferredEvent = newMockEvent();

stakeDelayedNotTransferredEvent.parameters = new Array();

stakeDelayedNotTransferredEvent.parameters.push(
new ethereum.EventParam("_address", ethereum.Value.fromAddress(_address))
);
stakeDelayedNotTransferredEvent.parameters.push(
new ethereum.EventParam("_courtID", ethereum.Value.fromUnsignedBigInt(_courtID))
);
stakeDelayedNotTransferredEvent.parameters.push(
new ethereum.EventParam("_amount", ethereum.Value.fromUnsignedBigInt(_amount))
);

return stakeDelayedNotTransferredEvent;
}

export function createStakeLockedEvent(_address: Address, _relativeAmount: BigInt, _unlock: boolean): StakeLocked {
let stakeLockedEvent = newMockEvent();

stakeLockedEvent.parameters = new Array();

stakeLockedEvent.parameters.push(new ethereum.EventParam("_address", ethereum.Value.fromAddress(_address)));
stakeLockedEvent.parameters.push(
new ethereum.EventParam("_relativeAmount", ethereum.Value.fromUnsignedBigInt(_relativeAmount))
);
stakeLockedEvent.parameters.push(new ethereum.EventParam("_unlock", ethereum.Value.fromBoolean(_unlock)));

return stakeLockedEvent;
}

export function createStakeSetEvent(_address: Address, _courtID: BigInt, _amount: BigInt): StakeSet {
let stakeSetEvent = newMockEvent();

stakeSetEvent.parameters = new Array();

stakeSetEvent.parameters.push(new ethereum.EventParam("_address", ethereum.Value.fromAddress(_address)));
stakeSetEvent.parameters.push(new ethereum.EventParam("_courtID", ethereum.Value.fromUnsignedBigInt(_courtID)));
stakeSetEvent.parameters.push(new ethereum.EventParam("_amount", ethereum.Value.fromUnsignedBigInt(_amount)));

return stakeSetEvent;
}
39 changes: 39 additions & 0 deletions subgraph/core/tests/sortition-module.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { assert, describe, test, clearStore, beforeAll, afterAll } from "matchstick-as/assembly/index";
import { BigInt, Address } from "@graphprotocol/graph-ts";
import { handleStakeSet } from "../src/SortitionModule";
import { createStakeSetEvent } from "./sortition-module-utils";

// Tests structure (matchstick-as >=0.5.0)
// https://thegraph.com/docs/en/developer/matchstick/#tests-structure-0-5-0

describe("Describe event", () => {
beforeAll(() => {
let courtId = BigInt.fromI32(1);
let amount = BigInt.fromI32(1000);
let jurorAddress = Address.fromString("0x922911F4f80a569a4425fa083456239838F7F003");
let newStakeSetEvent = createStakeSetEvent(jurorAddress, courtId, amount);
handleStakeSet(newStakeSetEvent);
});

afterAll(() => {
clearStore();
});

// For more test scenarios, see:
// https://thegraph.com/docs/en/developer/matchstick/#write-a-unit-test

test("Initialized created and stored", () => {
assert.entityCount("Initialized", 1);

// 0xa16081f360e3847006db660bae1c6d1b2e17ec2a is the default address used in newMockEvent() function
// assert.fieldEquals(
// "Initialized",
// "0xa16081f360e3847006db660bae1c6d1b2e17ec2a-1",
// "version",
// "234"
// )

// More assert options:
// https://thegraph.com/docs/en/developer/matchstick/#asserts
});
});