Skip to content

Commit b22899c

Browse files
authored
Merge pull request #2187 from kleros/feat/next-round-settings-in-dk
Increased Court and DK jump logic flexibility
2 parents c40c12c + 6d76559 commit b22899c

19 files changed

+1880
-194
lines changed

contracts/deploy/00-home-chain-arbitration-mainnet.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
3131
const classicDisputeKitID = 1; // Classic DK
3232
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassic", {
3333
from: deployer,
34-
args: [deployer, ZeroAddress, weth.target, classicDisputeKitID],
34+
args: [deployer, ZeroAddress, weth.target],
3535
log: true,
3636
});
3737

@@ -125,23 +125,23 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
125125
// Extra dispute kits
126126
const disputeKitShutter = await deployUpgradable(deployments, "DisputeKitShutter", {
127127
from: deployer,
128-
args: [deployer, core.target, weth.target, classicDisputeKitID],
128+
args: [deployer, core.target, weth.target],
129129
log: true,
130130
});
131131
await core.addNewDisputeKit(disputeKitShutter.address);
132132
const disputeKitShutterID = (await core.getDisputeKitsLength()) - 1n;
133133

134134
const disputeKitGated = await deployUpgradable(deployments, "DisputeKitGated", {
135135
from: deployer,
136-
args: [deployer, core.target, weth.target, classicDisputeKitID],
136+
args: [deployer, core.target, weth.target],
137137
log: true,
138138
});
139139
await core.addNewDisputeKit(disputeKitGated.address);
140140
const disputeKitGatedID = (await core.getDisputeKitsLength()) - 1n;
141141

142142
const disputeKitGatedShutter = await deployUpgradable(deployments, "DisputeKitGatedShutter", {
143143
from: deployer,
144-
args: [deployer, core.target, weth.target, disputeKitShutterID], // Does not jump to DKClassic
144+
args: [deployer, core.target, weth.target], // TODO: jump to a Shutter DK instead of a Classic one?
145145
log: true,
146146
});
147147
await core.addNewDisputeKit(disputeKitGatedShutter.address);

contracts/deploy/00-home-chain-arbitration-university.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
3434
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassicUniversity", {
3535
from: deployer,
3636
contract: "DisputeKitClassic",
37-
args: [deployer, ZeroAddress, weth.target, 1],
37+
args: [deployer, ZeroAddress, weth.target],
3838
log: true,
3939
});
4040

contracts/deploy/00-home-chain-arbitration.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
3737
const classicDisputeKitID = 1; // Classic DK
3838
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassic", {
3939
from: deployer,
40-
args: [deployer, ZeroAddress, weth.target, classicDisputeKitID],
40+
args: [deployer, ZeroAddress, weth.target],
4141
log: true,
4242
});
4343

@@ -115,7 +115,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
115115
// Extra dispute kits
116116
const disputeKitShutter = await deployUpgradable(deployments, "DisputeKitShutter", {
117117
from: deployer,
118-
args: [deployer, core.target, weth.target, classicDisputeKitID],
118+
args: [deployer, core.target, weth.target],
119119
log: true,
120120
});
121121
await core.addNewDisputeKit(disputeKitShutter.address);
@@ -124,7 +124,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
124124

125125
const disputeKitGated = await deployUpgradable(deployments, "DisputeKitGated", {
126126
from: deployer,
127-
args: [deployer, core.target, weth.target, classicDisputeKitID],
127+
args: [deployer, core.target, weth.target],
128128
log: true,
129129
});
130130
await core.addNewDisputeKit(disputeKitGated.address);
@@ -133,7 +133,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
133133

134134
const disputeKitGatedShutter = await deployUpgradable(deployments, "DisputeKitGatedShutter", {
135135
from: deployer,
136-
args: [deployer, core.target, weth.target, disputeKitShutterID], // Does not jump to DKClassic
136+
args: [deployer, core.target, weth.target], // TODO: jump to a Shutter DK instead of a Classic one?
137137
log: true,
138138
});
139139
await core.addNewDisputeKit(disputeKitGatedShutter.address);

