Skip to content

Commit

Permalink
Merge pull request #236 from RealityETH/forkableRealityETHUsingCreate…
Browse files Browse the repository at this point in the history
…Children

Made forkable reality.eth inherit from @reality.eth/contracts and fork using ForkableStructure
  • Loading branch information
edmundedgar authored Mar 2, 2024
2 parents 137dc41 + 33213bb commit f5e967b
Show file tree
Hide file tree
Showing 11 changed files with 1,715 additions and 1,064 deletions.
1,061 changes: 129 additions & 932 deletions contracts/ForkableRealityETH_ERC20.sol

Large diffs are not rendered by default.

121 changes: 121 additions & 0 deletions contracts/L1ForkArbitrator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.20;

/*
This is a very limited Arbitrator contract for the purpose of handling an arbitration request and passing it on to the ForkingManager.
It doesn't handle submitting the answer to the winning question, this is instead handled by the child reality.eth contract when forking.
*/

import {IRealityETH} from "@reality.eth/contracts/development/contracts/IRealityETH.sol";
import {IArbitratorCore} from "@reality.eth/contracts/development/contracts/IArbitratorCore.sol";
import {IArbitratorErrors} from "@reality.eth/contracts/development/contracts/IArbitratorErrors.sol";
import {IForkingManager} from "./interfaces/IForkingManager.sol";
import {IForkonomicToken} from "./interfaces/IForkonomicToken.sol";
import {IForkableStructure} from "./interfaces/IForkableStructure.sol";

contract L1ForkArbitrator is IArbitratorCore, IArbitratorErrors {
IForkingManager public forkmanager;
IRealityETH public realitio;
IForkonomicToken public token;

/// @notice Could not approve the transfer for some reason
error CouldNotApproveTransfer();

/// @notice Could not deduct fee
error CouldNotDeductFee();

/// @notice Not forked yet
error NotForkedYet();

/// @notice This arbitrator can only arbitrate one dispute in its lifetime
error CanOnlyArbitrateOneDispute();

/// @notice The question ID must be supplied
error MissingQuestionID();

bytes32 public arbitratingQuestionId;
address public payer;

constructor(address _realitio, address _forkmanager, address _token) {
realitio = IRealityETH(_realitio);
forkmanager = IForkingManager(_forkmanager);
token = IForkonomicToken(_token);
}

/* solhint-disable quotes */
// Tells the UI to know that it should prompt the user to use ERC20 instead of the native token.
string public metadata = '{"erc20": true}';

/// @notice Return the dispute fee for the specified question. 0 indicates that we won't arbitrate it.
/// @dev Uses a general default, but can be over-ridden on a question-by-question basis.
function getDisputeFee(bytes32) public view returns (uint256) {
return forkmanager.arbitrationFee();
}

/// @notice Request arbitration, freezing the question until we send submitAnswerByArbitrator
/// @dev Requires payment in token(), which the UI as of early 2024 will not handle.
/// @param _questionId The question in question
/// @param _maxPrevious If specified, reverts if a bond higher than this was submitted after you sent your transaction.
/// NB TODO: This is payable because the interface expects native tokens. Consider changing the interface or adding an ERC20 version.
function requestArbitration(
bytes32 _questionId,
uint256 _maxPrevious
) external payable returns (bool) {
if (arbitratingQuestionId != bytes32(0))
revert CanOnlyArbitrateOneDispute();
if (_questionId == bytes32(0)) revert MissingQuestionID();

uint256 fee = getDisputeFee(_questionId);
if (fee == 0)
revert TheArbitratorMustHaveSetANonZeroFeeForTheQuestion();

// First we transfer the fee to ourselves.
if (!token.transferFrom(msg.sender, address(this), fee))
revert CouldNotDeductFee();

payer = msg.sender;
arbitratingQuestionId = _questionId;

realitio.notifyOfArbitrationRequest(
_questionId,
msg.sender,
_maxPrevious
);

// Now approve so that the fee can be transferred right out to the ForkingManager
if (!token.approve(address(forkmanager), fee))
revert CouldNotApproveTransfer();
IForkingManager.DisputeData memory disputeData = IForkingManager
.DisputeData(true, address(this), _questionId);
IForkingManager(forkmanager).initiateFork(disputeData);

return true;
}

function settleChildren(
bytes32 lastHistoryHash,
bytes32 lastAnswer,
address lastAnswerer
) public {
(address child1, address child2) = IForkableStructure(address(realitio))
.getChildren();
if (child1 == address(0) || child2 == address(0)) revert NotForkedYet();
IRealityETH(child1).assignWinnerAndSubmitAnswerByArbitrator(
arbitratingQuestionId,
bytes32(uint256(1)),
payer,
lastHistoryHash,
lastAnswer,
lastAnswerer
);
IRealityETH(child2).assignWinnerAndSubmitAnswerByArbitrator(
arbitratingQuestionId,
bytes32(uint256(0)),
payer,
lastHistoryHash,
lastAnswer,
lastAnswerer
);
}
}
128 changes: 0 additions & 128 deletions contracts/interfaces/IForkableRealityETH.sol

This file was deleted.

14 changes: 14 additions & 0 deletions contracts/interfaces/IForkableRealityETH_ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.20;

import {IRealityETH_ERC20} from "@reality.eth/contracts/development/contracts/IRealityETH_ERC20.sol";

// solhint-disable-next-line contract-name-camelcase
interface IForkableRealityETH_ERC20 is IRealityETH_ERC20 {
function creditBalanceFromParent(
address beneficiary,
uint256 amount
) external;
function l1ForkArbitrator() external returns (address);
}
2 changes: 1 addition & 1 deletion contracts/interfaces/IForkingManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ interface IForkingManager is IForkableStructure {

function globalExitRoot() external returns (address);

function arbitrationFee() external returns (uint256);
function arbitrationFee() external view returns (uint256);

function disputeData()
external
Expand Down
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@openzeppelin/contracts": "^4.9.5",
"@openzeppelin/contracts-upgradeable": "^4.9.5",
"@openzeppelin/hardhat-upgrades": "1.22.1",
"@reality.eth/contracts": "4.0.0-rc.5",
"@RealityETH/zkevm-contracts": "github:RealityETH/zkevm-contracts#a090458140cdfce23763af887ff0767469368923",
"@types/sinon-chai": "^3.2.3",
"circomlibjs": "0.1.1",
Expand Down
2 changes: 1 addition & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
ds-test/=lib/forge-std/lib/ds-test/src/
forge-std/=lib/forge-std/src/
forge-std/=lib/forge-std/src/
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,12 @@ contract AdjudicationIntegrationTest is Test {
);

l1RealityEth = new ForkableRealityETH_ERC20();
l1RealityEth.init(tokenMock, address(0), bytes32(0));
l1RealityEth.initialize(
address(l1ForkingManager),
address(0),
address(tokenMock),
bytes32(0)
);

/*
Creates templates 1, 2, 3 as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,12 @@ contract AdjudicationIntegrationTest is Test {
);

l1RealityEth = new ForkableRealityETH_ERC20();
l1RealityEth.init(tokenMock, address(0), bytes32(0));
l1RealityEth.initialize(
address(l1ForkingManager),
address(0),
address(tokenMock),
(0)
);

/*
Creates templates 1, 2, 3 as
Expand Down
Loading

0 comments on commit f5e967b

Please sign in to comment.