Skip to content

Commit

Permalink
better interface for delay information (#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
josojo authored Feb 6, 2024
1 parent b3cb78a commit debb501
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 164 deletions.
41 changes: 6 additions & 35 deletions contracts/AdjudicationFramework/MinimalAdjudicationFramework.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,16 @@ pragma solidity ^0.8.20;
import {IRealityETH} from "./../lib/reality-eth/interfaces/IRealityETH.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IL2ForkArbitrator} from "../interfaces/IL2ForkArbitrator.sol";
import {IMinimalAdjudicationFramework} from "./interface/IMinimalAdjudicationFramework.sol";
/*
Minimal Adjudication framework every framework should implement.
Contains an enumerableSet of Arbitrators.
Arbitrators can be removed or added by providing a realityETH question with forking as a final arbitration.
Also, arbitrators who are challenged by a removal question, can be temporarily frozen, if a sufficient bond is provided.
*/

contract MinimalAdjudicationFramework {
contract MinimalAdjudicationFramework is IMinimalAdjudicationFramework {
using EnumerableSet for EnumerableSet.AddressSet;
/// @dev Error thrown with illegal modification of arbitrators
error NoArbitratorsToModify();
/// @dev Error thrown when a proposition already exists
error PropositionAlreadyExists();
/// @dev Error thrown when a proposition is not found
error PropositionNotFound();
/// @dev Error thrown when a proposition is not found
error ArbitratorNotInAllowList();
/// @dev Error thrown when an arbitrator is already frozen
error ArbitratorAlreadyFrozen();
/// @dev Error thrown when received messages from realityEth is not yes
error AnswerNotYes();
/// @dev Error thrown when received messages from realityEth is yes, but expected to be no
error PropositionNotFailed();
/// @dev Error thrown when bond is too low to freeze an arbitrator
error BondTooLowToFreeze();
/// @dev Error thrown when proposition is not accepted
error PropositionNotAccepted();

// Question delimiter for arbitrator modification questions for reality.eth
string internal constant _QUESTION_DELIM = "\u241f";
Expand Down Expand Up @@ -64,12 +46,6 @@ contract MinimalAdjudicationFramework {
// Contract used for requesting a fork in the L1 chain in remove propositions
address public forkArbitrator;

// Reality.eth questions for propositions we may be asked to rule on
struct ArbitratorProposition {
address arbitratorToRemove;
address arbitratorToAdd;
bool isFrozen;
}
mapping(bytes32 => ArbitratorProposition) public propositions;

// Keep a count of active propositions that freeze an arbitrator.
Expand Down Expand Up @@ -176,15 +152,6 @@ contract MinimalAdjudicationFramework {
0,
REALITY_ETH_BOND_ARBITRATOR_REMOVE
);
IL2ForkArbitrator(forkArbitrator).storeInformation(
templateId,
uint32(block.timestamp),
question,
REALITY_ETH_TIMEOUT,
REALITY_ETH_BOND_ARBITRATOR_REMOVE,
0,
forkActivationDelay
);
if (
propositions[questionId].arbitratorToAdd != address(0) ||
propositions[questionId].arbitratorToRemove != address(0)
Expand Down Expand Up @@ -314,4 +281,8 @@ contract MinimalAdjudicationFramework {
) external view returns (bool) {
return propositions[questionId].isFrozen;
}

function getInvestigationDelay() external view returns (uint256) {
return forkActivationDelay;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.20;

/* solhint-disable quotes */
/* solhint-disable not-rely-on-time */

import {IMinimalAdjudicationFrameworkErrors} from "./IMinimalAdjudicationFrameworkErrors.sol";

interface IMinimalAdjudicationFramework is IMinimalAdjudicationFrameworkErrors {
// Reality.eth questions for propositions we may be asked to rule on
struct ArbitratorProposition {
address arbitratorToRemove;
address arbitratorToAdd;
bool isFrozen;
}

function requestModificationOfArbitrators(
address arbitratorToRemove,
address arbitratorToAdd
) external returns (bytes32);

function executeModificationArbitratorFromAllowList(
bytes32 questionId
) external;

// When an arbitrator is listed for removal, they can be frozen given a sufficient bond
function freezeArbitrator(
bytes32 questionId,
bytes32[] memory historyHashes,
address[] memory addrs,
uint256[] memory bonds,
bytes32[] memory answers
) external;

function clearFailedProposition(bytes32 questionId) external;

// Getter functions only below here

function realitio() external view returns (address);

function isArbitrator(address arbitrator) external view returns (bool);

function isArbitratorPropositionFrozen(
bytes32 questionId
) external view returns (bool);

function getInvestigationDelay() external view returns (uint256);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.20;

interface IMinimalAdjudicationFrameworkErrors {
/// @dev Error thrown with illegal modification of arbitrators
error NoArbitratorsToModify();
/// @dev Error thrown when a proposition already exists
error PropositionAlreadyExists();
/// @dev Error thrown when a proposition is not found
error PropositionNotFound();
/// @dev Error thrown when a proposition is not found
error ArbitratorNotInAllowList();
/// @dev Error thrown when an arbitrator is already frozen
error ArbitratorAlreadyFrozen();
/// @dev Error thrown when received messages from realityEth is not yes
error AnswerNotYes();
/// @dev Error thrown when received messages from realityEth is yes, but expected to be no
error PropositionNotFailed();
/// @dev Error thrown when bond is too low to freeze an arbitrator
error BondTooLowToFreeze();
/// @dev Error thrown when proposition is not accepted
error PropositionNotAccepted();
}
44 changes: 11 additions & 33 deletions contracts/L2ForkArbitrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {CalculateMoneyBoxAddress} from "./lib/CalculateMoneyBoxAddress.sol";

import {IPolygonZkEVMBridge} from "@RealityETH/zkevm-contracts/contracts/interfaces/IPolygonZkEVMBridge.sol";
import {IL2ForkArbitrator} from "./interfaces/IL2ForkArbitrator.sol";
import {IMinimalAdjudicationFramework} from "./AdjudicationFramework/interface/IMinimalAdjudicationFramework.sol";
/*
This contract is the arbitrator used by governance propositions for AdjudicationFramework contracts.
It charges a dispute fee of 5% of total supply [TODO], which it forwards to L1 when requesting a fork.
Expand Down Expand Up @@ -39,15 +40,6 @@ contract L2ForkArbitrator is IL2ForkArbitrator {
uint256 timeOfRequest;
}

enum ArbitrationStatus {
NONE,
SOME
}
struct ArbitrationData {
ArbitrationStatus status;
uint256 delay; // Delay in seconds before the fork is activated
}

event LogRequestArbitration(
bytes32 indexed question_id,
uint256 fee_paid,
Expand All @@ -58,9 +50,6 @@ contract L2ForkArbitrator is IL2ForkArbitrator {
// stores data on the arbitration process
// questionId => ArbitrationRequest
mapping(bytes32 => ArbitrationRequest) public arbitrationRequests;
// stores data on the arbitration itself
// questionId => ArbitrationData
mapping(bytes32 => ArbitrationData) public arbitrationData;

mapping(address => uint256) public refundsDue;

Expand Down Expand Up @@ -117,25 +106,21 @@ contract L2ForkArbitrator is IL2ForkArbitrator {
maxPrevious
);
emit LogRequestArbitration(questionId, msg.value, msg.sender, 0);
if (
!isForkInProgress &&
arbitrationData[questionId].delay == 0 &&
arbitrationData[questionId].status == ArbitrationStatus.SOME
) {
requestActivateFork(questionId);
}
return true;
}

/// @inheritdoc IL2ForkArbitrator
function storeInformation(
// @note This function requires all the information from the original question,
// to verify the address of the adjudication framework that initially asked the question
// With the address of the adjudication framework, we can get the investigation delay
function requestActivateFork(
uint256 templateId,
uint32 openingTs,
string calldata question,
uint32 timeout,
uint256 minBond,
uint256 nonce,
uint256 delay
address adjudicationFramework
) public {
bytes32 contentHash = keccak256(
abi.encodePacked(templateId, openingTs, question)
Expand All @@ -147,25 +132,18 @@ contract L2ForkArbitrator is IL2ForkArbitrator {
timeout,
minBond,
address(realitio),
msg.sender,
adjudicationFramework,
nonce
)
);
arbitrationData[question_id] = ArbitrationData(
ArbitrationStatus.SOME,
delay
);
}
uint256 delay = IMinimalAdjudicationFramework(adjudicationFramework)
.getInvestigationDelay();

/// @inheritdoc IL2ForkArbitrator
function requestActivateFork(bytes32 question_id) public {
if (arbitrationData[question_id].status == ArbitrationStatus.NONE)
revert ArbitrationDataNotSet();
if (
arbitrationRequests[question_id].timeOfRequest +
arbitrationData[question_id].delay >
arbitrationRequests[question_id].timeOfRequest + delay >
block.timestamp
) revert RequestStillInWaitingPeriod();

if (isForkInProgress) {
revert ForkInProgress(); // Forking over something else
}
Expand Down
27 changes: 11 additions & 16 deletions contracts/interfaces/IL2ForkArbitrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,30 +62,25 @@ interface IL2ForkArbitrator is IBridgeMessageReceiver {
uint256 maxPrevious
) external payable returns (bool);

/// @notice If the fork request fails, we will get a message back through the bridge telling us about it
/// We will set FORK_REQUEST_FAILED which will allow anyone to request cancellation
/// @param templateId The templateId of the question
/// @param openingTs The opening timestamp of the question
/// @param question The question
/// @param timeout The timeout of the question
/// @param minBond The minimum bond of the question
/// @param nonce The nonce of the question
/// @param delay The delay for the L2 ForkArbitrator
function storeInformation(
/// @notice Request a fork via the bridge
/// @dev Talks to the L1 ForkingManager asynchronously, and may fail.
/// @param templateId The template id of the question during requestArbitration call
/// @param openingTs The opening timestamp of the question during requestArbitration call
/// @param question The question during requestArbitration call
/// @param timeout The timeout of the question during requestArbitration call
/// @param minBond The min bond of the question during requestArbitration call
/// @param nonce The nonce of the question during requestArbitration call
/// @param adjudicationFramework The address of the adjudication framework
function requestActivateFork(
uint256 templateId,
uint32 openingTs,
string calldata question,
uint32 timeout,
uint256 minBond,
uint256 nonce,
uint256 delay
address adjudicationFramework
) external;

/// @notice Request a fork via the bridge
/// @dev Talks to the L1 ForkingManager asynchronously, and may fail.
/// @param questionId The questionId in the question
function requestActivateFork(bytes32 questionId) external;

// If the fork request fails, we will get a message back through the bridge telling us about it
// We will set FORK_REQUEST_FAILED which will allow anyone to request cancellation
function onMessageReceived(
Expand Down
14 changes: 6 additions & 8 deletions test/AdjudicationFramework/AdjudicationFrameworkMinimal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {MinimalAdjudicationFramework} from "../../contracts/AdjudicationFramewor
import {L2ForkArbitrator} from "../../contracts/L2ForkArbitrator.sol";
import {L1GlobalForkRequester} from "../../contracts/L1GlobalForkRequester.sol";
import {L2ChainInfo} from "../../contracts/L2ChainInfo.sol";
import {IMinimalAdjudicationFrameworkErrors} from "../../contracts/AdjudicationFramework/interface/IMinimalAdjudicationFrameworkErrors.sol";

import {MockPolygonZkEVMBridge} from "../testcontract/MockPolygonZkEVMBridge.sol";

Expand Down Expand Up @@ -301,12 +302,9 @@ contract AdjudicationIntegrationTest is Test {
true,
delay
);
bytes32 questionIdAddMultiple = adjudicationFrameworkWithDelay
.requestModificationOfArbitrators(address(0), address(0x1000));
(, uint256 storedDelay) = l2ForkArbitrator.arbitrationData(
questionIdAddMultiple
);
assertEq(delay, storedDelay, "delay not stored correctly");
uint256 receivedDelay = adjudicationFrameworkWithDelay
.getInvestigationDelay();
assertEq(delay, receivedDelay, "delay not stored correctly");
}

function testrequestModificationOfArbitrators() public {
Expand Down Expand Up @@ -339,7 +337,7 @@ contract AdjudicationIntegrationTest is Test {

// Scenario 4: Invalid case - No arbitrators to modify
vm.expectRevert(
MinimalAdjudicationFramework.NoArbitratorsToModify.selector
IMinimalAdjudicationFrameworkErrors.NoArbitratorsToModify.selector
);
adjudicationFramework1.requestModificationOfArbitrators(
address(0),
Expand Down Expand Up @@ -421,7 +419,7 @@ contract AdjudicationIntegrationTest is Test {

// Clear failed proposition
vm.expectRevert(
MinimalAdjudicationFramework.PropositionNotFailed.selector
IMinimalAdjudicationFrameworkErrors.PropositionNotFailed.selector
);
adjudicationFramework1.clearFailedProposition(questionId);
}
Expand Down
Loading

0 comments on commit debb501

Please sign in to comment.