Skip to content
Merged
2 changes: 2 additions & 0 deletions contracts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The format is based on [Common Changelog](https://common-changelog.org/).
- **Breaking:** Rename the interface from `RNG` to `IRNG` ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- **Breaking:** Remove the `_block` parameter from `IRNG.requestRandomness()` and `IRNG.receiveRandomness()`, not needed for the primary VRF-based RNG ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- **Breaking:** Rename `governor` to `owner` in order to comply with the lightweight ownership standard [ERC-5313](https://eipsinsight.com/ercs/erc-5313) ([#2112](https://github.com/kleros/kleros-v2/issues/2112))
- **Breaking:** Add a new state variable `jumpDisputeKitID` to the `DisputeKitClassicBase` contract ([#2114](https://github.com/kleros/kleros-v2/issues/2114))
- Make the primary VRF-based RNG fall back to `BlockhashRNG` if the VRF request is not fulfilled within a timeout ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- Authenticate the calls to the RNGs to prevent 3rd parties from depleting the Chainlink VRF subscription funds ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- Use `block.timestamp` rather than `block.number` for `BlockhashRNG` for better reliability on Arbitrum as block production is sporadic depending on network conditions. ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
Expand All @@ -27,6 +28,7 @@ The format is based on [Common Changelog](https://common-changelog.org/).
### Added

- Allow the dispute kits to force an early court jump and to override the number of votes after an appeal (future-proofing) ([#2110](https://github.com/kleros/kleros-v2/issues/2110))
- Allow the dispute kits to specify which new dispute kit to use when a court jump occurs ([#2114](https://github.com/kleros/kleros-v2/issues/2114))

### Fixed

Expand Down
12 changes: 8 additions & 4 deletions contracts/deploy/00-home-chain-arbitration-neo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)

await deployUpgradable(deployments, "EvidenceModule", { from: deployer, args: [deployer], log: true });

const classicDisputeKitID = 1; // Classic DK
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassicNeo", {
from: deployer,
contract: "DisputeKitClassic",
args: [deployer, ZeroAddress, weth.target],
args: [deployer, ZeroAddress, weth.target, classicDisputeKitID],
log: true,
});

Expand Down Expand Up @@ -124,24 +125,27 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
// Extra dispute kits
const disputeKitShutter = await deployUpgradable(deployments, "DisputeKitShutter", {
from: deployer,
args: [deployer, core.target, weth.target],
args: [deployer, core.target, weth.target, classicDisputeKitID],
log: true,
});
await core.addNewDisputeKit(disputeKitShutter.address);
const disputeKitShutterID = (await core.getDisputeKitsLength()) - 1n;

const disputeKitGated = await deployUpgradable(deployments, "DisputeKitGated", {
from: deployer,
args: [deployer, core.target, weth.target],
args: [deployer, core.target, weth.target, classicDisputeKitID],
log: true,
});
await core.addNewDisputeKit(disputeKitGated.address);
const disputeKitGatedID = (await core.getDisputeKitsLength()) - 1n;

const disputeKitGatedShutter = await deployUpgradable(deployments, "DisputeKitGatedShutter", {
from: deployer,
args: [deployer, core.target, weth.target],
args: [deployer, core.target, weth.target, disputeKitShutterID], // Does not jump to DKClassic
log: true,
});
await core.addNewDisputeKit(disputeKitGatedShutter.address);
const disputeKitGatedShutterID = (await core.getDisputeKitsLength()) - 1n;

// Snapshot proxy
await deploy("KlerosCoreSnapshotProxy", {
Expand Down
18 changes: 11 additions & 7 deletions contracts/deploy/00-home-chain-arbitration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
log: true,
});

const classicDisputeKitID = 1; // Classic DK
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassic", {
from: deployer,
args: [deployer, ZeroAddress, weth.target],
args: [deployer, ZeroAddress, weth.target, classicDisputeKitID],
log: true,
});

Expand Down Expand Up @@ -105,27 +106,30 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
// Extra dispute kits
const disputeKitShutter = await deployUpgradable(deployments, "DisputeKitShutter", {
from: deployer,
args: [deployer, core.target, weth.target],
args: [deployer, core.target, weth.target, classicDisputeKitID],
log: true,
});
await core.addNewDisputeKit(disputeKitShutter.address);
await core.enableDisputeKits(Courts.GENERAL, [2], true); // enable disputeKitShutter on the General Court
const disputeKitShutterID = (await core.getDisputeKitsLength()) - 1n;
await core.enableDisputeKits(Courts.GENERAL, [disputeKitShutterID], true); // enable disputeKitShutter on the General Court

const disputeKitGated = await deployUpgradable(deployments, "DisputeKitGated", {
from: deployer,
args: [deployer, core.target, weth.target],
args: [deployer, core.target, weth.target, classicDisputeKitID],
log: true,
});
await core.addNewDisputeKit(disputeKitGated.address);
await core.enableDisputeKits(Courts.GENERAL, [3], true); // enable disputeKitGated on the General Court
const disputeKitGatedID = (await core.getDisputeKitsLength()) - 1n;
await core.enableDisputeKits(Courts.GENERAL, [disputeKitGatedID], true); // enable disputeKitGated on the General Court

const disputeKitGatedShutter = await deployUpgradable(deployments, "DisputeKitGatedShutter", {
from: deployer,
args: [deployer, core.target, weth.target],
args: [deployer, core.target, weth.target, disputeKitShutterID], // Does not jump to DKClassic
log: true,
});
await core.addNewDisputeKit(disputeKitGatedShutter.address);
await core.enableDisputeKits(Courts.GENERAL, [4], true); // enable disputeKitGatedShutter on the General Court
const disputeKitGatedShutterID = (await core.getDisputeKitsLength()) - 1n;
await core.enableDisputeKits(Courts.GENERAL, [disputeKitGatedShutterID], true); // enable disputeKitGatedShutter on the General Court

// Snapshot proxy
await deploy("KlerosCoreSnapshotProxy", {
Expand Down
8 changes: 6 additions & 2 deletions contracts/src/arbitration/KlerosCoreBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1079,8 +1079,12 @@ abstract contract KlerosCoreBase is IArbitratorV2, Initializable, UUPSProxiable
courtJump = true;

if (!courts[newCourtID].supportedDisputeKits[newDisputeKitID]) {
// Switch to classic dispute kit if parent court doesn't support the current one.
newDisputeKitID = DISPUTE_KIT_CLASSIC;
// The current Dispute Kit is not compatible with the new court, jump to another Dispute Kit.
newDisputeKitID = disputeKits[_round.disputeKitID].getJumpDisputeKitID();
if (newDisputeKitID == NULL_DISPUTE_KIT || !courts[newCourtID].supportedDisputeKits[newDisputeKitID]) {
// The new Dispute Kit is not defined or still not compatible, fall back to `DisputeKitClassic` which is always supported.
newDisputeKitID = DISPUTE_KIT_CLASSIC;
}
disputeKitJump = true;
}
}
Expand Down
16 changes: 11 additions & 5 deletions contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {DisputeKitClassicBase, KlerosCore} from "./DisputeKitClassicBase.sol";
/// - an incentive system: equal split between coherent votes,
/// - an appeal system: fund 2 choices only, vote on any choice.
contract DisputeKitClassic is DisputeKitClassicBase {
string public constant override version = "0.12.0";
string public constant override version = "0.13.0";

// ************************************* //
// * Constructor * //
Expand All @@ -26,12 +26,18 @@ contract DisputeKitClassic is DisputeKitClassicBase {
/// @param _owner The owner's address.
/// @param _core The KlerosCore arbitrator.
/// @param _wNative The wrapped native token address, typically wETH.
function initialize(address _owner, KlerosCore _core, address _wNative) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative);
/// @param _jumpDisputeKitID The ID of the dispute kit to switch to after the court jump.
function initialize(
address _owner,
KlerosCore _core,
address _wNative,
uint256 _jumpDisputeKitID
) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative, _jumpDisputeKitID);
}

function reinitialize(address _wNative) external reinitializer(9) {
wNative = _wNative;
function reinitialize(uint256 _jumpDisputeKitID) external reinitializer(10) {
jumpDisputeKitID = _jumpDisputeKitID;
}

// ************************ //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {KlerosCore, KlerosCoreBase, IDisputeKit, ISortitionModule} from "../Kler
import {Initializable} from "../../proxy/Initializable.sol";
import {UUPSProxiable} from "../../proxy/UUPSProxiable.sol";
import {SafeSend} from "../../libraries/SafeSend.sol";
import {ONE_BASIS_POINT} from "../../libraries/Constants.sol";
import {ONE_BASIS_POINT, DISPUTE_KIT_CLASSIC} from "../../libraries/Constants.sol";

/// @title DisputeKitClassicBase
/// Abstract Dispute kit classic implementation of the Kleros v1 features including:
Expand Down Expand Up @@ -68,6 +68,7 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
public alreadyDrawn; // True if the address has already been drawn, false by default. To be added to the Round struct when fully redeploying rather than upgrading.
mapping(uint256 coreDisputeID => bool) public coreDisputeIDToActive; // True if this dispute kit is active for this core dispute ID.
address public wNative; // The wrapped native token for safeSend().
uint256 public jumpDisputeKitID; // The ID of the dispute kit in Kleros Core disputeKits array that the dispute should switch to after the court jump, in case the new court doesn't support this dispute kit.

// ************************************* //
// * Events * //
Expand Down Expand Up @@ -147,14 +148,17 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
/// @param _owner The owner's address.
/// @param _core The KlerosCore arbitrator.
/// @param _wNative The wrapped native token address, typically wETH.
/// @param _jumpDisputeKitID The ID of the dispute kit to switch to after the court jump.
function __DisputeKitClassicBase_initialize(
address _owner,
KlerosCore _core,
address _wNative
address _wNative,
uint256 _jumpDisputeKitID
) internal onlyInitializing {
owner = _owner;
core = _core;
wNative = _wNative;
jumpDisputeKitID = _jumpDisputeKitID;
}

// ************************ //
Expand Down Expand Up @@ -182,6 +186,12 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
core = KlerosCore(_core);
}

/// @dev Changes the dispute kit ID used for the jump.
/// @param _jumpDisputeKitID The new value for the `jumpDisputeKitID` storage variable.
function changeJumpDisputeKitID(uint256 _jumpDisputeKitID) external onlyByOwner {
jumpDisputeKitID = _jumpDisputeKitID;
}

// ************************************* //
// * State Modifiers * //
// ************************************* //
Expand Down Expand Up @@ -639,6 +649,13 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
return (_currentNbVotes * 2) + 1;
}

/// @dev Returns the dispute kid ID be used after court jump by Kleros Core.
/// @return The ID of the dispute kit in Kleros Core disputeKits array.
function getJumpDisputeKitID() external view override returns (uint256) {
// Fall back to classic DK in case the jump ID is not defined.
return jumpDisputeKitID == 0 ? DISPUTE_KIT_CLASSIC : jumpDisputeKitID;
}

/// @dev Returns true if the specified voter was active in this round.
/// @param _coreDisputeID The ID of the dispute in Kleros Core, not in the Dispute Kit.
/// @param _coreRoundID The ID of the round in Kleros Core, not in the Dispute Kit.
Expand Down
16 changes: 11 additions & 5 deletions contracts/src/arbitration/dispute-kits/DisputeKitGated.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface IBalanceHolderERC1155 {
/// - an incentive system: equal split between coherent votes,
/// - an appeal system: fund 2 choices only, vote on any choice.
contract DisputeKitGated is DisputeKitClassicBase {
string public constant override version = "0.12.0";
string public constant override version = "0.13.0";

// ************************************* //
// * Constructor * //
Expand All @@ -42,12 +42,18 @@ contract DisputeKitGated is DisputeKitClassicBase {
/// @param _owner The owner's address.
/// @param _core The KlerosCore arbitrator.
/// @param _wNative The wrapped native token address, typically wETH.
function initialize(address _owner, KlerosCore _core, address _wNative) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative);
/// @param _jumpDisputeKitID The ID of the dispute kit to switch to after the court jump.
function initialize(
address _owner,
KlerosCore _core,
address _wNative,
uint256 _jumpDisputeKitID
) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative, _jumpDisputeKitID);
}

function reinitialize(address _wNative) external reinitializer(9) {
wNative = _wNative;
function reinitialize(uint256 _jumpDisputeKitID) external reinitializer(10) {
jumpDisputeKitID = _jumpDisputeKitID;
}

// ************************ //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ interface IBalanceHolderERC1155 {
/// - an incentive system: equal split between coherent votes,
/// - an appeal system: fund 2 choices only, vote on any choice.
contract DisputeKitGatedShutter is DisputeKitClassicBase {
string public constant override version = "0.12.0";
string public constant override version = "0.13.0";

// ************************************* //
// * Events * //
Expand Down Expand Up @@ -61,12 +61,18 @@ contract DisputeKitGatedShutter is DisputeKitClassicBase {
/// @param _owner The owner's address.
/// @param _core The KlerosCore arbitrator.
/// @param _wNative The wrapped native token address, typically wETH.
function initialize(address _owner, KlerosCore _core, address _wNative) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative);
/// @param _jumpDisputeKitID The ID of the dispute kit to switch to after the court jump.
function initialize(
address _owner,
KlerosCore _core,
address _wNative,
uint256 _jumpDisputeKitID
) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative, _jumpDisputeKitID);
}

function reinitialize(address _wNative) external reinitializer(9) {
wNative = _wNative;
function reinitialize(uint256 _jumpDisputeKitID) external reinitializer(10) {
jumpDisputeKitID = _jumpDisputeKitID;
}

// ************************ //
Expand Down
16 changes: 11 additions & 5 deletions contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {DisputeKitClassicBase, KlerosCore} from "./DisputeKitClassicBase.sol";
/// - an incentive system: equal split between coherent votes,
/// - an appeal system: fund 2 choices only, vote on any choice.
contract DisputeKitShutter is DisputeKitClassicBase {
string public constant override version = "0.12.0";
string public constant override version = "0.13.0";

// ************************************* //
// * Events * //
Expand Down Expand Up @@ -45,12 +45,18 @@ contract DisputeKitShutter is DisputeKitClassicBase {
/// @param _owner The owner's address.
/// @param _core The KlerosCore arbitrator.
/// @param _wNative The wrapped native token address, typically wETH.
function initialize(address _owner, KlerosCore _core, address _wNative) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative);
/// @param _jumpDisputeKitID The ID of the dispute kit to switch to after the court jump.
function initialize(
address _owner,
KlerosCore _core,
address _wNative,
uint256 _jumpDisputeKitID
) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative, _jumpDisputeKitID);
}

function reinitialize(address _wNative) external reinitializer(9) {
wNative = _wNative;
function reinitialize(uint256 _jumpDisputeKitID) external reinitializer(10) {
jumpDisputeKitID = _jumpDisputeKitID;
}

// ************************ //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface IProofOfHumanity {
/// - an incentive system: equal split between coherent votes,
/// - an appeal system: fund 2 choices only, vote on any choice.
contract DisputeKitSybilResistant is DisputeKitClassicBase {
string public constant override version = "0.12.0";
string public constant override version = "0.13.0";

// ************************************* //
// * Storage * //
Expand All @@ -40,13 +40,15 @@ contract DisputeKitSybilResistant is DisputeKitClassicBase {
/// @param _core The KlerosCore arbitrator.
/// @param _poh The Proof of Humanity registry.
/// @param _wNative The wrapped native token address, typically wETH.
/// @param _jumpDisputeKitID The ID of the dispute kit to switch to after the court jump.
function initialize(
address _owner,
KlerosCore _core,
IProofOfHumanity _poh,
address _wNative
address _wNative,
uint256 _jumpDisputeKitID
) external reinitializer(1) {
__DisputeKitClassicBase_initialize(_owner, _core, _wNative);
__DisputeKitClassicBase_initialize(_owner, _core, _wNative, _jumpDisputeKitID);
poh = _poh;
singleDrawPerJuror = true;
}
Expand Down
4 changes: 4 additions & 0 deletions contracts/src/arbitration/interfaces/IDisputeKit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ interface IDisputeKit {
uint256 _currentNbVotes
) external view returns (uint256); // TODO: remove previousDisputeKit

/// @dev Returns the dispute kid ID be used after court jump by Kleros Core.
/// @return The ID of the dispute kit in Kleros Core disputeKits array.
function getJumpDisputeKitID() external view returns (uint256);

/// @dev Returns true if the specified voter was active in this round.
/// @param _coreDisputeID The ID of the dispute in Kleros Core, not in the Dispute Kit.
/// @param _coreRoundID The ID of the round in Kleros Core, not in the Dispute Kit.
Expand Down
Loading