Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"@kleros/dispute-resolver-interface-contract-0.8/contracts/IDisputeResolver.sol": {
"content": "// SPDX-License-Identifier: MIT
/**
* @authors: [@ferittuncer]
* @reviewers: [@mtsalenc*, @hbarcelos*, @unknownunknown1, @MerlinEgalite, @fnanni-0*, @shalzz]
* @auditors: []
* @bounties: []
* @deployments: []
*/
pragma solidity ^0.8.0;
import "@kleros/erc-792/contracts/IArbitrable.sol";
import "@kleros/erc-792/contracts/erc-1497/IEvidence.sol";
import "@kleros/erc-792/contracts/IArbitrator.sol";
/**
* @title This serves as a standard interface for crowdfunded appeals and evidence submission, which aren't a part of the arbitration (erc-792 and erc-1497) standard yet.
This interface is used in Dispute Resolver (resolve.kleros.io).
*/
abstract contract IDisputeResolver is IArbitrable, IEvidence {
string public constant VERSION = "2.0.0"; // Can be used to distinguish between multiple deployed versions, if necessary.
/** @dev Raised when a contribution is made, inside fundAppeal function.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _round The round number the contribution was made to.
* @param ruling Indicates the ruling option which got the contribution.
* @param _contributor Caller of fundAppeal function.
* @param _amount Contribution amount.
*/
event Contribution(uint256 indexed _localDisputeID, uint256 indexed _round, uint256 ruling, address indexed _contributor, uint256 _amount);
/** @dev Raised when a contributor withdraws non-zero value.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _round The round number the withdrawal was made from.
* @param _ruling Indicates the ruling option which contributor gets rewards from.
* @param _contributor The beneficiary of withdrawal.
* @param _reward Total amount of withdrawal, consists of reimbursed deposits plus rewards.
*/
event Withdrawal(uint256 indexed _localDisputeID, uint256 indexed _round, uint256 _ruling, address indexed _contributor, uint256 _reward);
/** @dev To be raised when a ruling option is fully funded for appeal.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _round Number of the round this ruling option was fully funded in.
* @param _ruling The ruling option which just got fully funded.
*/
event RulingFunded(uint256 indexed _localDisputeID, uint256 indexed _round, uint256 indexed _ruling);
/** @dev Maps external (arbitrator side) dispute id to local (arbitrable) dispute id.
* @param _externalDisputeID Dispute id as in arbitrator contract.
* @return localDisputeID Dispute id as in arbitrable contract.
*/
function externalIDtoLocalID(uint256 _externalDisputeID) external virtual returns (uint256 localDisputeID);
/** @dev Returns number of possible ruling options. Valid rulings are [0, return value].
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @return count The number of ruling options.
*/
function numberOfRulingOptions(uint256 _localDisputeID) external view virtual returns (uint256 count);
/** @dev Allows to submit evidence for a given dispute.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _evidenceURI IPFS path to evidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/evidence.json'
*/
function submitEvidence(uint256 _localDisputeID, string calldata _evidenceURI) external virtual;
/** @dev Manages contributions and calls appeal function of the specified arbitrator to appeal a dispute. This function lets appeals be crowdfunded.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _ruling The ruling option to which the caller wants to contribute.
* @return fullyFunded True if the ruling option got fully funded as a result of this contribution.
*/
function fundAppeal(uint256 _localDisputeID, uint256 _ruling) external payable virtual returns (bool fullyFunded);
/** @dev Returns appeal multipliers.
* @return winnerStakeMultiplier Winners stake multiplier.
* @return loserStakeMultiplier Losers stake multiplier.
* @return loserAppealPeriodMultiplier Losers appeal period multiplier. The loser is given less time to fund its appeal to defend against last minute appeal funding attacks.
* @return denominator Multiplier denominator in basis points.
*/
function getMultipliers()
external
view
virtual
returns (
uint256 winnerStakeMultiplier,
uint256 loserStakeMultiplier,
uint256 loserAppealPeriodMultiplier,
uint256 denominator
);
/** @dev Allows to withdraw any reimbursable fees or rewards after the dispute gets resolved.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _contributor Beneficiary of withdraw operation.
* @param _round Number of the round that caller wants to execute withdraw on.
* @param _ruling A ruling option that caller wants to execute withdraw on.
* @return sum The amount that is going to be transferred to contributor as a result of this function call.
*/
function withdrawFeesAndRewards(
uint256 _localDisputeID,
address payable _contributor,
uint256 _round,
uint256 _ruling
) external virtual returns (uint256 sum);
/** @dev Allows to withdraw any rewards or reimbursable fees after the dispute gets resolved for all rounds at once.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _contributor Beneficiary of withdraw operation.
* @param _ruling Ruling option that caller wants to execute withdraw on.
*/
function withdrawFeesAndRewardsForAllRounds(
uint256 _localDisputeID,
address payable _contributor,
uint256 _ruling
) external virtual;
/** @dev Returns the sum of withdrawable amount.
* @param _localDisputeID Identifier of a dispute in scope of arbitrable contract. Arbitrator ids can be translated to local ids via externalIDtoLocalID.
* @param _contributor Beneficiary of withdraw operation.
* @param _ruling Ruling option that caller wants to get withdrawable amount from.
* @return sum The total amount available to withdraw.
*/
function getTotalWithdrawableAmount(
uint256 _localDisputeID,
address payable _contributor,
uint256 _ruling
) external view virtual returns (uint256 sum);
}
"
},
"@kleros/erc-792/contracts/erc-1497/IEvidence.sol": {
"content": "/**
* @authors: [@ferittuncer, @hbarcelos]
* @reviewers: []
* @auditors: []
* @bounties: []
* @deployments: []
* SPDX-License-Identifier: MIT
*/
pragma solidity >=0.7;
import "../IArbitrator.sol";
/** @title IEvidence
* ERC-1497: Evidence Standard
*/
interface IEvidence {
/**
* @dev To be emitted when meta-evidence is submitted.
* @param _metaEvidenceID Unique identifier of meta-evidence.
* @param _evidence A link to the meta-evidence JSON.
*/
event MetaEvidence(uint256 indexed _metaEvidenceID, string _evidence);
/**
* @dev To be raised when evidence is submitted. Should point to the resource (evidences are not to be stored on chain due to gas considerations).
* @param _arbitrator The arbitrator of the contract.
* @param _evidenceGroupID Unique identifier of the evidence group the evidence belongs to.
* @param _party The address of the party submiting the evidence. Note that 0x0 refers to evidence not submitted by any party.
* @param _evidence A URI to the evidence JSON file whose name should be its keccak256 hash followed by .json.
*/
event Evidence(
IArbitrator indexed _arbitrator,
uint256 indexed _evidenceGroupID,
address indexed _party,
string _evidence
);
/**
* @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.
* @param _arbitrator The arbitrator of the contract.
* @param _disputeID ID of the dispute in the Arbitrator contract.
* @param _metaEvidenceID Unique identifier of meta-evidence.
* @param _evidenceGroupID Unique identifier of the evidence group that is linked to this dispute.
*/
event Dispute(
IArbitrator indexed _arbitrator,
uint256 indexed _disputeID,
uint256 _metaEvidenceID,
uint256 _evidenceGroupID
);
}
"
},
"@kleros/erc-792/contracts/IArbitrable.sol": {
"content": "/**
* @authors: [@ferittuncer, @hbarcelos]
* @reviewers: [@remedcu*]
* @auditors: []
* @bounties: []
* @deployments: []
* SPDX-License-Identifier: MIT
*/
pragma solidity >=0.7;
import "./IArbitrator.sol";
/**
* @title IArbitrable
* Arbitrable interface.
* When developing arbitrable contracts, we need to:
* - Define the action taken when a ruling is received by the contract.
* - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData);
*/
interface IArbitrable {
/**
* @dev To be raised when a ruling is given.
* @param _arbitrator The arbitrator giving the ruling.
* @param _disputeID ID of the dispute in the Arbitrator contract.
* @param _ruling The ruling which was given.
*/
event Ruling(IArbitrator indexed _arbitrator, uint256 indexed _disputeID, uint256 _ruling);
/**
* @dev Give a ruling for a dispute. Must be called by the arbitrator.
* The purpose of this function is to ensure that the address calling it has the right to rule on the contract.
* @param _disputeID ID of the dispute in the Arbitrator contract.
* @param _ruling Ruling given by the arbitrator. Note that 0 is reserved for "Not able/wanting to make a decision".
*/
function rule(uint256 _disputeID, uint256 _ruling) external;
}
"
},
"@kleros/erc-792/contracts/IArbitrator.sol": {
"content": "/**
* @authors: [@ferittuncer, @hbarcelos]
* @reviewers: [@remedcu*]
* @auditors: []
* @bounties: []
* @deployments: []
* SPDX-License-Identifier: MIT
*/
pragma solidity >=0.7;
import "./IArbitrable.sol";
/**
* @title Arbitrator
* Arbitrator abstract contract.
* When developing arbitrator contracts we need to:
* - Define the functions for dispute creation (createDispute) and appeal (appeal). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes).
* - Define the functions for cost display (arbitrationCost and appealCost).
* - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling).
*/
interface IArbitrator {
enum DisputeStatus {Waiting, Appealable, Solved}
/**
* @dev To be emitted when a dispute is created.
* @param _disputeID ID of the dispute.
* @param _arbitrable The contract which created the dispute.
*/
event DisputeCreation(uint256 indexed _disputeID, IArbitrable indexed _arbitrable);
/**
* @dev To be emitted when a dispute can be appealed.
* @param _disputeID ID of the dispute.
* @param _arbitrable The contract which created the dispute.
*/
event AppealPossible(uint256 indexed _disputeID, IArbitrable indexed _arbitrable);
/**
* @dev To be emitted when the current ruling is appealed.
* @param _disputeID ID of the dispute.
* @param _arbitrable The contract which created the dispute.
*/
event AppealDecision(uint256 indexed _disputeID, IArbitrable indexed _arbitrable);
/**
* @dev Create a dispute. Must be called by the arbitrable contract.
* Must be paid at least arbitrationCost(_extraData).
* @param _choices Amount of choices the arbitrator can make in this dispute.
* @param _extraData Can be used to give additional info on the dispute to be created.
* @return disputeID ID of the dispute created.
*/
function createDispute(uint256 _choices, bytes calldata _extraData) external payable returns (uint256 disputeID);
/**
* @dev Compute the cost of arbitration. It is recommended not to increase it often, as it can be highly time and gas consuming for the arbitrated contracts to cope with fee augmentation.
* @param _extraData Can be used to give additional info on the dispute to be created.
* @return cost Amount to be paid.
*/
function arbitrationCost(bytes calldata _extraData) external view returns (uint256 cost);
/**
* @dev Appeal a ruling. Note that it has to be called before the arbitrator contract calls rule.
* @param _disputeID ID of the dispute to be appealed.
* @param _extraData Can be used to give extra info on the appeal.
*/
function appeal(uint256 _disputeID, bytes calldata _extraData) external payable;
/**
* @dev Compute the cost of appeal. It is recommended not to increase it often, as it can be higly time and gas consuming for the arbitrated contracts to cope with fee augmentation.
* @param _disputeID ID of the dispute to be appealed.
* @param _extraData Can be used to give additional info on the dispute to be created.
* @return cost Amount to be paid.
*/
function appealCost(uint256 _disputeID, bytes calldata _extraData) external view returns (uint256 cost);
/**
* @dev Compute the start and end of the dispute's current or next appeal period, if possible. If not known or appeal is impossible: should return (0, 0).
* @param _disputeID ID of the dispute.
* @return start The start of the period.
* @return end The end of the period.
*/
function appealPeriod(uint256 _disputeID) external view returns (uint256 start, uint256 end);
/**
* @dev Return the status of a dispute.
* @param _disputeID ID of the dispute to rule.
* @return status The status of the dispute.
*/
function disputeStatus(uint256 _disputeID) external view returns (DisputeStatus status);
/**
* @dev Return the current ruling of a dispute. This is useful for parties to know if they should appeal.
* @param _disputeID ID of the dispute.
* @return ruling The ruling which has been given or the one which will be given if there is no appeal.
*/
function currentRuling(uint256 _disputeID) external view returns (uint256 ruling);
}
"
},
"src/0.8/interfaces/IArbitrationProxies.sol": {
"content": "// SPDX-License-Identifier: MIT\r
pragma solidity 0.8.25;\r
\r
import {IArbitrable} from "@kleros/erc-792/contracts/IArbitrable.sol";\r
import {IEvidence} from "@kleros/erc-792/contracts/erc-1497/IEvidence.sol";\r
import {IRealitio} from "./IRealitio.sol";\r
\r
interface IHomeArbitrationProxy {\r
/**\r
* @notice To be emitted when the Realitio contract has been notified of an arbitration request.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
* @param _maxPrevious The maximum value of the previous bond for the question.\r
*/\r
event RequestNotified(bytes32 indexed _questionID, address indexed _requester, uint256 _maxPrevious);\r
\r
/**\r
* @notice To be emitted when arbitration request is rejected.\r
* @dev This can happen if the current bond for the question is higher than maxPrevious\r
* or if the question is already finalized.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
* @param _maxPrevious The maximum value of the current bond for the question.\r
* @param _reason The reason why the request was rejected.\r
*/\r
event RequestRejected(\r
bytes32 indexed _questionID,\r
address indexed _requester,\r
uint256 _maxPrevious,\r
string _reason\r
);\r
\r
/**\r
* @notice To be emitted when the arbitration request acknowledgement is sent to the Foreign Chain.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
event RequestAcknowledged(bytes32 indexed _questionID, address indexed _requester);\r
\r
/**\r
* @notice To be emitted when the arbitration request is canceled.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
event RequestCanceled(bytes32 indexed _questionID, address indexed _requester);\r
\r
/**\r
* @notice To be emitted when the dispute could not be created on the Foreign Chain.\r
* @dev This will happen if the arbitration fee increases in between the arbitration request and acknowledgement.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
event ArbitrationFailed(bytes32 indexed _questionID, address indexed _requester);\r
\r
/**\r
* @notice To be emitted when receiving the answer from the arbitrator.\r
* @param _questionID The ID of the question.\r
* @param _answer The answer from the arbitrator.\r
*/\r
event ArbitratorAnswered(bytes32 indexed _questionID, bytes32 _answer);\r
\r
/**\r
* @notice To be emitted when reporting the arbitrator answer to Realitio.\r
* @param _questionID The ID of the question.\r
*/\r
event ArbitrationFinished(bytes32 indexed _questionID);\r
\r
/**\r
* @dev Receives the requested arbitration for a question. TRUSTED.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
* @param _maxPrevious The maximum value of the current bond for the question. The arbitration request will get rejected if the current bond is greater than _maxPrevious. If set to 0, _maxPrevious is ignored.\r
*/\r
function receiveArbitrationRequest(bytes32 _questionID, address _requester, uint256 _maxPrevious) external;\r
\r
/**\r
* @notice Handles arbitration request after it has been notified to Realitio for a given question.\r
* @dev This method exists because `receiveArbitrationRequest` is called by\r
* the bridge and cannot send messages back to it.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
function handleNotifiedRequest(bytes32 _questionID, address _requester) external;\r
\r
/**\r
* @notice Handles arbitration request after it has been rejected.\r
* @dev This method exists because `receiveArbitrationRequest` is called by\r
* the bridge and cannot send messages back to it.\r
* Reasons why the request might be rejected:\r
* - The question does not exist\r
* - The question was not answered yet\r
* - The quesiton bond value changed while the arbitration was being requested\r
* - Another request was already accepted\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
function handleRejectedRequest(bytes32 _questionID, address _requester) external;\r
\r
/**\r
* @notice Receives a failed attempt to request arbitration. TRUSTED.\r
* @dev Currently this can happen only if the arbitration cost increased.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
function receiveArbitrationFailure(bytes32 _questionID, address _requester) external;\r
\r
/**\r
* @notice Receives the answer to a specified question. TRUSTED.\r
* @param _questionID The ID of the question.\r
* @param _answer The answer from the arbitrator.\r
*/\r
function receiveArbitrationAnswer(bytes32 _questionID, bytes32 _answer) external;\r
\r
/** @notice Provides a string of json-encoded metadata with the following properties:\r
- tos: A URI representing the location of a terms-of-service document for the arbitrator.\r
- template_hashes: An array of hashes of templates supported by the arbitrator. If you have a numerical ID for a template registered with Reality.eth, you can look up this hash by calling the Reality.eth template_hashes() function.\r
* @dev Template_hashes won't be used by this home proxy. \r
*/\r
function metadata() external view returns (string calldata);\r
\r
/**\r
* @notice Returns the address of Reality instance.\r
* @return Realitio address.\r
*/\r
function realitio() external view returns (IRealitio);\r
}\r
\r
interface IForeignArbitrationProxy {\r
/**\r
* @notice Should be emitted when the arbitration is requested.\r
* @param _questionID The ID of the question with the request for arbitration.\r
* @param _requester The address of the arbitration requester.\r
* @param _maxPrevious The maximum value of the current bond for the question. The arbitration request will get rejected if the current bond is greater than _maxPrevious. If set to 0, _maxPrevious is ignored.\r
*/\r
event ArbitrationRequested(bytes32 indexed _questionID, address indexed _requester, uint256 _maxPrevious);\r
\r
/**\r
* @notice Should be emitted when the dispute is created.\r
* @param _questionID The ID of the question with the request for arbitration.\r
* @param _requester The address of the arbitration requester.\r
* @param _disputeID The ID of the dispute.\r
*/\r
event ArbitrationCreated(bytes32 indexed _questionID, address indexed _requester, uint256 indexed _disputeID);\r
\r
/**\r
* @notice Should be emitted when the arbitration is canceled by the Home Chain.\r
* @param _questionID The ID of the question with the request for arbitration.\r
* @param _requester The address of the arbitration requester.\r
*/\r
event ArbitrationCanceled(bytes32 indexed _questionID, address indexed _requester);\r
\r
/**\r
* @notice Should be emitted when the dispute could not be created.\r
* @dev This will happen if there is an increase in the arbitration fees\r
* between the time the arbitration is made and the time it is acknowledged.\r
* @param _questionID The ID of the question with the request for arbitration.\r
* @param _requester The address of the arbitration requester.\r
*/\r
event ArbitrationFailed(bytes32 indexed _questionID, address indexed _requester);\r
\r
/**\r
* @notice Should be emitted when the ruling is relayed to home proxy manually. Some implementations may not emit this event.\r
* @param _questionID The ID of the question with the ruling to relay.\r
* @param _ruling Ruling converted into Realitio format.\r
*/\r
event RulingRelayed(bytes32 _questionID, bytes32 _ruling);\r
\r
/**\r
* @notice Requests arbitration for the given question and contested answer.\r
* @param _questionID The ID of the question.\r
* @param _maxPrevious The maximum value of the current bond for the question. The arbitration request will get rejected if the current bond is greater than _maxPrevious. If set to 0, _maxPrevious is ignored.\r
*/\r
function requestArbitration(bytes32 _questionID, uint256 _maxPrevious) external payable;\r
\r
/**\r
* @notice Receives the acknowledgement of the arbitration request for the given question and requester. TRUSTED.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
function receiveArbitrationAcknowledgement(bytes32 _questionID, address _requester) external;\r
\r
/**\r
* @notice Receives the cancelation of the arbitration request for the given question and requester. TRUSTED.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
function receiveArbitrationCancelation(bytes32 _questionID, address _requester) external;\r
\r
/**\r
* @notice Cancels the arbitration in case the dispute could not be created.\r
* @param _questionID The ID of the question.\r
* @param _requester The address of the arbitration requester.\r
*/\r
function handleFailedDisputeCreation(bytes32 _questionID, address _requester) external payable;\r
\r
/**\r
* @notice Gets the fee to create a dispute.\r
* @param _questionID the ID of the question.\r
* @return The fee to create a dispute.\r
*/\r
function getDisputeFee(bytes32 _questionID) external view returns (uint256);\r
\r
/**\r
* @notice Returns the address of the home proxy.\r
* @return Home proxy address.\r
*/\r
function homeProxy() external view returns (address);\r
\r
/**\r
* @notice Returns the creation block of the dispute.\r
* @param _disputeID the ID of the dispute.\r
* @return Block number of dispute creation.\r
*/\r
function arbitrationCreatedBlock(uint256 _disputeID) external view returns (uint256);\r
}\r
"
},
"src/0.8/interfaces/IRealitio.sol": {
"content": "/* solhint-disable var-name-mixedcase */\r
// SPDX-License-Identifier: MIT\r
\r
/**\r
* Interface of https://github.com/RealityETH/reality-eth-monorepo/blob/main/packages/contracts/flat/RealityETH-3.0.sol.\r
* @reviewers: [@hbarcelos, @fnanni-0, @nix1g, @unknownunknown1, @ferittuncer, @jaybuidl]\r
* @auditors: []\r
* @bounties: []\r
* @deployments: []\r
*/\r
\r
pragma solidity 0.8.25;\r
\r
interface IRealitio {\r
event LogNewAnswer(\r
bytes32 answer,\r
bytes32 indexed question_id,\r
bytes32 history_hash,\r
address indexed user,\r
uint256 bond,\r
uint256 ts,\r
bool is_commitment\r
);\r
\r
event LogNewTemplate(uint256 indexed template_id, address indexed user, string question_text);\r
\r
event LogNewQuestion(\r
bytes32 indexed question_id,\r
address indexed user,\r
uint256 template_id,\r
string question,\r
bytes32 indexed content_hash,\r
address arbitrator,\r
uint32 timeout,\r
uint32 opening_ts,\r
uint256 nonce,\r
uint256 created\r
);\r
\r
/**\r
* @dev The arbitrator contract is trusted to only call this if they've been paid, and tell us who paid them.\r
* @notice Notify the contract that the arbitrator has been paid for a question, freezing it pending their decision.\r
* @param question_id The ID of the question.\r
* @param requester The account that requested arbitration.\r
* @param max_previous If specified, reverts if a bond higher than this was submitted after you sent your transaction.\r
*/\r
function notifyOfArbitrationRequest(bytes32 question_id, address requester, uint256 max_previous) external;\r
\r
/**\r
* @notice Cancel a previously-requested arbitration and extend the timeout\r
* @dev Useful when doing arbitration across chains that can't be requested atomically\r
* @param question_id The ID of the question\r
*/\r
function cancelArbitration(bytes32 question_id) external;\r
\r
/**\r
* @notice Submit the answer for a question, for use by the arbitrator, working out the appropriate winner based on the last answer details.\r
* @dev Doesn't require (or allow) a bond.\r
* @param question_id The ID of the question\r
* @param answer The answer, encoded into bytes32\r
* @param payee_if_wrong The account to be credited as winner if the last answer given is wrong, usually the account that paid the arbitrator\r
* @param last_history_hash The history hash before the final one\r
* @param last_answer_or_commitment_id The last answer given, or the commitment ID if it was a commitment.\r
* @param last_answerer The address that supplied the last answer\r
*/\r
function assignWinnerAndSubmitAnswerByArbitrator(\r
bytes32 question_id,\r
bytes32 answer,\r
address payee_if_wrong,\r
bytes32 last_history_hash,\r
bytes32 last_answer_or_commitment_id,\r
address last_answerer\r
) external;\r
}\r
"
},
"src/0.8/interfaces/polygon/FxBaseRootTunnel.sol": {
"content": "// SPDX-License-Identifier: MIT\r
// https://github.com/0xPolygon/fx-portal/blob/65e642f8f97a2e44d703590346a25c4ae00652d0/contracts/tunnel/FxBaseRootTunnel.sol\r
pragma solidity 0.8.25;\r
\r
import {RLPReader} from "./lib/RLPReader.sol";\r
import {MerklePatriciaProof} from "./lib/MerklePatriciaProof.sol";\r
import {Merkle} from "./lib/Merkle.sol";\r
import "./lib/ExitPayloadReader.sol";\r
\r
interface IFxStateSender {\r
function sendMessageToChild(address _receiver, bytes calldata _data) external;\r
}\r
\r
contract ICheckpointManager {\r
struct HeaderBlock {\r
bytes32 root;\r
uint256 start;\r
uint256 end;\r
uint256 createdAt;\r
address proposer;\r
}\r
\r
/**\r
* @notice mapping of checkpoint header numbers to block details\r
* @dev These checkpoints are submited by plasma contracts\r
*/\r
mapping(uint256 => HeaderBlock) public headerBlocks;\r
}\r
\r
abstract contract FxBaseRootTunnel {\r
using RLPReader for RLPReader.RLPItem;\r
using Merkle for bytes32;\r
using ExitPayloadReader for bytes;\r
using ExitPayloadReader for ExitPayloadReader.ExitPayload;\r
using ExitPayloadReader for ExitPayloadReader.Log;\r
using ExitPayloadReader for ExitPayloadReader.LogTopics;\r
using ExitPayloadReader for ExitPayloadReader.Receipt;\r
\r
// keccak256(MessageSent(bytes))\r
bytes32 public constant SEND_MESSAGE_EVENT_SIG = 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036;\r
\r
// state sender contract\r
IFxStateSender public fxRoot;\r
// root chain manager\r
ICheckpointManager public checkpointManager;\r
// child tunnel contract which receives and sends messages\r
address public fxChildTunnel;\r
\r
// storage to avoid duplicate exits\r
mapping(bytes32 => bool) public processedExits;\r
\r
constructor(address _checkpointManager, address _fxRoot) {\r
checkpointManager = ICheckpointManager(_checkpointManager);\r
fxRoot = IFxStateSender(_fxRoot);\r
}\r
\r
// set fxChildTunnel if not set already\r
function setFxChildTunnel(address _fxChildTunnel) public virtual {\r
require(fxChildTunnel == address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET");\r
fxChildTunnel = _fxChildTunnel;\r
}\r
\r
/**\r
* @notice Send bytes message to Child Tunnel\r
* @param message bytes message that will be sent to Child Tunnel\r
* some message examples -\r
* abi.encode(tokenId);\r
* abi.encode(tokenId, tokenMetadata);\r
* abi.encode(messageType, messageData);\r
* @custom:security non-reentrant\r
*/\r
function _sendMessageToChild(bytes memory message) internal {\r
fxRoot.sendMessageToChild(fxChildTunnel, message);\r
}\r
\r
function _validateAndExtractMessage(bytes memory inputData) internal returns (bytes memory) {\r
ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload();\r
\r
bytes memory branchMaskBytes = payload.getBranchMaskAsBytes();\r
uint256 blockNumber = payload.getBlockNumber();\r
// checking if exit has already been processed\r
// unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex)\r
bytes32 exitHash = keccak256(\r
abi.encodePacked(\r
blockNumber,\r
// first 2 nibbles are dropped while generating nibble array\r
// this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only)\r
// so converting to nibble array and then hashing it\r
MerklePatriciaProof._getNibbleArray(branchMaskBytes),\r
payload.getReceiptLogIndex()\r
)\r
);\r
require(processedExits[exitHash] == false, "FxRootTunnel: EXIT_ALREADY_PROCESSED");\r
processedExits[exitHash] = true;\r
\r
ExitPayloadReader.Receipt memory receipt = payload.getReceipt();\r
ExitPayloadReader.Log memory log = receipt.getLog();\r
\r
// check child tunnel\r
require(fxChildTunnel == log.getEmitter(), "FxRootTunnel: INVALID_FX_CHILD_TUNNEL");\r
\r
bytes32 receiptRoot = payload.getReceiptRoot();\r
// verify receipt inclusion\r
require(\r
MerklePatriciaProof.verify(receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), receiptRoot),\r
"FxRootTunnel: INVALID_RECEIPT_PROOF"\r
);\r
\r
// verify checkpoint inclusion\r
_checkBlockMembershipInCheckpoint(\r
blockNumber,\r
payload.getBlockTime(),\r
payload.getTxRoot(),\r
receiptRoot,\r
payload.getHeaderNumber(),\r
payload.getBlockProof()\r
);\r
\r
ExitPayloadReader.LogTopics memory topics = log.getTopics();\r
\r
require(\r
bytes32(topics.getField(0).toUint()) == SEND_MESSAGE_EVENT_SIG, // topic0 is event sig\r
"FxRootTunnel: INVALID_SIGNATURE"\r
);\r
\r
// received message data\r
bytes memory message = abi.decode(log.getData(), (bytes)); // event decodes params again, so decoding bytes to get message\r
return message;\r
}\r
\r
function _checkBlockMembershipInCheckpoint(\r
uint256 blockNumber,\r
uint256 blockTime,\r
bytes32 txRoot,\r
bytes32 receiptRoot,\r
uint256 headerNumber,\r
bytes memory blockProof\r
) private view {\r
(bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = checkpointManager.headerBlocks(headerNumber);\r
\r
require(\r
keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership(\r
blockNumber - startBlock,\r
headerRoot,\r
blockProof\r
),\r
"FxRootTunnel: INVALID_HEADER"\r
);\r
}\r
\r
/**\r
* @notice receive message from L2 to L1, validated by proof\r
* @dev This function verifies if the transaction actually happened on child chain\r
*\r
* @param inputData RLP encoded data of the reference tx containing following list of fields\r
* 0 - headerNumber - Checkpoint header block number containing the reference tx\r
* 1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root\r
* 2 - blockNumber - Block number containing the reference tx on child chain\r
* 3 - blockTime - Reference tx block time\r
* 4 - txRoot - Transactions root of block\r
* 5 - receiptRoot - Receipts root of block\r
* 6 - receipt - Receipt of the reference transaction\r
* 7 - receiptProof - Merkle proof of the reference receipt\r
* 8 - branchMask - 32 bits denoting the path of receipt in merkle tree\r
* 9 - receiptLogIndex - Log Index to read from the receipt\r
*/\r
function receiveMessage(bytes memory inputData) public virtual {\r
bytes memory message = _validateAndExtractMessage(inputData);\r
_processMessageFromChild(message);\r
}\r
\r
/**\r
* @notice Process message received from Child Tunnel\r
* @dev function needs to be implemented to handle message as per requirement\r
* This is called by receiveMessage function.\r
* Since it is called via a system call, any event will not be emitted during its execution.\r
* @param message bytes message that was sent from Child Tunnel\r
*/\r
function _processMessageFromChild(bytes memory message) internal virtual;\r
}\r
"
},
"src/0.8/interfaces/polygon/lib/ExitPayloadReader.sol": {
"content": "pragma solidity 0.8.25;\r
\r
import {RLPReader} from "./RLPReader.sol";\r
\r
library ExitPayloadReader {\r
using RLPReader for bytes;\r
using RLPReader for RLPReader.RLPItem;\r
\r
uint8 constant WORD_SIZE = 32;\r
\r
struct ExitPayload {\r
RLPReader.RLPItem[] data;\r
}\r
\r
struct Receipt {\r
RLPReader.RLPItem[] data;\r
bytes raw;\r
uint256 logIndex;\r
}\r
\r
struct Log {\r
RLPReader.RLPItem data;\r
RLPReader.RLPItem[] list;\r
}\r
\r
struct LogTopics {\r
RLPReader.RLPItem[] data;\r
}\r
\r
// copy paste of private copy() from RLPReader to avoid changing of existing contracts\r
function copy(uint256 src, uint256 dest, uint256 len) private pure {\r
if (len == 0) return;\r
\r
// copy as many word sizes as possible\r
for (; len >= WORD_SIZE; len -= WORD_SIZE) {\r
assembly {\r
mstore(dest, mload(src))\r
}\r
\r
src += WORD_SIZE;\r
dest += WORD_SIZE;\r
}\r
\r
// left over bytes. Mask is used to remove unwanted bytes from the word\r
uint256 mask = 256 ** (WORD_SIZE - len) - 1;\r
assembly {\r
let srcpart := and(mload(src), not(mask)) // zero out src\r
let destpart := and(mload(dest), mask) // retrieve the bytes\r
mstore(dest, or(destpart, srcpart))\r
}\r
}\r
\r
function toExitPayload(bytes memory data) internal pure returns (ExitPayload memory) {\r
RLPReader.RLPItem[] memory payloadData = data.toRlpItem().toList();\r
\r
return ExitPayload(payloadData);\r
}\r
\r
function getHeaderNumber(ExitPayload memory payload) internal pure returns (uint256) {\r
return payload.data[0].toUint();\r
}\r
\r
function getBlockProof(ExitPayload memory payload) internal pure returns (bytes memory) {\r
return payload.data[1].toBytes();\r
}\r
\r
function getBlockNumber(ExitPayload memory payload) internal pure returns (uint256) {\r
return payload.data[2].toUint();\r
}\r
\r
function getBlockTime(ExitPayload memory payload) internal pure returns (uint256) {\r
return payload.data[3].toUint();\r
}\r
\r
function getTxRoot(ExitPayload memory payload) internal pure returns (bytes32) {\r
return bytes32(payload.data[4].toUint());\r
}\r
\r
function getReceiptRoot(ExitPayload memory payload) internal pure returns (bytes32) {\r
return bytes32(payload.data[5].toUint());\r
}\r
\r
function getReceipt(ExitPayload memory payload) internal pure returns (Receipt memory receipt) {\r
receipt.raw = payload.data[6].toBytes();\r
RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem();\r
\r
if (receiptItem.isList()) {\r
// legacy tx\r
receipt.data = receiptItem.toList();\r
} else {\r
// pop first byte before parsting receipt\r
bytes memory typedBytes = receipt.raw;\r
bytes memory result = new bytes(typedBytes.length - 1);\r
uint256 srcPtr;\r
uint256 destPtr;\r
assembly {\r
srcPtr := add(33, typedBytes)\r
destPtr := add(0x20, result)\r
}\r
\r
copy(srcPtr, destPtr, result.length);\r
receipt.data = result.toRlpItem().toList();\r
}\r
\r
receipt.logIndex = getReceiptLogIndex(payload);\r
return receipt;\r
}\r
\r
function getReceiptProof(ExitPayload memory payload) internal pure returns (bytes memory) {\r
return payload.data[7].toBytes();\r
}\r
\r
function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns (bytes memory) {\r
return payload.data[8].toBytes();\r
}\r
\r
function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns (uint256) {\r
return payload.data[8].toUint();\r
}\r
\r
function getReceiptLogIndex(ExitPayload memory payload) internal pure returns (uint256) {\r
return payload.data[9].toUint();\r
}\r
\r
// Receipt methods\r
function toBytes(Receipt memory receipt) internal pure returns (bytes memory) {\r
return receipt.raw;\r
}\r
\r
function getLog(Receipt memory receipt) internal pure returns (Log memory) {\r
RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex];\r
return Log(logData, logData.toList());\r
}\r
\r
// Log methods\r
function getEmitter(Log memory log) internal pure returns (address) {\r
return RLPReader.toAddress(log.list[0]);\r
}\r
\r
function getTopics(Log memory log) internal pure returns (LogTopics memory) {\r
return LogTopics(log.list[1].toList());\r
}\r
\r
function getData(Log memory log) internal pure returns (bytes memory) {\r
return log.list[2].toBytes();\r
}\r
\r
function toRlpBytes(Log memory log) internal pure returns (bytes memory) {\r
return log.data.toRlpBytes();\r
}\r
\r
// LogTopics methods\r
function getField(LogTopics memory topics, uint256 index) internal pure returns (RLPReader.RLPItem memory) {\r
return topics.data[index];\r
}\r
}\r
"
},
"src/0.8/interfaces/polygon/lib/Merkle.sol": {
"content": "// SPDX-License-Identifier: MIT\r
pragma solidity 0.8.25;\r
\r
library Merkle {\r
function checkMembership(\r
bytes32 leaf,\r
uint256 index,\r
bytes32 rootHash,\r
bytes memory proof\r
) internal pure returns (bool) {\r
require(proof.length % 32 == 0, "Invalid proof length");\r
uint256 proofHeight = proof.length / 32;\r
// Proof of size n means, height of the tree is n+1.\r
// In a tree of height n+1, max #leafs possible is 2 ^ n\r
require(index < 2 ** proofHeight, "Leaf index is too big");\r
\r
bytes32 proofElement;\r
bytes32 computedHash = leaf;\r
for (uint256 i = 32; i <= proof.length; i += 32) {\r
assembly {\r
proofElement := mload(add(proof, i))\r
}\r
\r
if (index % 2 == 0) {\r
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));\r
} else {\r
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));\r
}\r
\r
index = index / 2;\r
}\r
return computedHash == rootHash;\r
}\r
}\r
"
},
"src/0.8/interfaces/polygon/lib/MerklePatriciaProof.sol": {
"content": "// SPDX-License-Identifier: MIT\r
pragma solidity 0.8.25;\r
\r
import {RLPReader} from "./RLPReader.sol";\r
\r
library MerklePatriciaProof {\r
/*\r
* @dev Verifies a merkle patricia proof.\r
* @param value The terminating value in the trie.\r
* @param encodedPath The path in the trie leading to value.\r
* @param rlpParentNodes The rlp encoded stack of nodes.\r
* @param root The root hash of the trie.\r
* @return The boolean validity of the proof.\r
*/\r
function verify(\r
bytes memory value,\r
bytes memory encodedPath,\r
bytes memory rlpParentNodes,\r
bytes32 root\r
) internal pure returns (bool) {\r
RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes);\r
RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item);\r
\r
bytes memory currentNode;\r
RLPReader.RLPItem[] memory currentNodeList;\r
\r
bytes32 nodeKey = root;\r
uint256 pathPtr = 0;\r
\r
bytes memory path = _getNibbleArray(encodedPath);\r
if (path.length == 0) {\r
return false;\r
}\r
\r
for (uint256 i = 0; i < parentNodes.length; i++) {\r
if (pathPtr > path.length) {\r
return false;\r
}\r
\r
currentNode = RLPReader.toRlpBytes(parentNodes[i]);\r
if (nodeKey != keccak256(currentNode)) {\r
return false;\r
}\r
currentNodeList = RLPReader.toList(parentNodes[i]);\r
\r
if (currentNodeList.length == 17) {\r
if (pathPtr == path.length) {\r
if (keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value)) {\r
return true;\r
} else {\r
return false;\r
}\r
}\r
\r
uint8 nextPathNibble = uint8(path[pathPtr]);\r
if (nextPathNibble > 16) {\r
return false;\r
}\r
nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[nextPathNibble]));\r
pathPtr += 1;\r
} else if (currentNodeList.length == 2) {\r
uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr);\r
if (pathPtr + traversed == path.length) {\r
//leaf node\r
if (keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value)) {\r
return true;\r
} else {\r
return false;\r
}\r
}\r
\r
//extension node\r
if (traversed == 0) {\r
return false;\r
}\r
\r
pathPtr += traversed;\r
nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1]));\r
} else {\r
return false;\r
}\r
}\r
}\r
\r
function _nibblesToTraverse(\r
bytes memory encodedPartialPath,\r
bytes memory path,\r
uint256 pathPtr\r
) private pure returns (uint256) {\r
uint256 len = 0;\r
// encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath\r
// and slicedPath have elements that are each one hex character (1 nibble)\r
bytes memory partialPath = _getNibbleArray(encodedPartialPath);\r
bytes memory slicedPath = new bytes(partialPath.length);\r
\r
// pathPtr counts nibbles in path\r
// partialPath.length is a number of nibbles\r
for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) {\r
bytes1 pathNibble = path[i];\r
slicedPath[i - pathPtr] = pathNibble;\r
}\r
\r
if (keccak256(partialPath) == keccak256(slicedPath)) {\r
len = partialPath.length;\r
} else {\r
len = 0;\r
}\r
return len;\r
}\r
\r
// bytes b must be hp encoded\r
function _getNibbleArray(bytes memory b) internal pure returns (bytes memory) {\r
bytes memory nibbles = "";\r
if (b.length > 0) {\r
uint8 offset;\r
uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b));\r
if (hpNibble == 1 || hpNibble == 3) {\r
nibbles = new bytes(b.length * 2 - 1);\r
bytes1 oddNibble = _getNthNibbleOfBytes(1, b);\r
nibbles[0] = oddNibble;\r
offset = 1;\r
} else {\r
nibbles = new bytes(b.length * 2 - 2);\r
offset = 0;\r
}\r
\r
for (uint256 i = offset; i < nibbles.length; i++) {\r
nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b);\r
}\r
}\r
return nibbles;\r
}\r
\r
function _getNthNibbleOfBytes(uint256 n, bytes memory str) private pure returns (bytes1) {\r
return bytes1(n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10);\r
}\r
}\r
"
},
"src/0.8/interfaces/polygon/lib/RLPReader.sol": {
"content": "/*\r
* @author Hamdi Allam hamdi.allam97@gmail.com\r
* Please reach out with any questions or concerns\r
*/\r
pragma solidity 0.8.25;\r
\r
library RLPReader {\r
uint8 constant STRING_SHORT_START = 0x80;\r
uint8 constant STRING_LONG_START = 0xb8;\r
uint8 constant LIST_SHORT_START = 0xc0;\r
uint8 constant LIST_LONG_START = 0xf8;\r
uint8 constant WORD_SIZE = 32;\r
\r
struct RLPItem {\r
uint256 len;\r
uint256 memPtr;\r
}\r
\r
struct Iterator {\r
RLPItem item; // Item that's being iterated over.\r
uint256 nextPtr; // Position of the next item in the list.\r
}\r
\r
/*\r
* @dev Returns the next element in the iteration. Reverts if it has not next element.\r
* @param self The iterator.\r
* @return The next element in the iteration.\r
*/\r
function next(Iterator memory self) internal pure returns (RLPItem memory) {\r
require(hasNext(self));\r
\r
uint256 ptr = self.nextPtr;\r
uint256 itemLength = _itemLength(ptr);\r
self.nextPtr = ptr + itemLength;\r
\r
return RLPItem(itemLength, ptr);\r
}\r
\r
/*\r
* @dev Returns true if the iteration has more elements.\r
* @param self The iterator.\r
* @return true if the iteration has more elements.\r
*/\r
function hasNext(Iterator memory self) internal pure returns (bool) {\r
RLPItem memory item = self.item;\r
return self.nextPtr < item.memPtr + item.len;\r
}\r
\r
/*\r
* @param item RLP encoded bytes\r
*/\r
function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {\r
uint256 memPtr;\r
assembly {\r
memPtr := add(item, 0x20)\r
}\r
\r
return RLPItem(item.length, memPtr);\r
}\r
\r
/*\r
* @dev Create an iterator. Reverts if item is not a list.\r
* @param self The RLP item.\r
* @return An 'Iterator' over the item.\r
*/\r
function iterator(RLPItem memory self) internal pure returns (Iterator memory) {\r
require(isList(self));\r
\r
uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);\r
return Iterator(self, ptr);\r
}\r
\r
/*\r
* @param item RLP encoded bytes\r
*/\r
function rlpLen(RLPItem memory item) internal pure returns (uint256) {\r
return item.len;\r
}\r
\r
/*\r
* @param item RLP encoded bytes\r
*/\r
function payloadLen(RLPItem memory item) internal pure returns (uint256) {\r
return item.len - _payloadOffset(item.memPtr);\r
}\r
\r
/*\r
* @param item RLP encoded list in bytes\r
*/\r
function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {\r
require(isList(item));\r
\r
uint256 items = numItems(item);\r
RLPItem[] memory result = new RLPItem[](items);\r
\r
uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);\r
uint256 dataLen;\r
for (uint256 i = 0; i < items; i++) {\r
dataLen = _itemLength(memPtr);\r
result[i] = RLPItem(dataLen, memPtr);\r
memPtr = memPtr + dataLen;\r
}\r
\r
return result;\r
}\r
\r
// @return indicator whether encoded payload is a list. negate this function call for isData.\r
function isList(RLPItem memory item) internal pure returns (bool) {\r
if (item.len == 0) return false;\r
\r
uint8 byte0;\r
uint256 memPtr = item.memPtr;\r
assembly {\r
byte0 := byte(0, mload(memPtr))\r
}\r
\r
if (byte0 < LIST_SHORT_START) return false;\r
return true;\r
}\r
\r
/*\r
* @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory.\r
* @return keccak256 hash of RLP encoded bytes.\r
*/\r
function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) {\r
uint256 ptr = item.memPtr;\r
uint256 len = item.len;\r
bytes32 result;\r
assembly {\r
result := keccak256(ptr, len)\r
}\r
return result;\r
}\r
\r
function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) {\r
uint256 offset = _payloadOffset(item.memPtr);\r
uint256 memPtr = item.memPtr + offset;\r
uint256 len = item.len - offset; // data length\r
return (memPtr, len);\r
}\r
\r
/*\r
* @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory.\r
* @return keccak256 hash of the item payload.\r
*/\r
function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) {\r
(uint256 memPtr, uint256 len) = payloadLocation(item);\r
bytes32 result;\r
assembly {\r
result := keccak256(memPtr, len)\r
}\r
return result;\r
}\r
\r
/** RLPItem conversions into data types **/\r
\r
// @returns raw rlp encoding in bytes\r
function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {\r
bytes memory result = new bytes(item.len);\r
if (result.length == 0) return result;\r
\r
uint256 ptr;\r
assembly {\r
ptr := add(0x20, result)\r
}\r
\r
copy(item.memPtr, ptr, item.len);\r
return result;\r
}\r
\r
// any non-zero byte is considered true\r
function toBoolean(RLPItem memory item) internal pure returns (bool) {\r
require(item.len == 1);\r
uint256 result;\r
uint256 memPtr = item.memPtr;\r
assembly {\r
result := byte(0, mload(memPtr))\r
}\r
\r
return result == 0 ? false : true;\r
}\r
\r
function toAddress(RLPItem memory item) internal pure returns (address) {\r
// 1 byte for the length prefix\r
require(item.len == 21);\r
\r
return address(uint160(toUint(item)));\r
}\r
\r
function toUint(RLPItem memory item) internal pure returns (uint256) {\r
require(item.len > 0 && item.len <= 33);\r
\r
uint256 offset = _payloadOffset(item.memPtr);\r
uint256 len = item.len - offset;\r
\r
uint256 result;\r
uint256 memPtr = item.memPtr + offset;\r
assembly {\r
result := mload(memPtr)\r
\r
// shfit to the correct location if neccesary\r
if lt(len, 32) {\r
result := div(result, exp(256, sub(32, len)))\r
}\r
}\r
\r
return result;\r
}\r
\r
// enforces 32 byte length\r
function toUintStrict(RLPItem memory item) internal pure returns (uint256) {\r
// one byte prefix\r
require(item.len == 33);\r
\r
uint256 result;\r
uint256 memPtr = item.memPtr + 1;\r
assembly {\r
result := mload(memPtr)\r
}\r
\r
return result;\r
}\r
\r
function toBytes(RLPItem memory item) internal pure returns (bytes memory) {\r
require(item.len > 0);\r
\r
uint256 offset = _payloadOffset(item.memPtr);\r
uint256 len = item.len - offset; // data length\r
bytes memory result = new bytes(len);\r
\r
uint256 destPtr;\r
assembly {\r
destPtr := add(0x20, result)\r
}\r
\r
copy(item.memPtr + offset, destPtr, len);\r
return result;\r
}\r
\r
/*\r
* Private Helpers\r
*/\r
\r
// @return number of payload items inside an encoded list.\r
function numItems(RLPItem memory item) private pure returns (uint256) {\r
if (item.len == 0) return 0;\r
\r
uint256 count = 0;\r
uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);\r
uint256 endPtr = item.memPtr + item.len;\r
while (currPtr < endPtr) {\r
currPtr = currPtr + _itemLength(currPtr); // skip over an item\r
count++;\r
}\r
\r
return count;\r
}\r
\r
// @return entire rlp item byte length\r
function _itemLength(uint256 memPtr) private pure returns (uint256) {\r
uint256 itemLen;\r
uint256 byte0;\r
assembly {\r
byte0 := byte(0, mload(memPtr))\r
}\r
\r
if (byte0 < STRING_SHORT_START) itemLen = 1;\r
else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1;\r
else if (byte0 < LIST_SHORT_START) {\r
assembly {\r
let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is\r
memPtr := add(memPtr, 1) // skip over the first byte\r
/* 32 byte word size */\r
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len\r
itemLen := add(dataLen, add(byteLen, 1))\r
}\r
} else if (byte0 < LIST_LONG_START) {\r
itemLen = byte0 - LIST_SHORT_START + 1;\r
} else {\r
assembly {\r
let byteLen := sub(byte0, 0xf7)\r
memPtr := add(memPtr, 1)\r
\r
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length\r
itemLen := add(dataLen, add(byteLen, 1))\r
}\r
}\r
\r
return itemLen;\r
}\r
\r
// @return number of bytes until the data\r
function _payloadOffset(uint256 memPtr) private pure returns (uint256) {\r
uint256 byte0;\r
assembly {\r
byte0 := byte(0, mload(memPtr))\r
}\r
\r
if (byte0 < STRING_SHORT_START) return 0;\r
else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1;\r
else if (byte0 < LIST_SHORT_START)\r
// being explicit\r
return byte0 - (STRING_LONG_START - 1) + 1;\r
else return byte0 - (LIST_LONG_START - 1) + 1;\r
}\r
\r
/*\r
* @param src Pointer to source\r
* @param dest Pointer to destination\r
* @param len Amount of memory to copy from the source\r
*/\r
function copy(uint256 src, uint256 dest, uint256 len) private pure {\r
if (len == 0) return;\r
\r
// copy as many word sizes as possible\r
for (; len >= WORD_SIZE; len -= WORD_SIZE) {\r
assembly {\r
mstore(dest, mload(src))\r
}\r
\r
src += WORD_SIZE;\r
dest += WORD_SIZE;\r
}\r
\r
if (len == 0) return;\r
\r
// left over bytes. Mask is used to remove unwanted bytes from the word\r
uint256 mask = 256 ** (WORD_SIZE - len) - 1;\r
\r
assembly {\r
let srcpart := and(mload(src), not(mask)) // zero out src\r
let destpart := and(mload(dest), mask) // retrieve the bytes\r
mstore(dest, or(destpart, srcpart))\r
}\r
}\r
}\r
"
},
"src/0.8/libraries/SafeSend.sol": {
"content": "/**\r
* @authors: [@andreimvp]\r
* @reviewers: [@divyangchauhan, @wadader, @fcanela, @unknownunknown1]\r
* @auditors: []\r
* @bounties: []\r
* SPDX-License-Identifier: MIT\r
*/\r
\r
pragma solidity 0.8.25;\r
\r
interface WethLike {\r
function deposit() external payable;\r
\r
function transfer(address dst, uint256 wad) external;\r
}\r
\r
library SafeSend {\r
function safeSend(address payable _to, uint256 _value, address _wethLike) internal {\r
if (_to.send(_value)) return;\r
\r
WethLike(_wethLike).deposit{value: _value}();\r
WethLike(_wethLike).transfer(_to, _value);\r
}\r
}\r
"
},
"src/0.8/RealitioForeignProxyPolygon.sol": {
"content": "// SPDX-License-Identifier: MIT\r
\r
/**\r
* @authors: [@hbarcelos, @unknownunknown1, @shalzz]\r
* @reviewers: [@MerlinEgalite*, @jaybuidl, @unknownunknown1, @fnanni-0*]\r
* @auditors: []\r
* @bounties: []\r
* @deployments: []\r
*/\r
\r
pragma solidity 0.8.25;\r
\r
import {IDisputeResolver, IArbitrator} from "@kleros/dispute-resolver-interface-contract-0.8/contracts/IDisputeResolver.sol";\r
import {FxBaseRootTunnel} from "./interfaces/polygon/FxBaseRootTunnel.sol";\r
import {IForeignArbitrationProxy, IHomeArbitrationProxy} from "./interfaces/IArbitrationProxies.sol";\r
import {SafeSend} from "./libraries/SafeSend.sol";\r
\r
/**\r
* @title Arbitration proxy for Realitio on Ethereum side (A.K.A. the Foreign Chain).\r
* @dev This contract is meant to be deployed to the Ethereum chains where Kleros is deployed.\r
*/\r
contract RealitioForeignProxyPolygon is IForeignArbitrationProxy, IDisputeResolver, FxBaseRootTunnel {\r
using SafeSend for address payable;\r
/* Constants */\r
\r
uint256 public constant NUMBER_OF_CHOICES_FOR_ARBITRATOR = type(uint256).max; // The number of choices for the arbitrator.\r
uint256 public constant REFUSE_TO_ARBITRATE_REALITIO = type(uint256).max; // Constant that represents "Refuse to rule" in realitio format.\r
uint256 public constant MULTIPLIER_DIVISOR = 10000; // Divisor parameter for multipliers.\r
uint256 public constant META_EVIDENCE_ID = 0; // The ID of the MetaEvidence for disputes.\r
\r
/* Storage */\r
\r
enum Status {\r
None,\r
Requested,\r
Created,\r
Ruled,\r
Relayed,\r
Failed\r
}\r
\r
struct ArbitrationRequest {\r
Status status; // Status of the arbitration.\r
uint248 deposit; // The deposit paid by the requester at the time of the arbitration.\r
uint256 disputeID; // The ID of the dispute in arbitrator contract.\r
uint256 answer; // The answer given by the arbitrator.\r
Round[] rounds; // Tracks each appeal round of a dispute.\r
}\r
\r
struct DisputeDetails {\r
uint256 arbitrationID; // The ID of the arbitration.\r
address requester; // The address of the requester who managed to go through with the arbitration request.\r
}\r
\r
// Round struct stores the contributions made to particular answers.\r
struct Round {\r
mapping(uint256 => uint256) paidFees; // Tracks the fees paid in this round in the form paidFees[answer].\r
mapping(uint256 => bool) hasPaid; // True if the fees for this particular answer have been fully paid in the form hasPaid[answer].\r
mapping(address => mapping(uint256 => uint256)) contributions; // Maps contributors to their contributions for each answer in the form contributions[address][answer].\r
uint256 feeRewards; // Sum of reimbursable appeal fees available to the parties that made contributions to the answer that ultimately wins a dispute.\r
uint256[] fundedAnswers; // Stores the answer choices that are fully funded.\r
}\r
\r
address public immutable wNative; // Address of wrapped version of the chain's native currency. WETH-like.\r
\r
IArbitrator public immutable arbitrator; // The address of the arbitrator. TRUSTED.\r
bytes public arbitratorExtraData; // The extra data used to raise a dispute in the arbitrator.\r
\r
// Multipliers are in basis points.\r
uint256 public immutable winnerMultiplier; // Multiplier for calculating the appeal fee that must be paid for the an
Submitted on: 2025-09-26 14:10:25
Comments
Log in to comment.
No comments yet.