kleros/kleros-v2

View on GitHub
contracts/src/arbitration/KlerosCoreNeo.sol

Summary

Maintainability
Test Coverage
// SPDX-License-Identifier: MIT

/// @custom:authors: [@unknownunknown1, @jaybuidl]
/// @custom:reviewers: []
/// @custom:auditors: []
/// @custom:bounties: []
/// @custom:deployments: []

pragma solidity 0.8.24;

import "./KlerosCoreBase.sol";
import {UUPSProxiable} from "../proxy/UUPSProxiable.sol";
import {Initializable} from "../proxy/Initializable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

/// @title KlerosCoreNeo
/// Core arbitrator contract for Kleros v2.
/// Note that this contract trusts the PNK token, the dispute kit and the sortition module contracts.
contract KlerosCoreNeo is KlerosCoreBase, UUPSProxiable, Initializable {
    // ************************************* //
    // *             Storage               * //
    // ************************************* //

    mapping(address => bool) public arbitrableWhitelist; // Arbitrable whitelist.
    IERC721 public jurorNft; // Eligible jurors NFT.

    // ************************************* //
    // *            Constructor            * //
    // ************************************* //

    /// @dev Constructor, initializing the implementation to reduce attack surface.
    constructor() {
        _disableInitializers();
    }

    /// @dev Initializer (constructor equivalent for upgradable contracts).
    /// @param _governor The governor's address.
    /// @param _guardian The guardian's address.
    /// @param _pinakion The address of the token contract.
    /// @param _jurorProsecutionModule The address of the juror prosecution module.
    /// @param _disputeKit The address of the default dispute kit.
    /// @param _hiddenVotes The `hiddenVotes` property value of the general court.
    /// @param _courtParameters Numeric parameters of General court (minStake, alpha, feeForJuror and jurorsForCourtJump respectively).
    /// @param _timesPerPeriod The `timesPerPeriod` property value of the general court.
    /// @param _sortitionExtraData The extra data for sortition module.
    /// @param _sortitionModuleAddress The sortition module responsible for sortition of the jurors.
    /// @param _jurorNft NFT contract to vet the jurors.
    function initialize(
        address _governor,
        address _guardian,
        IERC20 _pinakion,
        address _jurorProsecutionModule,
        IDisputeKit _disputeKit,
        bool _hiddenVotes,
        uint256[4] memory _courtParameters,
        uint256[4] memory _timesPerPeriod,
        bytes memory _sortitionExtraData,
        ISortitionModule _sortitionModuleAddress,
        IERC721 _jurorNft
    ) external reinitializer(2) {
        super._initialize(
            _governor,
            _guardian,
            _pinakion,
            _jurorProsecutionModule,
            _disputeKit,
            _hiddenVotes,
            _courtParameters,
            _timesPerPeriod,
            _sortitionExtraData,
            _sortitionModuleAddress
        );
        jurorNft = _jurorNft;
    }

    // ************************************* //
    // *             Governance            * //
    // ************************************* //

    /// @dev Access Control to perform implementation upgrades (UUPS Proxiable)
    ///      Only the governor can perform upgrades (`onlyByGovernor`)
    function _authorizeUpgrade(address) internal view override onlyByGovernor {
        // NOP
    }

    /// @dev Changes the `jurorNft` storage variable.
    /// @param _jurorNft The new value for the `jurorNft` storage variable.
    function changeJurorNft(IERC721 _jurorNft) external onlyByGovernor {
        jurorNft = _jurorNft;
    }

    /// @dev Adds or removes an arbitrable from whitelist.
    /// @param _arbitrable Arbitrable address.
    /// @param _allowed Whether add or remove permission.
    function changeArbitrableWhitelist(address _arbitrable, bool _allowed) external onlyByGovernor {
        arbitrableWhitelist[_arbitrable] = _allowed;
    }

    // ************************************* //
    // *         State Modifiers           * //
    // ************************************* //

    /// @dev Sets the caller's stake in a court.
    /// Note: Staking and unstaking is forbidden during pause.
    /// @param _courtID The ID of the court.
    /// @param _newStake The new stake.
    /// Note that the existing delayed stake will be nullified as non-relevant.
    function setStake(uint96 _courtID, uint256 _newStake) external override whenNotPaused {
        if (jurorNft.balanceOf(msg.sender) == 0) revert NotEligibleForStaking();
        super._setStake(msg.sender, _courtID, _newStake, false, OnError.Revert);
    }

    // ************************************* //
    // *            Internal               * //
    // ************************************* //

    function _createDispute(
        uint256 _numberOfChoices,
        bytes memory _extraData,
        IERC20 _feeToken,
        uint256 _feeAmount
    ) internal override returns (uint256 disputeID) {
        if (!arbitrableWhitelist[msg.sender]) revert ArbitrableNotWhitelisted();
        return super._createDispute(_numberOfChoices, _extraData, _feeToken, _feeAmount);
    }

    function _stakingFailed(OnError _onError, StakingResult _result) internal pure override {
        super._stakingFailed(_onError, _result);
        if (_result == StakingResult.CannotStakeMoreThanMaxStakePerJuror) revert StakingMoreThanMaxStakePerJuror();
        if (_result == StakingResult.CannotStakeMoreThanMaxTotalStaked) revert StakingMoreThanMaxTotalStaked();
    }

    // ************************************* //
    // *              Errors               * //
    // ************************************* //

    error NotEligibleForStaking();
    error StakingMoreThanMaxStakePerJuror();
    error StakingMoreThanMaxTotalStaked();
    error ArbitrableNotWhitelisted();
}