Skip to content

Commit 6b8f08d

Browse files
authored
Merge branch 'dev' into dev
2 parents 49ae1e1 + 4adedb5 commit 6b8f08d

File tree

14 files changed

+121
-20
lines changed

14 files changed

+121
-20
lines changed

contracts/deploy/upgrade-all.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const deployUpgradeAll: DeployFunction = async (hre: HardhatRuntimeEnvironment)
8181
await upgrade(disputeKitClassic, "initialize6", []);
8282
await upgrade(disputeTemplateRegistry, "initialize2", []);
8383
await upgrade(evidence, "initialize2", []);
84-
await upgrade(core, "initialize4", []);
84+
await upgrade(core, "initialize5", []);
8585
await upgrade(policyRegistry, "initialize2", []);
8686
await upgrade(sortition, "initialize3", []);
8787
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#! /usr/bin/env bash
2+
3+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
4+
5+
declare -A rpcUrls
6+
rpcUrls["arbitrum"]=$(mesc url arbitrum_alchemy)
7+
rpcUrls["arbitrumSepolia"]=$(mesc url arbitrumSepolia_alchemy)
8+
rpcUrls["arbitrumSepoliaDevnet"]=$(mesc url arbitrumSepolia_alchemy)
9+
10+
# event Initialized(uint64 version);
11+
eventTopic=0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2
12+
13+
for c in arbitrum arbitrumSepolia arbitrumSepoliaDevnet; do
14+
echo "--------------------------------"
15+
echo "$c"
16+
echo "--------------------------------"
17+
for f in "$SCRIPT_DIR"/../deployments/"$c"/*_Proxy.json; do
18+
address=$(jq -r .address "$f")
19+
block=$(jq -r .receipt.blockNumber "$f")
20+
basename "$f"
21+
results=$(cast logs --from-block "$block" --to-block latest $eventTopic --address "$address" --rpc-url "${rpcUrls[$c]}" --json | jq -r .[].data)
22+
initializer=$(cast --to-dec "$(echo "$results" | tail -n1)")
23+
version=$(cast call --rpc-url "${rpcUrls[$c]}" "$address" "version()(string)" --json 2>/dev/null | jq -r '.[0]')
24+
echo "$initializer" @v"$version"
25+
echo
26+
done
27+
done

contracts/scripts/keeperBot.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Cores, getContracts as getContractsForCoreType } from "./utils/contract
77

88
let request: <T>(url: string, query: string) => Promise<T>; // Workaround graphql-request ESM import
99
const { ethers } = hre;
10+
const MAX_DRAW_CALLS_WITHOUT_JURORS = 10;
1011
const MAX_DRAW_ITERATIONS = 30;
1112
const MAX_EXECUTE_ITERATIONS = 20;
1213
const MAX_DELAYED_STAKES_ITERATIONS = 50;
@@ -248,7 +249,19 @@ const drawJurors = async (dispute: { id: string; currentRoundIndex: string }, it
248249
const { core } = await getContracts();
249250
let success = false;
250251
try {
251-
await core.draw.staticCall(dispute.id, iterations, HIGH_GAS_LIMIT);
252+
const simulatedIterations = iterations * MAX_DRAW_CALLS_WITHOUT_JURORS; // Drawing will be skipped as long as no juror is available in the next MAX_DRAW_CALLS_WITHOUT_JURORS calls to draw() given this nb of iterations.
253+
const { drawnJurors: drawnJurorsBefore } = await core.getRoundInfo(dispute.id, dispute.currentRoundIndex);
254+
const nbDrawnJurors = (await core.draw.staticCall(dispute.id, simulatedIterations, HIGH_GAS_LIMIT)) as bigint;
255+
const extraJurors = nbDrawnJurors - BigInt(drawnJurorsBefore.length);
256+
logger.debug(
257+
`Draw: ${extraJurors} jurors available in the next ${simulatedIterations} iterations for dispute ${dispute.id}`
258+
);
259+
if (extraJurors <= 0n) {
260+
logger.warn(
261+
`Draw: skipping, no jurors available in the next ${simulatedIterations} iterations for dispute ${dispute.id}`
262+
);
263+
return success;
264+
}
252265
} catch (e) {
253266
logger.error(`Draw: will fail for ${dispute.id}, skipping`);
254267
return success;

contracts/src/arbitration/KlerosCore.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {KlerosCoreBase, IDisputeKit, ISortitionModule, IERC20} from "./KlerosCor
88
/// Core arbitrator contract for Kleros v2.
99
/// Note that this contract trusts the PNK token, the dispute kit and the sortition module contracts.
1010
contract KlerosCore is KlerosCoreBase {
11-
string public constant override version = "0.9.3";
11+
string public constant override version = "0.9.4";
1212

1313
// ************************************* //
1414
// * Constructor * //
@@ -56,7 +56,7 @@ contract KlerosCore is KlerosCoreBase {
5656
);
5757
}
5858

59-
function initialize4() external reinitializer(4) {
59+
function initialize5() external reinitializer(5) {
6060
// NOP
6161
}
6262

contracts/src/arbitration/KlerosCoreBase.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,8 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
593593
/// @dev Draws jurors for the dispute. Can be called in parts.
594594
/// @param _disputeID The ID of the dispute.
595595
/// @param _iterations The number of iterations to run.
596-
function draw(uint256 _disputeID, uint256 _iterations) external {
596+
/// @return nbDrawnJurors The total number of jurors drawn in the round.
597+
function draw(uint256 _disputeID, uint256 _iterations) external returns (uint256 nbDrawnJurors) {
597598
Dispute storage dispute = disputes[_disputeID];
598599
uint256 currentRound = dispute.rounds.length - 1;
599600
Round storage round = dispute.rounds[currentRound];
@@ -616,6 +617,7 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
616617
}
617618
}
618619
round.drawIterations += i;
620+
return round.drawnJurors.length;
619621
}
620622

621623
/// @dev Appeals the ruling of a specified dispute.

contracts/src/arbitration/KlerosCoreNeo.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
99
/// Core arbitrator contract for Kleros v2.
1010
/// Note that this contract trusts the PNK token, the dispute kit and the sortition module contracts.
1111
contract KlerosCoreNeo is KlerosCoreBase {
12-
string public constant override version = "0.8.0";
12+
string public constant override version = "0.9.4";
1313

1414
// ************************************* //
1515
// * Storage * //
@@ -67,7 +67,7 @@ contract KlerosCoreNeo is KlerosCoreBase {
6767
jurorNft = _jurorNft;
6868
}
6969

70-
function initialize4() external reinitializer(4) {
70+
function initialize5() external reinitializer(5) {
7171
// NOP
7272
}
7373

subgraph/core/src/KlerosCore.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,19 @@ export function handleAppealDecision(event: AppealDecision): void {
215215
const disputeID = event.params._disputeID;
216216
const dispute = Dispute.load(disputeID.toString());
217217
if (!dispute) return;
218+
219+
// Load the current (previous) round
220+
const previousRoundID = dispute.currentRound;
221+
const previousRound = Round.load(previousRoundID);
222+
if (previousRound) {
223+
previousRound.isCurrentRound = false;
224+
previousRound.save();
225+
}
226+
218227
const newRoundIndex = dispute.currentRoundIndex.plus(ONE);
219-
const roundID = `${disputeID}-${newRoundIndex.toString()}`;
228+
const newRoundID = `${disputeID}-${newRoundIndex.toString()}`;
220229
dispute.currentRoundIndex = newRoundIndex;
221-
dispute.currentRound = roundID;
230+
dispute.currentRound = newRoundID;
222231
dispute.save();
223232
const roundInfo = contract.getRoundInfo(disputeID, newRoundIndex);
224233

subgraph/core/src/entities/Dispute.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,36 @@ export const updateDisputeRequestData = (event: DisputeCreation): void => {
5757
if (!receipt) return;
5858

5959
const logs = receipt.logs;
60+
const coreDisputeId = event.params._disputeID;
6061

6162
// note that the topic at 0th index is always the event signature
62-
const disputeRequestEventIndex = logs.findIndex((log) => log.topics[0] == DisputeRequestSignature);
63-
const crossChainDisputeEventIndex = logs.findIndex((log) => log.topics[0] == CrossChainDisputeIncomingSignature);
63+
// For DisputeRequestSignature
64+
let disputeRequestEventIndex = -1;
65+
for (let i = 0; i < logs.length; i++) {
66+
let log = logs[i];
67+
if (log.topics.length > 2 && log.topics[0] == DisputeRequestSignature) {
68+
// 3rd indexed argument in event is _arbitratorDisputeId
69+
let decodedId = ethereum.decode("uint256", log.topics[2]);
70+
if (decodedId != null && coreDisputeId.equals(decodedId.toBigInt())) {
71+
disputeRequestEventIndex = i;
72+
break;
73+
}
74+
}
75+
}
76+
77+
// For CrossChainDisputeIncomingSignature
78+
let crossChainDisputeEventIndex = -1;
79+
for (let i = 0; i < logs.length; i++) {
80+
let log = logs[i];
81+
if (log.topics.length > 3 && log.topics[0] == CrossChainDisputeIncomingSignature) {
82+
// 4th indexed argument in event is _arbitratorDisputeId
83+
let decodedId = ethereum.decode("uint256", log.topics[3]);
84+
if (decodedId != null && coreDisputeId.equals(decodedId.toBigInt())) {
85+
crossChainDisputeEventIndex = i;
86+
break;
87+
}
88+
}
89+
}
6490

6591
if (crossChainDisputeEventIndex !== -1) {
6692
const crossChainDisputeEvent = logs[crossChainDisputeEventIndex];

subgraph/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kleros/kleros-v2-subgraph",
3-
"version": "0.15.2",
3+
"version": "0.15.4",
44
"drtVersion": "0.12.0",
55
"license": "MIT",
66
"scripts": {

web/src/components/DisputePreview/Policies.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from "react";
22
import styled, { css } from "styled-components";
33

4+
import { useParams } from "react-router-dom";
5+
46
import PaperclipIcon from "svgs/icons/paperclip.svg";
57
import PolicyIcon from "svgs/icons/policy.svg";
68

@@ -67,17 +69,23 @@ interface IPolicies {
6769
}
6870

6971
export const Policies: React.FC<IPolicies> = ({ disputePolicyURI, courtId, attachment }) => {
72+
const { id } = useParams();
73+
7074
return (
7175
<Container>
7276
<StyledP>Policy documents:</StyledP>
7377
{!isUndefined(attachment) && !isUndefined(attachment.uri) ? (
74-
<StyledInternalLink to={`/attachment/?title=${"Case Policy"}&url=${getIpfsUrl(attachment.uri)}`}>
78+
<StyledInternalLink
79+
to={`/attachment/?disputeId=${id}&title=${"Case Policy"}&url=${getIpfsUrl(attachment.uri)}`}
80+
>
7581
<StyledPaperclipIcon />
7682
{attachment.label ?? "Attachment"}
7783
</StyledInternalLink>
7884
) : null}
7985
{isUndefined(disputePolicyURI) ? null : (
80-
<StyledInternalLink to={`/attachment/?title=${"Dispute Policy"}&url=${getIpfsUrl(disputePolicyURI)}`}>
86+
<StyledInternalLink
87+
to={`/attachment/?disputeId=${id}&title=${"Dispute Policy"}&url=${getIpfsUrl(disputePolicyURI)}`}
88+
>
8189
<StyledPolicyIcon />
8290
Dispute Policy
8391
</StyledInternalLink>

web/src/components/EvidenceCard.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import styled, { css } from "styled-components";
33

44
import Identicon from "react-identicons";
55
import ReactMarkdown from "react-markdown";
6+
import { useParams } from "react-router-dom";
67

78
import { Card } from "@kleros/ui-components-library";
89

@@ -224,6 +225,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
224225
fileURI,
225226
}) => {
226227
const profileLink = `/profile/1/desc/all?address=${sender}`;
228+
const { id } = useParams();
227229

228230
const transactionExplorerLink = useMemo(() => {
229231
return getTxnExplorerLink(transactionHash ?? "");
@@ -258,7 +260,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
258260
</BottomLeftContent>
259261
{fileURI && fileURI !== "-" ? (
260262
<FileLinkContainer>
261-
<StyledInternalLink to={`/attachment/?title=${"Evidence File"}&url=${getIpfsUrl(fileURI)}`}>
263+
<StyledInternalLink to={`/attachment/?disputeId=${id}&title=${"Evidence File"}&url=${getIpfsUrl(fileURI)}`}>
262264
<AttachmentIcon />
263265
<AttachedFileText />
264266
</StyledInternalLink>

web/src/components/FileViewer/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ const StyledDocViewer = styled(DocViewer)`
2424
#pdf-controls {
2525
z-index: 3;
2626
}
27+
28+
[class*="--loading"] {
29+
color: ${({ theme }) => theme.secondaryText};
30+
}
2731
`;
2832

2933
/**

web/src/pages/AttachmentDisplay/Header.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22
import styled from "styled-components";
33

4-
import { useNavigate } from "react-router-dom";
4+
import { useNavigate, useSearchParams } from "react-router-dom";
55

66
import { Button } from "@kleros/ui-components-library";
77

@@ -66,9 +66,20 @@ const StyledButton = styled(Button)`
6666

6767
const Header: React.FC<{ title: string }> = ({ title }) => {
6868
const navigate = useNavigate();
69+
const [searchParams] = useSearchParams();
70+
const disputeId = searchParams.get("disputeId");
71+
const attachmentTitle = searchParams.get("title");
6972

7073
const handleReturn = () => {
71-
navigate(-1);
74+
if (attachmentTitle === "Evidence File") {
75+
navigate(`/cases/${disputeId}/evidence`);
76+
} else if (attachmentTitle === "Case Policy" || attachmentTitle === "Dispute Policy") {
77+
navigate(`/cases/${disputeId}/overview`);
78+
} else if (attachmentTitle === "Policy File") {
79+
navigate(`/resolver/policy`);
80+
} else {
81+
navigate("/");
82+
}
7283
};
7384

7485
return (

web/src/pages/Cases/CaseDetails/Timeline.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,10 @@ const AppealBanner: React.FC = () => {
8383
const { fundedChoices } = useFundingContext();
8484

8585
const text = useMemo(() => {
86-
if (loserSideCountdown)
87-
return `${secondsToDayHourMinute(loserSideCountdown)} left until losing options can be funded`;
86+
if (loserSideCountdown) return `${secondsToDayHourMinute(loserSideCountdown)} remaining to fund losing options`;
8887
// only show if loosing option was funded and winner needs funding, else no action is needed from user
8988
if (winnerSideCountdown && !isUndefined(fundedChoices) && fundedChoices.length > 0)
90-
return `${secondsToDayHourMinute(winnerSideCountdown)} left until winning option can be funded`;
89+
return `${secondsToDayHourMinute(winnerSideCountdown)} remaining to fund winning option`;
9190
return;
9291
}, [loserSideCountdown, winnerSideCountdown, fundedChoices]);
9392

0 commit comments

Comments
 (0)