Skip to content

Commit

Permalink
prettify
Browse files Browse the repository at this point in the history
  • Loading branch information
edmundedgar committed Feb 22, 2024
1 parent 109643a commit 8d4778b
Show file tree
Hide file tree
Showing 6 changed files with 894 additions and 226 deletions.
81 changes: 57 additions & 24 deletions contracts/ForkableRealityETH_ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import {L1ForkArbitrator} from "./L1ForkArbitrator.sol";
This is a forkable version of the Reality.eth contract for use on L1.
*/

contract ForkableRealityETH_ERC20 is RealityETHFreezable_ERC20, ForkableStructure {

contract ForkableRealityETH_ERC20 is
RealityETHFreezable_ERC20,
ForkableStructure
{
// Asking questions is locked down the the forkmanager.
// This isn't strictly necessary but it reduces the attack surface.
// TODO: We might want to replace this with a governance contract owned by the forkmanager.
modifier permittedQuestionerOnly() override {
if (msg.sender != forkmanager) revert PermittedQuestionerOnly();
if (msg.sender != forkmanager) revert PermittedQuestionerOnly();
_;
}

Expand All @@ -30,16 +32,21 @@ contract ForkableRealityETH_ERC20 is RealityETHFreezable_ERC20, ForkableStructur

uint256 constant UPGRADE_TEMPLATE_ID = 1048576;

function initialize (
function initialize(
address _forkmanager,
address _parentContract,
address _token,
bytes32 _questionIdWeForkedOver
) initializer public {

) public initializer {
// We do this with a new contract instead of a proxy as it's pretty tiny
// TODO: Should we use a proxy pattern like elsewhere?
l1ForkArbitrator = address(new L1ForkArbitrator(address(this), address(_forkmanager), address(_token)));
l1ForkArbitrator = address(
new L1ForkArbitrator(
address(this),
address(_forkmanager),
address(_token)
)
);

ForkableStructure.initialize(_forkmanager, _parentContract);

Expand All @@ -49,12 +56,13 @@ contract ForkableRealityETH_ERC20 is RealityETHFreezable_ERC20, ForkableStructur
// We immediately import the initial question we forked over, which keep its original arbitrator.
// (Any other imported question will use the new l1ForkArbitrator)
if (_questionIdWeForkedOver != bytes32(0x0)) {
address parentArbitrator = ForkableRealityETH_ERC20(parentContract).l1ForkArbitrator();
address parentArbitrator = ForkableRealityETH_ERC20(parentContract)
.l1ForkArbitrator();
_importQuestion(_questionIdWeForkedOver, parentArbitrator);
}
}

function _createInitialTemplates() override internal {
function _createInitialTemplates() internal override {
// TODO: Decide if we want to include the original templates for consistency/flexibility
// ...even though they won't be used unless we upgrade the forkmanager or whatever governs this.

Expand All @@ -71,15 +79,23 @@ contract ForkableRealityETH_ERC20 is RealityETHFreezable_ERC20, ForkableStructur
/// NB The question ID will no longer match the hash of the content, as the arbitrator has changed
/// @param _questionId - The ID of the question to import
/// @param _newArbitrator - The new arbitrator we should use.
function _importQuestion(bytes32 _questionId, address _newArbitrator) internal {

IForkableRealityETH_ERC20 parent = IForkableRealityETH_ERC20(parentContract);
function _importQuestion(
bytes32 _questionId,
address _newArbitrator
) internal {
IForkableRealityETH_ERC20 parent = IForkableRealityETH_ERC20(
parentContract
);
uint32 timeout = parent.getTimeout(_questionId);
uint32 finalizeTS = parent.getFinalizeTS(_questionId);
bool isPendingArbitration = parent.isPendingArbitration(_questionId);

// For any open question, bump the finalization time to the import time plus a normal timeout period.
if (finalizeTS > 0 && !isPendingArbitration && !parent.isFinalized(_questionId)) {
if (
finalizeTS > 0 &&
!isPendingArbitration &&
!parent.isFinalized(_questionId)
) {
finalizeTS = uint32(block.timestamp + timeout);
}

Expand All @@ -99,7 +115,9 @@ contract ForkableRealityETH_ERC20 is RealityETHFreezable_ERC20, ForkableStructur
}

// Anyone can import any question if it has not already been imported.
function importQuestion(bytes32 questionId) stateNotCreated(questionId) external {
function importQuestion(
bytes32 questionId
) external stateNotCreated(questionId) {
_importQuestion(questionId, l1ForkArbitrator);
}

Expand All @@ -110,32 +128,47 @@ contract ForkableRealityETH_ERC20 is RealityETHFreezable_ERC20, ForkableStructur
{
return _createChildren();
}

// Move our internal balance record for a single address to the child contracts after a fork.
function moveBalanceToChildren(address beneficiary) onlyAfterForking external {
function moveBalanceToChildren(
address beneficiary
) external onlyAfterForking {
uint256 bal = balanceOf[beneficiary];
balanceOf[beneficiary] = 0;
IForkableRealityETH_ERC20(children[0]).creditBalanceFromParent(beneficiary, bal);
IForkableRealityETH_ERC20(children[1]).creditBalanceFromParent(beneficiary, bal);
IForkableRealityETH_ERC20(children[0]).creditBalanceFromParent(
beneficiary,
bal
);
IForkableRealityETH_ERC20(children[1]).creditBalanceFromParent(
beneficiary,
bal
);
}

function creditBalanceFromParent(address beneficiary, uint256 amount) onlyParent external {
function creditBalanceFromParent(
address beneficiary,
uint256 amount
) external onlyParent {
balanceOf[beneficiary] = balanceOf[beneficiary] + amount;
}

function _moveTokensToChild(address _childRealityETH, uint256 amount) internal {
address childToken = address(IForkableRealityETH_ERC20(_childRealityETH).token());
function _moveTokensToChild(
address _childRealityETH,
uint256 amount
) internal {
address childToken = address(
IForkableRealityETH_ERC20(_childRealityETH).token()
);
IForkonomicToken(childToken).transfer(_childRealityETH, amount);
}

// TODO: Make sure this gets called on initiateFork, it can't wait until executeFork because we can't arbitrate anything else that happens
// It may be simpler to let anybody call it and have it check with the fork manager that we're forking
function handleFork() onlyForkManger onlyAfterForking external {
function handleFork() external onlyForkManger onlyAfterForking {
uint256 balance = token.balanceOf(address(this));
IForkonomicToken(address(token)).splitTokensIntoChildTokens(balance);
_moveTokensToChild(children[0], balance);
_moveTokensToChild(children[1], balance);
freezeTs = uint32(block.timestamp);
freezeTs = uint32(block.timestamp);
}

}
59 changes: 39 additions & 20 deletions contracts/L1ForkArbitrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ 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;
Expand All @@ -35,11 +34,7 @@ contract L1ForkArbitrator is IArbitratorCore, IArbitratorErrors {
bytes32 public arbitratingQuestionId;
address public payer;

constructor(
address _realitio,
address _forkmanager,
address _token
) {
constructor(address _realitio, address _forkmanager, address _token) {
realitio = IRealityETH(_realitio);
forkmanager = IForkingManager(_forkmanager);
token = IForkonomicToken(_token);
Expand All @@ -59,40 +54,64 @@ contract L1ForkArbitrator is IArbitratorCore, IArbitratorErrors {
/// @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();
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();
if (fee == 0)
revert TheArbitratorMustHaveSetANonZeroFeeForTheQuestion();

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

payer = msg.sender;
arbitratingQuestionId = _questionId;

realitio.notifyOfArbitrationRequest(_questionId, msg.sender, _maxPrevious);
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 CouldNotDeductFee();
IForkingManager.DisputeData memory disputeData = IForkingManager.DisputeData(true,address(this), _questionId);
if (!token.approve(address(forkmanager), fee))
revert CouldNotDeductFee();
IForkingManager.DisputeData memory disputeData = IForkingManager
.DisputeData(true, address(this), _questionId);
IForkingManager(forkmanager).initiateFork(disputeData);

return true;

}

function settleChildren(
bytes32 lastHistoryHash,
bytes32 lastAnswer,
address lastAnswerer
address lastAnswerer
) public {
(address child1, address child2) = IForkableStructure(address(realitio)).getChildren();
(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);
IRealityETH(child1).assignWinnerAndSubmitAnswerByArbitrator(
arbitratingQuestionId,
bytes32(uint256(1)),
payer,
lastHistoryHash,
lastAnswer,
lastAnswerer
);
IRealityETH(child2).assignWinnerAndSubmitAnswerByArbitrator(
arbitratingQuestionId,
bytes32(uint256(0)),
payer,
lastHistoryHash,
lastAnswer,
lastAnswerer
);
}

}
7 changes: 5 additions & 2 deletions contracts/interfaces/IForkableRealityETH_ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import {IRealityETH_ERC20} from "@reality.eth/contracts/development/contracts/IR

// 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);
function creditBalanceFromParent(
address beneficiary,
uint256 amount
) external;
function l1ForkArbitrator() external returns (address);
}
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.initialize(address(l1ForkingManager), address(0), address(tokenMock), 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.initialize(address(l1ForkingManager), address(0), address(tokenMock), (0));
l1RealityEth.initialize(
address(l1ForkingManager),
address(0),
address(tokenMock),
(0)
);

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

0 comments on commit 8d4778b

Please sign in to comment.