contracts/hardhat.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const config: HardhatUserConfig = {
3232
viaIR: process.env.VIA_IR !== "false", // Defaults to true
3333
optimizer: {
3434
enabled: true,
35-
runs: 800, // Constrained by the size of the KlerosCore contract
35+
runs: 1000, // Constrained by the size of the KlerosCore contract
3636
},
3737
outputSelection: {
3838
"*": {

contracts/src/arbitration/KlerosCore.sol

Lines changed: 75 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -785,13 +785,13 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
785785
Round storage extraRound = dispute.rounds.push();
786786
uint256 extraRoundID = dispute.rounds.length - 1;
787787

788-
(uint96 newCourtID, uint256 newDisputeKitID, bool courtJump, ) = _getCourtAndDisputeKitJumps(
788+
(uint96 newCourtID, uint256 newDisputeKitID, ) = _getCompatibleNextRoundSettings(
789789
dispute,
790790
round,
791791
courts[dispute.courtID],
792792
_disputeID
793793
);
794-
if (courtJump) {
794+
if (newCourtID != dispute.courtID) {
795795
emit CourtJump(_disputeID, extraRoundID, dispute.courtID, newCourtID);
796796
}
797797

@@ -1080,31 +1080,26 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
10801080

10811081
/// @notice Gets the cost of appealing a specified dispute.
10821082
/// @param _disputeID The ID of the dispute.
1083-
/// @return cost The appeal cost.
1084-
function appealCost(uint256 _disputeID) public view returns (uint256 cost) {
1083+
/// @return The appeal cost.
1084+
function appealCost(uint256 _disputeID) public view returns (uint256) {
10851085
Dispute storage dispute = disputes[_disputeID];
10861086
Round storage round = dispute.rounds[dispute.rounds.length - 1];
10871087
Court storage court = courts[dispute.courtID];
1088-
1089-
(, uint256 newDisputeKitID, bool courtJump, ) = _getCourtAndDisputeKitJumps(dispute, round, court, _disputeID);
1090-
1091-
uint256 nbVotesAfterAppeal = disputeKits[newDisputeKitID].getNbVotesAfterAppeal(
1092-
disputeKits[round.disputeKitID],
1093-
round.nbVotes
1088+
(uint96 newCourtID, , uint256 nbVotesAfterAppeal) = _getCompatibleNextRoundSettings(
1089+
dispute,
1090+
round,
1091+
court,
1092+
_disputeID
10941093
);
1095-
1096-
if (courtJump) {
1097-
// Jump to parent court.
1098-
if (dispute.courtID == GENERAL_COURT) {
1099-
// TODO: Handle the forking when appealed in General court.
1100-
cost = NON_PAYABLE_AMOUNT; // Get the cost of the parent court.
1101-
} else {
1102-
cost = courts[court.parent].feeForJuror * nbVotesAfterAppeal;
1103-
}
1104-
} else {
1105-
// Stay in current court.
1106-
cost = court.feeForJuror * nbVotesAfterAppeal;
1094+
if (newCourtID == dispute.courtID) {
1095+
// No court jump
1096+
return court.feeForJuror * nbVotesAfterAppeal;
1097+
}
1098+
if (dispute.courtID != GENERAL_COURT && newCourtID != FORKING_COURT) {
1099+
// Court jump but not to the Forking court
1100+
return courts[newCourtID].feeForJuror * nbVotesAfterAppeal;
11071101
}
1102+
return NON_PAYABLE_AMOUNT; // Jumping to the Forking Court is not supported yet.
11081103
}
11091104

11101105
/// @notice Gets the start and the end of a specified dispute's current appeal period.
@@ -1180,20 +1175,38 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
11801175
return dispute.rounds[dispute.rounds.length - 1].nbVotes;
11811176
}
11821177

1183-
/// @notice Returns true if the dispute kit will be switched to a parent DK.
1184-
/// @param _disputeID The ID of the dispute.
1185-
/// @return Whether DK will be switched or not.
1186-
function isDisputeKitJumping(uint256 _disputeID) external view returns (bool) {
1178+
/// @notice Checks whether a dispute will jump to new court/DK and enforces a compatibility check.
1179+
/// @param _disputeID Dispute ID.
1180+
/// @return newCourtID Court ID after jump.
1181+
/// @return newDisputeKitID Dispute kit ID after jump.
1182+
/// @return newRoundNbVotes The number of votes in the new round.
1183+
/// @return courtJump Whether the dispute jumps to a new court or not.
1184+
/// @return disputeKitJump Whether the dispute jumps to a new dispute kit or not.
1185+
function getCourtAndDisputeKitJumps(
1186+
uint256 _disputeID
1187+
)
1188+
external
1189+
view
1190+
returns (
1191+
uint96 newCourtID,
1192+
uint256 newDisputeKitID,
1193+
uint256 newRoundNbVotes,
1194+
bool courtJump,
1195+
bool disputeKitJump
1196+
)
1197+
{
11871198
Dispute storage dispute = disputes[_disputeID];
11881199
Round storage round = dispute.rounds[dispute.rounds.length - 1];
11891200
Court storage court = courts[dispute.courtID];
11901201

1191-
if (!_isCourtJumping(round, court, _disputeID)) {
1192-
return false;
1193-
}
1194-
1195-
// Jump if the parent court doesn't support the current DK.
1196-
return !courts[court.parent].supportedDisputeKits[round.disputeKitID];
1202+
(newCourtID, newDisputeKitID, newRoundNbVotes) = _getCompatibleNextRoundSettings(
1203+
dispute,
1204+
round,
1205+
court,
1206+
_disputeID
1207+
);
1208+
courtJump = (newCourtID != dispute.courtID);
1209+
disputeKitJump = (newDisputeKitID != round.disputeKitID);
11971210
}
11981211

11991212
/// @notice Returns the length of disputeKits array.
@@ -1214,51 +1227,47 @@ contract KlerosCore is IArbitratorV2, Initializable, UUPSProxiable {
12141227
// * Internal * //
12151228
// ************************************* //
12161229

1217-
/// @notice Returns true if the round is jumping to a parent court.
1218-
/// @param _round The round to check.
1219-
/// @param _court The court to check.
1220-
/// @return Whether the round is jumping to a parent court or not.
1221-
function _isCourtJumping(
1222-
Round storage _round,
1223-
Court storage _court,
1224-
uint256 _disputeID
1225-
) internal view returns (bool) {
1226-
return
1227-
disputeKits[_round.disputeKitID].earlyCourtJump(_disputeID) || _round.nbVotes >= _court.jurorsForCourtJump;
1228-
}
1229-
1230-
/// @notice Checks whether a dispute will jump to new court/DK, and returns new court and DK.
1230+
/// @notice Get the next round settings for a given dispute
1231+
/// @dev Enforces a compatibility check between the next round's court and dispute kit.
12311232
/// @param _dispute Dispute data.
12321233
/// @param _round Round ID.
12331234
/// @param _court Current court ID.
12341235
/// @param _disputeID Dispute ID.
12351236
/// @return newCourtID Court ID after jump.
12361237
/// @return newDisputeKitID Dispute kit ID after jump.
1237-
/// @return courtJump Whether the dispute jumps to a new court or not.
1238-
/// @return disputeKitJump Whether the dispute jumps to a new dispute kit or not.
1239-
function _getCourtAndDisputeKitJumps(
1238+
/// @return newRoundNbVotes The number of votes in the new round.
1239+
function _getCompatibleNextRoundSettings(
12401240
Dispute storage _dispute,
12411241
Round storage _round,
12421242
Court storage _court,
12431243
uint256 _disputeID
1244-
) internal view returns (uint96 newCourtID, uint256 newDisputeKitID, bool courtJump, bool disputeKitJump) {
1245-
newCourtID = _dispute.courtID;
1246-
newDisputeKitID = _round.disputeKitID;
1247-
1248-
if (!_isCourtJumping(_round, _court, _disputeID)) return (newCourtID, newDisputeKitID, false, false);
1249-
1250-
// Jump to parent court.
1251-
newCourtID = courts[newCourtID].parent;
1252-
courtJump = true;
1253-
1244+
) internal view returns (uint96 newCourtID, uint256 newDisputeKitID, uint256 newRoundNbVotes) {
1245+
uint256 disputeKitID = _round.disputeKitID;
1246+
(newCourtID, newDisputeKitID, newRoundNbVotes) = disputeKits[disputeKitID].getNextRoundSettings(
1247+
_disputeID,
1248+
_dispute.courtID,
1249+
_court.parent,
1250+
_court.jurorsForCourtJump,
1251+
disputeKitID,
1252+
_round.nbVotes
1253+
);
1254+
if (
1255+
newCourtID == FORKING_COURT ||
1256+
newCourtID >= courts.length ||
1257+
newDisputeKitID == NULL_DISPUTE_KIT ||
1258+
newDisputeKitID >= disputeKits.length ||
1259+
newRoundNbVotes == 0
1260+
) {
1261+
// Falling back to the current court and dispute kit with default nbVotes.
1262+
newCourtID = _dispute.courtID;
1263+
newDisputeKitID = disputeKitID;
1264+
newRoundNbVotes = (_round.nbVotes * 2) + 1;
1265+
}
1266+
// Ensure compatibility between the next round's court and dispute kit.
12541267
if (!courts[newCourtID].supportedDisputeKits[newDisputeKitID]) {
1255-
// The current Dispute Kit is not compatible with the new court, jump to another Dispute Kit.
1256-
newDisputeKitID = disputeKits[_round.disputeKitID].getJumpDisputeKitID();
1257-
if (newDisputeKitID == NULL_DISPUTE_KIT || !courts[newCourtID].supportedDisputeKits[newDisputeKitID]) {
1258-
// The new Dispute Kit is not defined or still not compatible, fall back to `DisputeKitClassic` which is always supported.
1259-
newDisputeKitID = DISPUTE_KIT_CLASSIC;
1260-
}
1261-
disputeKitJump = true;
1268+
// Falling back to `DisputeKitClassic` which is always supported and with default nbVotes.
1269+
newDisputeKitID = DISPUTE_KIT_CLASSIC;
1270+
newRoundNbVotes = (_round.nbVotes * 2) + 1;
12621271
}
12631272
}
12641273

contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,8 @@ contract DisputeKitClassic is DisputeKitClassicBase {
2626
/// @param _owner The owner's address.
2727
/// @param _core The KlerosCore arbitrator.
2828
/// @param _wNative The wrapped native token address, typically wETH.
29-
/// @param _jumpDisputeKitID The ID of the dispute kit to switch to after the court jump.
30-
function initialize(
31-
address _owner,
32-
KlerosCore _core,
33-
address _wNative,
34-
uint256 _jumpDisputeKitID
35-
) external initializer {
36-
__DisputeKitClassicBase_initialize(_owner, _core, _wNative, _jumpDisputeKitID);
29+
function initialize(address _owner, KlerosCore _core, address _wNative) external initializer {
30+
__DisputeKitClassicBase_initialize(_owner, _core, _wNative);
3731
}
3832

3933
// ************************ //

0 commit comments

Comments
 (0)