diff --git a/contracts/README.md b/contracts/README.md index 0bf26ae77..609afed66 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -6,11 +6,10 @@ Smart contracts for Kleros v2 Refresh the list of deployed contracts by running `./scripts/generateDeploymentsMarkdown.sh`. -### v2-alpha-1 - #### Chiado - [ArbitrableExample](https://blockscout.com/gnosis/chiado/address/0xc0fcc96BFd78e36550FCaB434A9EE1210B57225b) +- [DisputeResolver](https://blockscout.com/gnosis/chiado/address/0x433eD78895df1df7668C40b3e82d54410331F942) - [ForeignGatewayOnGnosis](https://blockscout.com/gnosis/chiado/address/0x573bcD6ee4aEe152eCC9Cafd2c0820Dc548AF6cC) - [SortitionSumTreeFactory](https://blockscout.com/gnosis/chiado/address/0xc7e3BF90299f6BD9FA7c3703837A9CAbB5743636) - [TokenBridge](https://blockscout.com/gnosis/chiado/address/0xbb3c86f9918C3C1d83668fA84e79E876d147fFf2) @@ -28,10 +27,10 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments #### Arbitrum Goerli - [PNK](https://goerli.arbiscan.io/token/0x4DEeeFD054434bf6721eF39Aa18EfB3fd0D12610/token-transfers) -- [ArbitrableExampleEthFee](https://goerli.arbiscan.io/address/0x1fF31be1924f55804350ADe4945f3B3a6a2e15d2) +- [ArbitrableExampleEthFee](https://goerli.arbiscan.io/address/0x1d533481cCD1402f83Df3D9Ba7496B5e5b602875) - [BlockHashRNG](https://goerli.arbiscan.io/address/0x68eE49dfD9d76f3386257a3D0e0A85c0A5519bBD) - [DisputeKitClassic](https://goerli.arbiscan.io/address/0xcBE3aD699919Cf59efDF715e4B41AF30A0E4c92d) -- [DisputeResolver](https://goerli.arbiscan.io/address/0x3B4edEFd12a467D1C71506ae2eE88828145202b1) +- [DisputeResolver](https://goerli.arbiscan.io/address/0xF6652c10c4D3f5bA6066254B78c57A468d9b9606) - [HomeGatewayToGnosis](https://goerli.arbiscan.io/address/0xD60CD2151e118Dd796efcb1ceFFcF892226F9b3a) - [KlerosCore](https://goerli.arbiscan.io/address/0xA429667Abb1A6c530BAd1083df4C69FBce86D696) - [PolicyRegistry](https://goerli.arbiscan.io/address/0xED503aBA65B28D81444294D1eAa5d84CeFdC2C58) diff --git a/contracts/deploy/00-home-chain-arbitrable.ts b/contracts/deploy/00-home-chain-arbitrable.ts index 8b0724e86..1cf94f5f5 100644 --- a/contracts/deploy/00-home-chain-arbitrable.ts +++ b/contracts/deploy/00-home-chain-arbitrable.ts @@ -1,5 +1,6 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; +import disputeTemplate from "../../kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json"; enum HomeChains { ARBITRUM_ONE = 42161, @@ -21,12 +22,13 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) await deploy("ArbitrableExample", { from: deployer, - args: [ - klerosCore.address, - 0, - "https://cloudflare-ipfs.com/ipfs/bafkreifteme6tusnjwyzajk75fyvzdmtyycxctf7yhfijb6rfigz3n4lvq", - weth.address, - ], + args: [klerosCore.address, disputeTemplate, weth.address], + log: true, + }); + + await deploy("DisputeResolver", { + from: deployer, + args: [klerosCore.address], log: true, }); }; diff --git a/contracts/deploy/01-foreign-gateway-on-gnosis.ts b/contracts/deploy/01-foreign-gateway-on-gnosis.ts index dd7390489..1c0670516 100644 --- a/contracts/deploy/01-foreign-gateway-on-gnosis.ts +++ b/contracts/deploy/01-foreign-gateway-on-gnosis.ts @@ -2,6 +2,7 @@ import { parseUnits } from "ethers/lib/utils"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; import getContractAddress from "../deploy-helpers/getContractAddress"; +import { KlerosCore__factory } from "../typechain-types"; enum ForeignChains { GNOSIS_MAINNET = 100, @@ -49,13 +50,13 @@ const deployForeignGateway: DeployFunction = async (hre: HardhatRuntimeEnvironme }); // TODO: disable the gateway until fully initialized with the correct fees OR allow disputeCreators to add funds again if necessary. - await execute( - "ForeignGatewayOnGnosis", - { from: deployer, log: true }, - "changeCourtJurorFee", - 0, - ethers.utils.parseEther("0.00001") - ); + const coreDeployment = await hre.companionNetworks.home.deployments.get("KlerosCore"); + const core = await KlerosCore__factory.connect(coreDeployment.address, homeChainProvider); + // TODO: set up the correct fees for the FORKING_COURT + const courtId = await core.GENERAL_COURT(); + const fee = (await core.courts(courtId)).feeForJuror; + await execute("ForeignGatewayOnGnosis", { from: deployer, log: true }, "changeCourtJurorFee", courtId, fee); + // TODO: set up the correct fees for the lower courts }; deployForeignGateway.tags = ["ForeignGatewayOnGnosis"]; diff --git a/contracts/deploy/03-vea-mock.ts b/contracts/deploy/03-vea-mock.ts index 23c90104a..1a5635ef1 100644 --- a/contracts/deploy/03-vea-mock.ts +++ b/contracts/deploy/03-vea-mock.ts @@ -1,6 +1,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; import getContractAddress from "../deploy-helpers/getContractAddress"; +import disputeTemplate from "../../kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json"; const HARDHAT_NETWORK = 31337; @@ -51,11 +52,9 @@ const deployHomeGateway: DeployFunction = async (hre: HardhatRuntimeEnvironment) ethers.BigNumber.from(10).pow(17) ); - const metaEvidenceUri = `https://raw.githubusercontent.com/kleros/kleros-v2/master/contracts/deployments/goerli/MetaEvidence_ArbitrableExample.json`; - await deploy("ArbitrableExample", { from: deployer, - args: [foreignGateway.address, 0, metaEvidenceUri, ethers.constants.AddressZero], + args: [foreignGateway.address, disputeTemplate, ethers.constants.AddressZero], log: true, }); }; diff --git a/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts b/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts index a66f1f6c4..e2a446f0a 100644 --- a/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts +++ b/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts @@ -1,6 +1,7 @@ import { parseUnits, parseEther } from "ethers/lib/utils"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; +import disputeTemplate from "../../kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json"; enum ForeignChains { GNOSIS_MAINNET = 100, @@ -98,29 +99,11 @@ const deployKlerosLiquid: DeployFunction = async (hre: HardhatRuntimeEnvironment // const xKlerosLiquidV2 = await deployments.get("xKlerosLiquidV2"); await deploy("ArbitrableExample", { from: deployer, - args: [ - xKlerosLiquidV2.address, - 0, - "/ipfs/bafkreifteme6tusnjwyzajk75fyvzdmtyycxctf7yhfijb6rfigz3n4lvq", // PoH registration - weth.address, - ], + args: [xKlerosLiquidV2.address, 0, disputeTemplate, weth.address], log: true, maxFeePerGas: ONE_GWEI, maxPriorityFeePerGas: ONE_GWEI, }); - - await execute( - "ArbitrableExample", - { - from: deployer, - log: true, - maxFeePerGas: ONE_GWEI, - maxPriorityFeePerGas: ONE_GWEI, - }, - "changeMetaEvidence", - 1, - "/ipfs/bafkreibiuxwejijwg4pxco7fqszawcwmpt26itbdxeqgh7cvpeuwtmlhoa" // PoH clearing - ); }; // TODO: mock deployment on the hardhat network diff --git a/contracts/deploy/04-resolver-to-v2-gnosis.ts b/contracts/deploy/04-resolver-to-v2-gnosis.ts new file mode 100644 index 000000000..ceed24413 --- /dev/null +++ b/contracts/deploy/04-resolver-to-v2-gnosis.ts @@ -0,0 +1,39 @@ +import { parseUnits } from "ethers/lib/utils"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { DeployFunction } from "hardhat-deploy/types"; + +enum ForeignChains { + GNOSIS_MAINNET = 100, + GNOSIS_CHIADO = 10200, + HARDHAT = 31337, +} + +const ONE_GWEI = parseUnits("1", "gwei"); + +const deployResolver: DeployFunction = async (hre: HardhatRuntimeEnvironment) => { + const { deployments, getNamedAccounts, getChainId } = hre; + const { deploy } = deployments; + + // fallback to hardhat node signers on local network + const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address; + const chainId = Number(await getChainId()); + console.log("Deploying to chainId %s with deployer %s", chainId, deployer); + + const foreignGateway = await deployments.get("ForeignGatewayOnGnosis"); + + await deploy("DisputeResolver", { + from: deployer, + args: [foreignGateway.address], + log: true, + maxFeePerGas: ONE_GWEI, + maxPriorityFeePerGas: ONE_GWEI, + }); +}; + +deployResolver.tags = ["ResolverOnGnosis"]; +deployResolver.skip = async ({ getChainId }) => { + const chainId = Number(await getChainId()); + return !ForeignChains[chainId]; +}; + +export default deployResolver; diff --git a/contracts/deployments/arbitrumGoerli/DisputeResolver.json b/contracts/deployments/arbitrumGoerli/DisputeResolver.json index 341ae2368..b01058058 100644 --- a/contracts/deployments/arbitrumGoerli/DisputeResolver.json +++ b/contracts/deployments/arbitrumGoerli/DisputeResolver.json @@ -1,10 +1,10 @@ { - "address": "0x3B4edEFd12a467D1C71506ae2eE88828145202b1", + "address": "0xF6652c10c4D3f5bA6066254B78c57A468d9b9606", "abi": [ { "inputs": [ { - "internalType": "contract IArbitrator", + "internalType": "contract IArbitratorV2", "name": "_arbitrator", "type": "address" } @@ -17,30 +17,85 @@ "inputs": [ { "indexed": true, - "internalType": "contract IArbitrator", + "internalType": "contract IArbitratorV2", "name": "_arbitrator", "type": "address" }, + { + "indexed": false, + "internalType": "uint256", + "name": "_arbitrableChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "_arbitrable", + "type": "address" + }, { "indexed": true, "internalType": "uint256", - "name": "_disputeID", + "name": "_arbitrableDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_externalDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_templateId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "_templateUri", + "type": "string" + } + ], + "name": "CrossChainDisputeRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_arbitrableDisputeID", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "_metaEvidenceID", + "name": "_externalDisputeID", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "_evidenceGroupID", + "name": "_templateId", "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "_templateUri", + "type": "string" } ], - "name": "Dispute", + "name": "DisputeRequest", "type": "event" }, { @@ -49,17 +104,23 @@ { "indexed": true, "internalType": "uint256", - "name": "_metaEvidenceID", + "name": "_templateId", "type": "uint256" }, + { + "indexed": true, + "internalType": "string", + "name": "_templateTag", + "type": "string" + }, { "indexed": false, "internalType": "string", - "name": "_evidence", + "name": "data", "type": "string" } ], - "name": "MetaEvidence", + "name": "DisputeTemplate", "type": "event" }, { @@ -67,7 +128,7 @@ "inputs": [ { "indexed": true, - "internalType": "contract IArbitrator", + "internalType": "contract IArbitratorV2", "name": "_arbitrator", "type": "address" }, @@ -92,7 +153,7 @@ "name": "arbitrator", "outputs": [ { - "internalType": "contract IArbitrator", + "internalType": "contract IArbitratorV2", "name": "", "type": "address" } @@ -100,6 +161,80 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "arbitratorDisputeIDToLocalID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + } + ], + "name": "changeArbitrator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_arbitratorExtraData", + "type": "bytes" + }, + { + "internalType": "string", + "name": "_disputeTemplate", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_numberOfRulingOptions", + "type": "uint256" + } + ], + "name": "createDisputeForTemplate", + "outputs": [ + { + "internalType": "uint256", + "name": "disputeID", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, { "inputs": [ { @@ -109,7 +244,7 @@ }, { "internalType": "string", - "name": "_metaevidenceURI", + "name": "_disputeTemplateUri", "type": "string" }, { @@ -118,7 +253,7 @@ "type": "uint256" } ], - "name": "createDispute", + "name": "createDisputeForTemplateUri", "outputs": [ { "internalType": "uint256", @@ -164,19 +299,13 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "externalIDtoLocalID", + "inputs": [], + "name": "governor", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -201,70 +330,101 @@ "type": "function" } ], - "transactionHash": "0xc98034a500dfe7e53940c6c8f65ac6788f383393efbd9480ff71e47a6eabb72b", + "transactionHash": "0xed9f2c713fef809dc6e57ab0d647637b434c4a66bd3299d19112056cdf26d4f8", "receipt": { "to": null, "from": "0xF50E77f2A2B6138D16c6c7511562E5C33c4B15A3", - "contractAddress": "0x3B4edEFd12a467D1C71506ae2eE88828145202b1", + "contractAddress": "0xF6652c10c4D3f5bA6066254B78c57A468d9b9606", "transactionIndex": 1, - "gasUsed": "592785", + "gasUsed": "2186354", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb603106426692421641ace35dc368185179b479a93e1b029a7b50c68223e8aee", - "transactionHash": "0xc98034a500dfe7e53940c6c8f65ac6788f383393efbd9480ff71e47a6eabb72b", + "blockHash": "0x8b1d2f7d43ce621f44fbda339212d9c591b32e22c96a93dba151914ea4e616f1", + "transactionHash": "0xed9f2c713fef809dc6e57ab0d647637b434c4a66bd3299d19112056cdf26d4f8", "logs": [], - "blockNumber": 25602158, - "cumulativeGasUsed": "592785", + "blockNumber": 25952527, + "cumulativeGasUsed": "2186354", "status": 1, "byzantium": true }, "args": [ "0xA429667Abb1A6c530BAd1083df4C69FBce86D696" ], - "numDeployments": 2, - "solcInputHash": "e839c2860a2bc794c3b8ff7bcdbfe1cc", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IArbitrator\",\"name\":\"_arbitrator\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitrator\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_disputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_metaEvidenceID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_evidenceGroupID\",\"type\":\"uint256\"}],\"name\":\"Dispute\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_metaEvidenceID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_evidence\",\"type\":\"string\"}],\"name\":\"MetaEvidence\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitrator\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_disputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"Ruling\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"arbitrator\",\"outputs\":[{\"internalType\":\"contract IArbitrator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_metaevidenceURI\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"_numberOfRulingOptions\",\"type\":\"uint256\"}],\"name\":\"createDispute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"disputeID\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"disputes\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"isRuled\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"ruling\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numberOfRulingOptions\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"externalIDtoLocalID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"Dispute(address,uint256,uint256,uint256)\":{\"details\":\"To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\",\"params\":{\"_arbitrator\":\"The arbitrator of the contract.\",\"_disputeID\":\"ID of the dispute in the Arbitrator contract.\",\"_evidenceGroupID\":\"Unique identifier of the evidence group that is linked to this dispute.\",\"_metaEvidenceID\":\"Unique identifier of meta-evidence.\"}},\"MetaEvidence(uint256,string)\":{\"details\":\"To be emitted when meta-evidence is submitted.\",\"params\":{\"_evidence\":\"IPFS path to metaevidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/metaevidence.json'\",\"_metaEvidenceID\":\"Unique identifier of meta-evidence.\"}},\"Ruling(address,uint256,uint256)\":{\"details\":\"To be raised when a ruling is given.\",\"params\":{\"_arbitrator\":\"The arbitrator giving the ruling.\",\"_disputeID\":\"ID of the dispute in the Arbitrator contract.\",\"_ruling\":\"The ruling which was given.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor\",\"params\":{\"_arbitrator\":\"Target global arbitrator for any disputes.\"}},\"createDispute(bytes,string,uint256)\":{\"details\":\"TRUSTED. Calls createDispute function of the specified arbitrator to create a dispute. Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\",\"params\":{\"_arbitratorExtraData\":\"Extra data for the arbitrator of the dispute.\",\"_metaevidenceURI\":\"Link to metaevidence of the dispute.\",\"_numberOfRulingOptions\":\"Number of ruling options.\"},\"returns\":{\"disputeID\":\"Dispute id (on arbitrator side) of the created dispute.\"}},\"rule(uint256,uint256)\":{\"details\":\"To be called by the arbitrator of the dispute, to declare the winning ruling.\",\"params\":{\"_externalDisputeID\":\"ID of the dispute in arbitrator contract.\",\"_ruling\":\"The ruling choice of the arbitration.\"}}},\"title\":\"DisputeResolver DisputeResolver contract adapted for V2 https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitration/arbitrables/DisputeResolver.sol\":\"DisputeResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"src/arbitration/IArbitrable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"./IArbitrator.sol\\\";\\n\\n/// @title IArbitrable\\n/// Arbitrable interface. Note that this interface follows the ERC-792 standard.\\n/// When developing arbitrable contracts, we need to:\\n/// - Define the action taken when a ruling is received by the contract.\\n/// - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData);\\ninterface IArbitrable {\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrator The arbitrator giving the ruling.\\n /// @param _disputeID ID of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitrator indexed _arbitrator, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Give a ruling for a dispute. Must be called by the arbitrator.\\n /// The purpose of this function is to ensure that the address calling it has the right to rule on the contract.\\n /// @param _disputeID ID of the dispute in the Arbitrator contract.\\n /// @param _ruling Ruling given by the arbitrator. Note that 0 is reserved for \\\"Not able/wanting to make a decision\\\".\\n function rule(uint256 _disputeID, uint256 _ruling) external;\\n}\\n\",\"keccak256\":\"0x2a5363c37d33749f6b53c288f6d1538f013c6efbb3df86e63eceaa8163a6b212\",\"license\":\"MIT\"},\"src/arbitration/IArbitrator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"./IArbitrable.sol\\\";\\n\\n/// @title Arbitrator\\n/// Arbitrator interface that implements the new arbitration standard.\\n/// Unlike the ERC-792 this standard doesn't have anything related to appeals, so each arbitrator can implement an appeal system that suits it the most.\\n/// When developing arbitrator contracts we need to:\\n/// - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes).\\n/// - Define the functions for cost display (arbitrationCost).\\n/// - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling).\\ninterface IArbitrator {\\n /// @dev To be emitted when a dispute is created.\\n /// @param _disputeID ID of the dispute.\\n /// @param _arbitrable The contract which created the dispute.\\n event DisputeCreation(uint256 indexed _disputeID, IArbitrable indexed _arbitrable);\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrable The arbitrable receiving the ruling.\\n /// @param _disputeID ID of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitrable indexed _arbitrable, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Create a dispute. Must be called by the arbitrable contract.\\n /// Must pay at least arbitrationCost(_extraData).\\n /// @param _choices Amount of choices the arbitrator can make in this dispute.\\n /// @param _extraData Can be used to give additional info on the dispute to be created.\\n /// @return disputeID ID of the dispute created.\\n function createDispute(uint256 _choices, bytes calldata _extraData) external payable returns (uint256 disputeID);\\n\\n /// @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.\\n /// @param _extraData Can be used to give additional info on the dispute to be created.\\n /// @return cost Required cost of arbitration.\\n function arbitrationCost(bytes calldata _extraData) external view returns (uint256 cost);\\n}\\n\",\"keccak256\":\"0x8028f7d6a0fe07687f975fc51c9f889083ae1a409a134e8017a044701310948f\",\"license\":\"MIT\"},\"src/arbitration/arbitrables/DisputeResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@ferittuncer, @unknownunknown1]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n\\nimport \\\"../IArbitrable.sol\\\";\\nimport \\\"../../evidence/IMetaEvidence.sol\\\";\\n\\npragma solidity 0.8.18;\\n\\n/// @title DisputeResolver\\n/// DisputeResolver contract adapted for V2 https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.\\ncontract DisputeResolver is IArbitrable, IMetaEvidence {\\n struct DisputeStruct {\\n bytes arbitratorExtraData; // Extra data for the dispute.\\n bool isRuled; // True if the dispute has been ruled.\\n uint256 ruling; // Ruling given to the dispute.\\n uint256 numberOfRulingOptions; // The number of choices the arbitrator can give.\\n }\\n\\n IArbitrator public immutable arbitrator; // Arbitrator is set in constructor and never changed.\\n\\n DisputeStruct[] public disputes; // Local disputes.\\n mapping(uint256 => uint256) public externalIDtoLocalID; // Maps external (arbitrator side) dispute IDs to local dispute IDs.\\n\\n /// @dev Constructor\\n /// @param _arbitrator Target global arbitrator for any disputes.\\n constructor(IArbitrator _arbitrator) {\\n arbitrator = _arbitrator;\\n }\\n\\n /// @dev TRUSTED. Calls createDispute function of the specified arbitrator to create a dispute.\\n /// Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator of the dispute.\\n /// @param _metaevidenceURI Link to metaevidence of the dispute.\\n /// @param _numberOfRulingOptions Number of ruling options.\\n /// @return disputeID Dispute id (on arbitrator side) of the created dispute.\\n function createDispute(\\n bytes calldata _arbitratorExtraData,\\n string calldata _metaevidenceURI,\\n uint256 _numberOfRulingOptions\\n ) external payable returns (uint256 disputeID) {\\n require(_numberOfRulingOptions > 1, \\\"Should be at least 2 ruling options.\\\");\\n\\n disputeID = arbitrator.createDispute{value: msg.value}(_numberOfRulingOptions, _arbitratorExtraData);\\n uint256 localDisputeID = disputes.length;\\n disputes.push(\\n DisputeStruct({\\n arbitratorExtraData: _arbitratorExtraData,\\n isRuled: false,\\n ruling: 0,\\n numberOfRulingOptions: _numberOfRulingOptions\\n })\\n );\\n\\n externalIDtoLocalID[disputeID] = localDisputeID;\\n\\n emit MetaEvidence(localDisputeID, _metaevidenceURI);\\n emit Dispute(arbitrator, disputeID, localDisputeID, localDisputeID);\\n }\\n\\n /// @dev To be called by the arbitrator of the dispute, to declare the winning ruling.\\n /// @param _externalDisputeID ID of the dispute in arbitrator contract.\\n /// @param _ruling The ruling choice of the arbitration.\\n function rule(uint256 _externalDisputeID, uint256 _ruling) external override {\\n uint256 localDisputeID = externalIDtoLocalID[_externalDisputeID];\\n DisputeStruct storage dispute = disputes[localDisputeID];\\n require(msg.sender == address(arbitrator), \\\"Only the arbitrator can execute this.\\\");\\n require(_ruling <= dispute.numberOfRulingOptions, \\\"Invalid ruling.\\\");\\n require(!dispute.isRuled, \\\"This dispute has been ruled already.\\\");\\n\\n dispute.isRuled = true;\\n dispute.ruling = _ruling;\\n\\n emit Ruling(IArbitrator(msg.sender), _externalDisputeID, dispute.ruling);\\n }\\n}\\n\",\"keccak256\":\"0x3d564c243e064e8172ff3768ee5ece0b004c33a19bb92766f1c2470ec341d098\",\"license\":\"MIT\"},\"src/evidence/IMetaEvidence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"../arbitration/IArbitrator.sol\\\";\\n\\n/// @title IMetaEvidence\\n/// ERC-1497: Evidence Standard excluding evidence emission as it will be handled by the arbitrator.\\ninterface IMetaEvidence {\\n /// @dev To be emitted when meta-evidence is submitted.\\n /// @param _metaEvidenceID Unique identifier of meta-evidence.\\n /// @param _evidence IPFS path to metaevidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/metaevidence.json'\\n event MetaEvidence(uint256 indexed _metaEvidenceID, string _evidence);\\n\\n /// @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _disputeID ID of the dispute in the Arbitrator contract.\\n /// @param _metaEvidenceID Unique identifier of meta-evidence.\\n /// @param _evidenceGroupID Unique identifier of the evidence group that is linked to this dispute.\\n event Dispute(\\n IArbitrator indexed _arbitrator,\\n uint256 indexed _disputeID,\\n uint256 _metaEvidenceID,\\n uint256 _evidenceGroupID\\n );\\n}\\n\",\"keccak256\":\"0x4d985d8a86445a9556917c495b14c4074e33f4495e3674bb23b4448296579de7\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b50604051610a5d380380610a5d83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516109be61009f6000396000818160bc0152818161017c0152818161044c01526105df01526109be6000f3fe60806040526004361061004a5760003560e01c8063311a6c561461004f578063564a565d146100715780636cc6cde1146100aa578063c21ae061146100f6578063e2c7981b14610131575b600080fd5b34801561005b57600080fd5b5061006f61006a366004610635565b610144565b005b34801561007d57600080fd5b5061009161008c366004610657565b610309565b6040516100a19493929190610670565b60405180910390f35b3480156100b657600080fd5b506100de7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a1565b34801561010257600080fd5b50610123610111366004610657565b60016020526000908152604090205481565b6040519081526020016100a1565b61012361013f36600461071e565b6103d7565b600082815260016020526040812054815490919081908390811061016a5761016a610792565b906000526020600020906004020190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316336001600160a01b03161461020e5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79207468652061726269747261746f722063616e2065786563757465206044820152643a3434b99760d91b60648201526084015b60405180910390fd5b80600301548311156102545760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b210393ab634b7339760891b6044820152606401610205565b600181015460ff16156102b55760405162461bcd60e51b8152602060048201526024808201527f54686973206469737075746520686173206265656e2072756c656420616c726560448201526330b23c9760e11b6064820152608401610205565b6001818101805460ff1916909117905560028101839055604051838152849033907f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769060200160405180910390a350505050565b6000818154811061031957600080fd5b906000526020600020906004020160009150905080600001805461033c906107a8565b80601f0160208091040260200160405190810160405280929190818152602001828054610368906107a8565b80156103b55780601f1061038a576101008083540402835291602001916103b5565b820191906000526020600020905b81548152906001019060200180831161039857829003601f168201915b5050505060018301546002840154600390940154929360ff9091169290915084565b6000600182116104355760405162461bcd60e51b8152602060048201526024808201527f53686f756c64206265206174206c6561737420322072756c696e67206f70746960448201526337b7399760e11b6064820152608401610205565b60405163c13517e160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c13517e19034906104879086908b908b9060040161080b565b60206040518083038185885af11580156104a5573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906104ca919061082e565b600080546040805160a06020601f8c018190040282018101909252608081018a8152949550919382918b908b908190850183828082843760009201829052509385525050506020808301829052604083018290526060909201879052835460018101855593815220815191926004020190819061054790826108ac565b506020828101516001838101805460ff191692151592909217909155604080850151600285015560609094015160039093019290925560008581529190528190208290555181907f61606860eb6c87306811e2695215385101daab53bd6ab4e9f9049aead9363c7d906105bd908890889061096c565b60405180910390a2604080518281526020810183905283916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016917f74baab670a4015ab2f1b467c5252a96141a2573f2908e58a92081e80d3cfde3d910160405180910390a35095945050505050565b6000806040838503121561064857600080fd5b50508035926020909101359150565b60006020828403121561066957600080fd5b5035919050565b608081526000855180608084015260005b8181101561069e57602081890181015160a0868401015201610681565b50600060a0828501015260a0601f19601f830116840101915050841515602083015283604083015282606083015295945050505050565b60008083601f8401126106e757600080fd5b50813567ffffffffffffffff8111156106ff57600080fd5b60208301915083602082850101111561071757600080fd5b9250929050565b60008060008060006060868803121561073657600080fd5b853567ffffffffffffffff8082111561074e57600080fd5b61075a89838a016106d5565b9097509550602088013591508082111561077357600080fd5b50610780888289016106d5565b96999598509660400135949350505050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806107bc57607f821691505b6020821081036107dc57634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8381526040602082015260006108256040830184866107e2565b95945050505050565b60006020828403121561084057600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b601f8211156108a757600081815260208120601f850160051c810160208610156108845750805b601f850160051c820191505b818110156108a357828155600101610890565b5050505b505050565b815167ffffffffffffffff8111156108c6576108c6610847565b6108da816108d484546107a8565b8461085d565b602080601f83116001811461090f57600084156108f75750858301515b600019600386901b1c1916600185901b1785556108a3565b600085815260208120601f198616915b8281101561093e5788860151825594840194600190910190840161091f565b508582101561095c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020815260006109806020830184866107e2565b94935050505056fea26469706673582212208e7d47ef8d6b22a035f41afcc5f56e22a79524eb3c710b3d6299740721da8b3d64736f6c63430008120033", - "deployedBytecode": "0x60806040526004361061004a5760003560e01c8063311a6c561461004f578063564a565d146100715780636cc6cde1146100aa578063c21ae061146100f6578063e2c7981b14610131575b600080fd5b34801561005b57600080fd5b5061006f61006a366004610635565b610144565b005b34801561007d57600080fd5b5061009161008c366004610657565b610309565b6040516100a19493929190610670565b60405180910390f35b3480156100b657600080fd5b506100de7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a1565b34801561010257600080fd5b50610123610111366004610657565b60016020526000908152604090205481565b6040519081526020016100a1565b61012361013f36600461071e565b6103d7565b600082815260016020526040812054815490919081908390811061016a5761016a610792565b906000526020600020906004020190507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316336001600160a01b03161461020e5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79207468652061726269747261746f722063616e2065786563757465206044820152643a3434b99760d91b60648201526084015b60405180910390fd5b80600301548311156102545760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b210393ab634b7339760891b6044820152606401610205565b600181015460ff16156102b55760405162461bcd60e51b8152602060048201526024808201527f54686973206469737075746520686173206265656e2072756c656420616c726560448201526330b23c9760e11b6064820152608401610205565b6001818101805460ff1916909117905560028101839055604051838152849033907f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769060200160405180910390a350505050565b6000818154811061031957600080fd5b906000526020600020906004020160009150905080600001805461033c906107a8565b80601f0160208091040260200160405190810160405280929190818152602001828054610368906107a8565b80156103b55780601f1061038a576101008083540402835291602001916103b5565b820191906000526020600020905b81548152906001019060200180831161039857829003601f168201915b5050505060018301546002840154600390940154929360ff9091169290915084565b6000600182116104355760405162461bcd60e51b8152602060048201526024808201527f53686f756c64206265206174206c6561737420322072756c696e67206f70746960448201526337b7399760e11b6064820152608401610205565b60405163c13517e160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c13517e19034906104879086908b908b9060040161080b565b60206040518083038185885af11580156104a5573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906104ca919061082e565b600080546040805160a06020601f8c018190040282018101909252608081018a8152949550919382918b908b908190850183828082843760009201829052509385525050506020808301829052604083018290526060909201879052835460018101855593815220815191926004020190819061054790826108ac565b506020828101516001838101805460ff191692151592909217909155604080850151600285015560609094015160039093019290925560008581529190528190208290555181907f61606860eb6c87306811e2695215385101daab53bd6ab4e9f9049aead9363c7d906105bd908890889061096c565b60405180910390a2604080518281526020810183905283916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016917f74baab670a4015ab2f1b467c5252a96141a2573f2908e58a92081e80d3cfde3d910160405180910390a35095945050505050565b6000806040838503121561064857600080fd5b50508035926020909101359150565b60006020828403121561066957600080fd5b5035919050565b608081526000855180608084015260005b8181101561069e57602081890181015160a0868401015201610681565b50600060a0828501015260a0601f19601f830116840101915050841515602083015283604083015282606083015295945050505050565b60008083601f8401126106e757600080fd5b50813567ffffffffffffffff8111156106ff57600080fd5b60208301915083602082850101111561071757600080fd5b9250929050565b60008060008060006060868803121561073657600080fd5b853567ffffffffffffffff8082111561074e57600080fd5b61075a89838a016106d5565b9097509550602088013591508082111561077357600080fd5b50610780888289016106d5565b96999598509660400135949350505050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806107bc57607f821691505b6020821081036107dc57634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8381526040602082015260006108256040830184866107e2565b95945050505050565b60006020828403121561084057600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b601f8211156108a757600081815260208120601f850160051c810160208610156108845750805b601f850160051c820191505b818110156108a357828155600101610890565b5050505b505050565b815167ffffffffffffffff8111156108c6576108c6610847565b6108da816108d484546107a8565b8461085d565b602080601f83116001811461090f57600084156108f75750858301515b600019600386901b1c1916600185901b1785556108a3565b600085815260208120601f198616915b8281101561093e5788860151825594840194600190910190840161091f565b508582101561095c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020815260006109806020830184866107e2565b94935050505056fea26469706673582212208e7d47ef8d6b22a035f41afcc5f56e22a79524eb3c710b3d6299740721da8b3d64736f6c63430008120033", + "numDeployments": 3, + "solcInputHash": "c6054c8267f7fff860ff9e6cbf28bb9e", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_arbitrableChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_arbitrable\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_arbitrableDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_templateId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_templateUri\",\"type\":\"string\"}],\"name\":\"CrossChainDisputeRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_arbitrableDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_templateId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_templateUri\",\"type\":\"string\"}],\"name\":\"DisputeRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_templateId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"_templateTag\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"data\",\"type\":\"string\"}],\"name\":\"DisputeTemplate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_disputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"Ruling\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"arbitrator\",\"outputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"arbitratorDisputeIDToLocalID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"}],\"name\":\"changeArbitrator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_disputeTemplate\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"_numberOfRulingOptions\",\"type\":\"uint256\"}],\"name\":\"createDisputeForTemplate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"disputeID\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_disputeTemplateUri\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"_numberOfRulingOptions\",\"type\":\"uint256\"}],\"name\":\"createDisputeForTemplateUri\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"disputeID\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"disputes\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"isRuled\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"ruling\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numberOfRulingOptions\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"CrossChainDisputeRequest(address,uint256,address,uint256,uint256,uint256,string)\":{\"details\":\"To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\",\"params\":{\"_arbitrable\":\"The address of the Arbitrable contract.\",\"_arbitrableChainId\":\"The chain identifier where the Arbitrable contract is deployed.\",\"_arbitrableDisputeID\":\"The identifier of the dispute in the Arbitrable contract.\",\"_arbitrator\":\"The arbitrator of the contract.\",\"_externalDisputeID\":\"An identifier created outside Kleros by the protocol requesting arbitration.\",\"_templateId\":\"The identifier of the dispute template. Should not be used with _templateUri.\",\"_templateUri\":\"IPFS path to the dispute template starting with '/ipfs/'. Should not be used with _templateId.\"}},\"DisputeRequest(address,uint256,uint256,uint256,string)\":{\"details\":\"To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\",\"params\":{\"_arbitrableDisputeID\":\"The identifier of the dispute in the Arbitrable contract.\",\"_arbitrator\":\"The arbitrator of the contract.\",\"_externalDisputeID\":\"An identifier created outside Kleros by the protocol requesting arbitration.\",\"_templateId\":\"The identifier of the dispute template. Should not be used with _templateUri.\",\"_templateUri\":\"The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId.\"}},\"DisputeTemplate(uint256,string,string)\":{\"details\":\"To be emitted when a new dispute template is created.\",\"params\":{\"_templateId\":\"The identifier of the dispute template.\",\"_templateTag\":\"An optional tag for the dispute template, such as \\\"registration\\\" or \\\"removal\\\".\",\"data\":\"The template data.\"}},\"Ruling(address,uint256,uint256)\":{\"details\":\"To be raised when a ruling is given.\",\"params\":{\"_arbitrator\":\"The arbitrator giving the ruling.\",\"_disputeID\":\"The identifier of the dispute in the Arbitrator contract.\",\"_ruling\":\"The ruling which was given.\"}}},\"kind\":\"dev\",\"methods\":{\"changeGovernor(address)\":{\"details\":\"Changes the governor.\",\"params\":{\"_governor\":\"The address of the new governor.\"}},\"constructor\":{\"details\":\"Constructor\",\"params\":{\"_arbitrator\":\"Target global arbitrator for any disputes.\"}},\"createDisputeForTemplate(bytes,string,uint256)\":{\"details\":\"Calls createDispute function of the specified arbitrator to create a dispute. Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\",\"params\":{\"_arbitratorExtraData\":\"Extra data for the arbitrator of the dispute.\",\"_disputeTemplate\":\"Dispute template.\",\"_numberOfRulingOptions\":\"Number of ruling options.\"},\"returns\":{\"disputeID\":\"Dispute id (on arbitrator side) of the created dispute.\"}},\"createDisputeForTemplateUri(bytes,string,uint256)\":{\"details\":\"Calls createDispute function of the specified arbitrator to create a dispute. Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\",\"params\":{\"_arbitratorExtraData\":\"Extra data for the arbitrator of the dispute.\",\"_disputeTemplateUri\":\"The URI to the dispute template. For example on IPFS: starting with '/ipfs/'.\",\"_numberOfRulingOptions\":\"Number of ruling options.\"},\"returns\":{\"disputeID\":\"Dispute id (on arbitrator side) of the created dispute.\"}},\"rule(uint256,uint256)\":{\"details\":\"To be called by the arbitrator of the dispute, to declare the winning ruling.\",\"params\":{\"_externalDisputeID\":\"ID of the dispute in arbitrator contract.\",\"_ruling\":\"The ruling choice of the arbitration.\"}}},\"title\":\"DisputeResolver DisputeResolver contract adapted for V2 from https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitration/arbitrables/DisputeResolver.sol\":\"DisputeResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"src/arbitration/IArbitrableV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"./IArbitratorV2.sol\\\";\\n\\n/// @title IArbitrableV2\\n/// @notice Arbitrable interface.\\n/// When developing arbitrable contracts, we need to:\\n/// - Define the action taken when a ruling is received by the contract.\\n/// - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData);\\ninterface IArbitrableV2 {\\n /// @dev To be emitted when a new dispute template is created.\\n /// @param _templateId The identifier of the dispute template.\\n /// @param _templateTag An optional tag for the dispute template, such as \\\"registration\\\" or \\\"removal\\\".\\n /// @param data The template data.\\n event DisputeTemplate(uint256 indexed _templateId, string indexed _templateTag, string data);\\n\\n /// @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitrableDisputeID The identifier of the dispute in the Arbitrable contract.\\n /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration.\\n /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri.\\n /// @param _templateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId.\\n event DisputeRequest(\\n IArbitratorV2 indexed _arbitrator,\\n uint256 indexed _arbitrableDisputeID,\\n uint256 _externalDisputeID,\\n uint256 _templateId,\\n string _templateUri\\n );\\n\\n /// @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitrableChainId The chain identifier where the Arbitrable contract is deployed.\\n /// @param _arbitrable The address of the Arbitrable contract.\\n /// @param _arbitrableDisputeID The identifier of the dispute in the Arbitrable contract.\\n /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration.\\n /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri.\\n /// @param _templateUri IPFS path to the dispute template starting with '/ipfs/'. Should not be used with _templateId.\\n event CrossChainDisputeRequest(\\n IArbitratorV2 indexed _arbitrator,\\n uint256 _arbitrableChainId,\\n address indexed _arbitrable,\\n uint256 indexed _arbitrableDisputeID,\\n uint256 _externalDisputeID,\\n uint256 _templateId,\\n string _templateUri\\n );\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrator The arbitrator giving the ruling.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitratorV2 indexed _arbitrator, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Give a ruling for a dispute.\\n /// Must be called by the arbitrator.\\n /// The purpose of this function is to ensure that the address calling it has the right to rule on the contract.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling Ruling given by the arbitrator.\\n /// Note that 0 is reserved for \\\"Not able/wanting to make a decision\\\".\\n function rule(uint256 _disputeID, uint256 _ruling) external;\\n}\\n\",\"keccak256\":\"0xc1a18e122cab929e6b0a028dd48cc560806cf530a0e1e199b15078b79cfd239c\",\"license\":\"MIT\"},\"src/arbitration/IArbitratorV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"./IArbitrableV2.sol\\\";\\n\\n/// @title Arbitrator\\n/// Arbitrator interface that implements the new arbitration standard.\\n/// Unlike the ERC-792 this standard is not concerned with appeals, so each arbitrator can implement an appeal system that suits it the most.\\n/// When developing arbitrator contracts we need to:\\n/// - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes).\\n/// - Define the functions for cost display (arbitrationCost).\\n/// - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling).\\ninterface IArbitratorV2 {\\n /// @dev To be emitted when a dispute is created.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _arbitrable The contract which created the dispute.\\n event DisputeCreation(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable);\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrable The arbitrable receiving the ruling.\\n /// @param _disputeID The identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitrableV2 indexed _arbitrable, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Create a dispute.\\n /// Must be called by the arbitrable contract.\\n /// Must pay at least arbitrationCost(_extraData).\\n /// @param _choices Amount of choices the arbitrator can make in this dispute.\\n /// @param _extraData Can be used to give additional info on the dispute to be created.\\n /// @return disputeID The identifier of the dispute created.\\n function createDispute(uint256 _choices, bytes calldata _extraData) external payable returns (uint256 disputeID);\\n\\n /// @dev Compute the cost of arbitration.\\n /// 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.\\n /// @param _extraData Can be used to give additional info on the dispute to be created.\\n /// @return cost Required cost of arbitration.\\n function arbitrationCost(bytes calldata _extraData) external view returns (uint256 cost);\\n\\n /// @dev Return the current ruling of a dispute.\\n /// This is useful for parties to know if they should appeal.\\n /// @param _disputeID The identifer of the dispute.\\n /// @return ruling The ruling which has been given or the one which will be given if there is no appeal.\\n function currentRuling(uint _disputeID) external view returns (uint ruling);\\n}\\n\",\"keccak256\":\"0xe9a699c2d9c3f57c0e2acf8bea94d274198e5947e91c5eb5f69d86c99e68dbbf\",\"license\":\"MIT\"},\"src/arbitration/arbitrables/DisputeResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@ferittuncer, @unknownunknown1, @jaybuidl]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n\\nimport \\\"../IArbitrableV2.sol\\\";\\n\\npragma solidity 0.8.18;\\n\\n/// @title DisputeResolver\\n/// DisputeResolver contract adapted for V2 from https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.\\ncontract DisputeResolver is IArbitrableV2 {\\n // ************************************* //\\n // * Enums / Structs * //\\n // ************************************* //\\n\\n struct DisputeStruct {\\n bytes arbitratorExtraData; // Extra data for the dispute.\\n bool isRuled; // True if the dispute has been ruled.\\n uint256 ruling; // Ruling given to the dispute.\\n uint256 numberOfRulingOptions; // The number of choices the arbitrator can give.\\n }\\n\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n\\n address public governor; // The governor.\\n IArbitratorV2 public arbitrator; // The arbitrator.\\n DisputeStruct[] public disputes; // Local disputes.\\n mapping(uint256 => uint256) public arbitratorDisputeIDToLocalID; // Maps arbitrator-side dispute IDs to local dispute IDs.\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor\\n /// @param _arbitrator Target global arbitrator for any disputes.\\n constructor(IArbitratorV2 _arbitrator) {\\n governor = msg.sender;\\n arbitrator = _arbitrator;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the governor.\\n /// @param _governor The address of the new governor.\\n function changeGovernor(address _governor) external {\\n require(governor == msg.sender, \\\"Access not allowed: Governor only.\\\");\\n governor = _governor;\\n }\\n\\n function changeArbitrator(IArbitratorV2 _arbitrator) external {\\n require(governor == msg.sender, \\\"Access not allowed: Governor only.\\\");\\n arbitrator = _arbitrator;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Calls createDispute function of the specified arbitrator to create a dispute.\\n /// Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator of the dispute.\\n /// @param _disputeTemplate Dispute template.\\n /// @param _numberOfRulingOptions Number of ruling options.\\n /// @return disputeID Dispute id (on arbitrator side) of the created dispute.\\n function createDisputeForTemplate(\\n bytes calldata _arbitratorExtraData,\\n string calldata _disputeTemplate,\\n uint256 _numberOfRulingOptions\\n ) external payable returns (uint256 disputeID) {\\n return _createDispute(_arbitratorExtraData, _disputeTemplate, \\\"\\\", _numberOfRulingOptions);\\n }\\n\\n /// @dev Calls createDispute function of the specified arbitrator to create a dispute.\\n /// Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator of the dispute.\\n /// @param _disputeTemplateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'.\\n /// @param _numberOfRulingOptions Number of ruling options.\\n /// @return disputeID Dispute id (on arbitrator side) of the created dispute.\\n function createDisputeForTemplateUri(\\n bytes calldata _arbitratorExtraData,\\n string calldata _disputeTemplateUri,\\n uint256 _numberOfRulingOptions\\n ) external payable returns (uint256 disputeID) {\\n return _createDispute(_arbitratorExtraData, \\\"\\\", _disputeTemplateUri, _numberOfRulingOptions);\\n }\\n\\n /// @dev To be called by the arbitrator of the dispute, to declare the winning ruling.\\n /// @param _externalDisputeID ID of the dispute in arbitrator contract.\\n /// @param _ruling The ruling choice of the arbitration.\\n function rule(uint256 _externalDisputeID, uint256 _ruling) external override {\\n uint256 localDisputeID = arbitratorDisputeIDToLocalID[_externalDisputeID];\\n DisputeStruct storage dispute = disputes[localDisputeID];\\n require(msg.sender == address(arbitrator), \\\"Only the arbitrator can execute this.\\\");\\n require(_ruling <= dispute.numberOfRulingOptions, \\\"Invalid ruling.\\\");\\n require(!dispute.isRuled, \\\"This dispute has been ruled already.\\\");\\n\\n dispute.isRuled = true;\\n dispute.ruling = _ruling;\\n\\n emit Ruling(IArbitratorV2(msg.sender), _externalDisputeID, dispute.ruling);\\n }\\n\\n // ************************************* //\\n // * Internal * //\\n // ************************************* //\\n\\n function _createDispute(\\n bytes calldata _arbitratorExtraData,\\n string memory _disputeTemplate,\\n string memory _disputeTemplateUri,\\n uint256 _numberOfRulingOptions\\n ) internal returns (uint256 disputeID) {\\n require(_numberOfRulingOptions > 1, \\\"Should be at least 2 ruling options.\\\");\\n\\n disputeID = arbitrator.createDispute{value: msg.value}(_numberOfRulingOptions, _arbitratorExtraData);\\n uint256 localDisputeID = disputes.length;\\n disputes.push(\\n DisputeStruct({\\n arbitratorExtraData: _arbitratorExtraData,\\n isRuled: false,\\n ruling: 0,\\n numberOfRulingOptions: _numberOfRulingOptions\\n })\\n );\\n arbitratorDisputeIDToLocalID[disputeID] = localDisputeID;\\n\\n uint256 templateId = localDisputeID;\\n emit DisputeTemplate(templateId, \\\"\\\", _disputeTemplate);\\n emit DisputeRequest(arbitrator, disputeID, localDisputeID, templateId, _disputeTemplateUri);\\n }\\n}\\n\",\"keccak256\":\"0x83e137298606af8bea506fff29de9c274d41fd89b85dd2d2815443a9fae38716\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610c89380380610c8983398101604081905261002f91610062565b60008054336001600160a01b031991821617909155600180549091166001600160a01b0392909216919091179055610092565b60006020828403121561007457600080fd5b81516001600160a01b038116811461008b57600080fd5b9392505050565b610be8806100a16000396000f3fe6080604052600436106100765760003560e01c80630c340a241461007b57806325fb3977146100b8578063311a6c56146100d9578063564a565d146100fb5780636cc6cde11461012b578063908bb2951461014b578063e09997d91461015e578063e4c0aaf41461018b578063fc548f08146101ab575b600080fd5b34801561008757600080fd5b5060005461009b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cb6100c6366004610811565b6101cb565b6040519081526020016100af565b3480156100e557600080fd5b506100f96100f4366004610885565b610228565b005b34801561010757600080fd5b5061011b6101163660046108a7565b6103c8565b6040516100af9493929190610906565b34801561013757600080fd5b5060015461009b906001600160a01b031681565b6100cb610159366004610811565b610496565b34801561016a57600080fd5b506100cb6101793660046108a7565b60036020526000908152604090205481565b34801561019757600080fd5b506100f96101a636600461094d565b6104eb565b3480156101b757600080fd5b506100f96101c636600461094d565b610537565b600061021e868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292508891506105839050565b9695505050505050565b600082815260036020526040812054600280549192918390811061024e5761024e610971565b6000918252602090912060015460049092020191506001600160a01b031633146102cd5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79207468652061726269747261746f722063616e2065786563757465206044820152643a3434b99760d91b60648201526084015b60405180910390fd5b80600301548311156103135760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b210393ab634b7339760891b60448201526064016102c4565b600181015460ff16156103745760405162461bcd60e51b8152602060048201526024808201527f54686973206469737075746520686173206265656e2072756c656420616c726560448201526330b23c9760e11b60648201526084016102c4565b6001818101805460ff1916909117905560028101839055604051838152849033907f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769060200160405180910390a350505050565b600281815481106103d857600080fd5b90600052602060002090600402016000915090508060000180546103fb90610987565b80601f016020809104026020016040519081016040528092919081815260200182805461042790610987565b80156104745780601f1061044957610100808354040283529160200191610474565b820191906000526020600020905b81548152906001019060200180831161045757829003601f168201915b5050505060018301546002840154600390940154929360ff9091169290915084565b600061021e86866040518060200160405280600081525087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250899250610583915050565b6000546001600160a01b031633146105155760405162461bcd60e51b81526004016102c4906109c1565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105615760405162461bcd60e51b81526004016102c4906109c1565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000600182116105e15760405162461bcd60e51b8152602060048201526024808201527f53686f756c64206265206174206c6561737420322072756c696e67206f70746960448201526337b7399760e11b60648201526084016102c4565b60015460405163c13517e160e01b81526001600160a01b039091169063c13517e19034906106179086908b908b90600401610a03565b60206040518083038185885af1158015610635573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061065a9190610a39565b600280546040805160a06020601f8c018190040282018101909252608081018a8152949550919382918b908b90819085018382808284376000920182905250938552505050602080830182905260408301829052606090920187905283546001810185559381522081519192600402019081906106d79082610ab7565b5060208281015160018301805460ff1916911515919091179055604080840151600284015560609093015160039283015560008581529190528190208290555181907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709082907f9684b36e8ac6332c160d4d4e14a78ea2679b6484c08726432cf097c99ba978409061076a908a90610b77565b60405180910390a360015460405184916001600160a01b0316907f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e27186906107b590869086908b90610b8a565b60405180910390a3505095945050505050565b60008083601f8401126107da57600080fd5b50813567ffffffffffffffff8111156107f257600080fd5b60208301915083602082850101111561080a57600080fd5b9250929050565b60008060008060006060868803121561082957600080fd5b853567ffffffffffffffff8082111561084157600080fd5b61084d89838a016107c8565b9097509550602088013591508082111561086657600080fd5b50610873888289016107c8565b96999598509660400135949350505050565b6000806040838503121561089857600080fd5b50508035926020909101359150565b6000602082840312156108b957600080fd5b5035919050565b6000815180845260005b818110156108e6576020818501810151868301820152016108ca565b506000602082860101526020601f19601f83011685010191505092915050565b60808152600061091960808301876108c0565b9415156020830152506040810192909252606090910152919050565b6001600160a01b038116811461094a57600080fd5b50565b60006020828403121561095f57600080fd5b813561096a81610935565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061099b57607f821691505b6020821081036109bb57634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b606082015260800190565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b600060208284031215610a4b57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610ab257600081815260208120601f850160051c81016020861015610a8f5750805b601f850160051c820191505b81811015610aae57828155600101610a9b565b5050505b505050565b815167ffffffffffffffff811115610ad157610ad1610a52565b610ae581610adf8454610987565b84610a68565b602080601f831160018114610b1a5760008415610b025750858301515b600019600386901b1c1916600185901b178555610aae565b600085815260208120601f198616915b82811015610b4957888601518255948401946001909101908401610b2a565b5085821015610b675787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600061096a60208301846108c0565b838152826020820152606060408201526000610ba960608301846108c0565b9594505050505056fea26469706673582212209e73d035463fa04bd6a44a74fe31a00141aff519a72beffc9a48e5cd8476b07864736f6c63430008120033", + "deployedBytecode": "0x6080604052600436106100765760003560e01c80630c340a241461007b57806325fb3977146100b8578063311a6c56146100d9578063564a565d146100fb5780636cc6cde11461012b578063908bb2951461014b578063e09997d91461015e578063e4c0aaf41461018b578063fc548f08146101ab575b600080fd5b34801561008757600080fd5b5060005461009b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cb6100c6366004610811565b6101cb565b6040519081526020016100af565b3480156100e557600080fd5b506100f96100f4366004610885565b610228565b005b34801561010757600080fd5b5061011b6101163660046108a7565b6103c8565b6040516100af9493929190610906565b34801561013757600080fd5b5060015461009b906001600160a01b031681565b6100cb610159366004610811565b610496565b34801561016a57600080fd5b506100cb6101793660046108a7565b60036020526000908152604090205481565b34801561019757600080fd5b506100f96101a636600461094d565b6104eb565b3480156101b757600080fd5b506100f96101c636600461094d565b610537565b600061021e868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292508891506105839050565b9695505050505050565b600082815260036020526040812054600280549192918390811061024e5761024e610971565b6000918252602090912060015460049092020191506001600160a01b031633146102cd5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79207468652061726269747261746f722063616e2065786563757465206044820152643a3434b99760d91b60648201526084015b60405180910390fd5b80600301548311156103135760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b210393ab634b7339760891b60448201526064016102c4565b600181015460ff16156103745760405162461bcd60e51b8152602060048201526024808201527f54686973206469737075746520686173206265656e2072756c656420616c726560448201526330b23c9760e11b60648201526084016102c4565b6001818101805460ff1916909117905560028101839055604051838152849033907f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769060200160405180910390a350505050565b600281815481106103d857600080fd5b90600052602060002090600402016000915090508060000180546103fb90610987565b80601f016020809104026020016040519081016040528092919081815260200182805461042790610987565b80156104745780601f1061044957610100808354040283529160200191610474565b820191906000526020600020905b81548152906001019060200180831161045757829003601f168201915b5050505060018301546002840154600390940154929360ff9091169290915084565b600061021e86866040518060200160405280600081525087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250899250610583915050565b6000546001600160a01b031633146105155760405162461bcd60e51b81526004016102c4906109c1565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105615760405162461bcd60e51b81526004016102c4906109c1565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000600182116105e15760405162461bcd60e51b8152602060048201526024808201527f53686f756c64206265206174206c6561737420322072756c696e67206f70746960448201526337b7399760e11b60648201526084016102c4565b60015460405163c13517e160e01b81526001600160a01b039091169063c13517e19034906106179086908b908b90600401610a03565b60206040518083038185885af1158015610635573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061065a9190610a39565b600280546040805160a06020601f8c018190040282018101909252608081018a8152949550919382918b908b90819085018382808284376000920182905250938552505050602080830182905260408301829052606090920187905283546001810185559381522081519192600402019081906106d79082610ab7565b5060208281015160018301805460ff1916911515919091179055604080840151600284015560609093015160039283015560008581529190528190208290555181907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709082907f9684b36e8ac6332c160d4d4e14a78ea2679b6484c08726432cf097c99ba978409061076a908a90610b77565b60405180910390a360015460405184916001600160a01b0316907f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e27186906107b590869086908b90610b8a565b60405180910390a3505095945050505050565b60008083601f8401126107da57600080fd5b50813567ffffffffffffffff8111156107f257600080fd5b60208301915083602082850101111561080a57600080fd5b9250929050565b60008060008060006060868803121561082957600080fd5b853567ffffffffffffffff8082111561084157600080fd5b61084d89838a016107c8565b9097509550602088013591508082111561086657600080fd5b50610873888289016107c8565b96999598509660400135949350505050565b6000806040838503121561089857600080fd5b50508035926020909101359150565b6000602082840312156108b957600080fd5b5035919050565b6000815180845260005b818110156108e6576020818501810151868301820152016108ca565b506000602082860101526020601f19601f83011685010191505092915050565b60808152600061091960808301876108c0565b9415156020830152506040810192909252606090910152919050565b6001600160a01b038116811461094a57600080fd5b50565b60006020828403121561095f57600080fd5b813561096a81610935565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061099b57607f821691505b6020821081036109bb57634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b606082015260800190565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b600060208284031215610a4b57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610ab257600081815260208120601f850160051c81016020861015610a8f5750805b601f850160051c820191505b81811015610aae57828155600101610a9b565b5050505b505050565b815167ffffffffffffffff811115610ad157610ad1610a52565b610ae581610adf8454610987565b84610a68565b602080601f831160018114610b1a5760008415610b025750858301515b600019600386901b1c1916600185901b178555610aae565b600085815260208120601f198616915b82811015610b4957888601518255948401946001909101908401610b2a565b5085821015610b675787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600061096a60208301846108c0565b838152826020820152606060408201526000610ba960608301846108c0565b9594505050505056fea26469706673582212209e73d035463fa04bd6a44a74fe31a00141aff519a72beffc9a48e5cd8476b07864736f6c63430008120033", "devdoc": { "events": { - "Dispute(address,uint256,uint256,uint256)": { + "CrossChainDisputeRequest(address,uint256,address,uint256,uint256,uint256,string)": { "details": "To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.", "params": { + "_arbitrable": "The address of the Arbitrable contract.", + "_arbitrableChainId": "The chain identifier where the Arbitrable contract is deployed.", + "_arbitrableDisputeID": "The identifier of the dispute in the Arbitrable contract.", "_arbitrator": "The arbitrator of the contract.", - "_disputeID": "ID of the dispute in the Arbitrator contract.", - "_evidenceGroupID": "Unique identifier of the evidence group that is linked to this dispute.", - "_metaEvidenceID": "Unique identifier of meta-evidence." + "_externalDisputeID": "An identifier created outside Kleros by the protocol requesting arbitration.", + "_templateId": "The identifier of the dispute template. Should not be used with _templateUri.", + "_templateUri": "IPFS path to the dispute template starting with '/ipfs/'. Should not be used with _templateId." } }, - "MetaEvidence(uint256,string)": { - "details": "To be emitted when meta-evidence is submitted.", + "DisputeRequest(address,uint256,uint256,uint256,string)": { + "details": "To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.", + "params": { + "_arbitrableDisputeID": "The identifier of the dispute in the Arbitrable contract.", + "_arbitrator": "The arbitrator of the contract.", + "_externalDisputeID": "An identifier created outside Kleros by the protocol requesting arbitration.", + "_templateId": "The identifier of the dispute template. Should not be used with _templateUri.", + "_templateUri": "The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId." + } + }, + "DisputeTemplate(uint256,string,string)": { + "details": "To be emitted when a new dispute template is created.", "params": { - "_evidence": "IPFS path to metaevidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/metaevidence.json'", - "_metaEvidenceID": "Unique identifier of meta-evidence." + "_templateId": "The identifier of the dispute template.", + "_templateTag": "An optional tag for the dispute template, such as \"registration\" or \"removal\".", + "data": "The template data." } }, "Ruling(address,uint256,uint256)": { "details": "To be raised when a ruling is given.", "params": { "_arbitrator": "The arbitrator giving the ruling.", - "_disputeID": "ID of the dispute in the Arbitrator contract.", + "_disputeID": "The identifier of the dispute in the Arbitrator contract.", "_ruling": "The ruling which was given." } } }, "kind": "dev", "methods": { + "changeGovernor(address)": { + "details": "Changes the governor.", + "params": { + "_governor": "The address of the new governor." + } + }, "constructor": { "details": "Constructor", "params": { "_arbitrator": "Target global arbitrator for any disputes." } }, - "createDispute(bytes,string,uint256)": { - "details": "TRUSTED. Calls createDispute function of the specified arbitrator to create a dispute. Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract.", + "createDisputeForTemplate(bytes,string,uint256)": { + "details": "Calls createDispute function of the specified arbitrator to create a dispute. Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract.", + "params": { + "_arbitratorExtraData": "Extra data for the arbitrator of the dispute.", + "_disputeTemplate": "Dispute template.", + "_numberOfRulingOptions": "Number of ruling options." + }, + "returns": { + "disputeID": "Dispute id (on arbitrator side) of the created dispute." + } + }, + "createDisputeForTemplateUri(bytes,string,uint256)": { + "details": "Calls createDispute function of the specified arbitrator to create a dispute. Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract.", "params": { "_arbitratorExtraData": "Extra data for the arbitrator of the dispute.", - "_metaevidenceURI": "Link to metaevidence of the dispute.", + "_disputeTemplateUri": "The URI to the dispute template. For example on IPFS: starting with '/ipfs/'.", "_numberOfRulingOptions": "Number of ruling options." }, "returns": { @@ -279,7 +439,7 @@ } } }, - "title": "DisputeResolver DisputeResolver contract adapted for V2 https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.", + "title": "DisputeResolver DisputeResolver contract adapted for V2 from https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.", "version": 1 }, "userdoc": { @@ -290,25 +450,46 @@ "storageLayout": { "storage": [ { - "astId": 9696, + "astId": 129, "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", - "label": "disputes", + "label": "governor", "offset": 0, "slot": "0", - "type": "t_array(t_struct(DisputeStruct)9689_storage)dyn_storage" + "type": "t_address" }, { - "astId": 9700, + "astId": 132, "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", - "label": "externalIDtoLocalID", + "label": "arbitrator", "offset": 0, "slot": "1", + "type": "t_contract(IArbitratorV2)112" + }, + { + "astId": 136, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "disputes", + "offset": 0, + "slot": "2", + "type": "t_array(t_struct(DisputeStruct)127_storage)dyn_storage" + }, + { + "astId": 140, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "arbitratorDisputeIDToLocalID", + "offset": 0, + "slot": "3", "type": "t_mapping(t_uint256,t_uint256)" } ], "types": { - "t_array(t_struct(DisputeStruct)9689_storage)dyn_storage": { - "base": "t_struct(DisputeStruct)9689_storage", + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(DisputeStruct)127_storage)dyn_storage": { + "base": "t_struct(DisputeStruct)127_storage", "encoding": "dynamic_array", "label": "struct DisputeResolver.DisputeStruct[]", "numberOfBytes": "32" @@ -323,6 +504,11 @@ "label": "bytes", "numberOfBytes": "32" }, + "t_contract(IArbitratorV2)112": { + "encoding": "inplace", + "label": "contract IArbitratorV2", + "numberOfBytes": "20" + }, "t_mapping(t_uint256,t_uint256)": { "encoding": "mapping", "key": "t_uint256", @@ -330,12 +516,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(DisputeStruct)9689_storage": { + "t_struct(DisputeStruct)127_storage": { "encoding": "inplace", "label": "struct DisputeResolver.DisputeStruct", "members": [ { - "astId": 9682, + "astId": 120, "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", "label": "arbitratorExtraData", "offset": 0, @@ -343,7 +529,7 @@ "type": "t_bytes_storage" }, { - "astId": 9684, + "astId": 122, "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", "label": "isRuled", "offset": 0, @@ -351,7 +537,7 @@ "type": "t_bool" }, { - "astId": 9686, + "astId": 124, "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", "label": "ruling", "offset": 0, @@ -359,7 +545,7 @@ "type": "t_uint256" }, { - "astId": 9688, + "astId": 126, "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", "label": "numberOfRulingOptions", "offset": 0, diff --git a/contracts/deployments/chiado/DisputeResolver.json b/contracts/deployments/chiado/DisputeResolver.json new file mode 100644 index 000000000..5ccce5b6b --- /dev/null +++ b/contracts/deployments/chiado/DisputeResolver.json @@ -0,0 +1,565 @@ +{ + "address": "0x433eD78895df1df7668C40b3e82d54410331F942", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_arbitrableChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "_arbitrable", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_arbitrableDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_externalDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_templateId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "_templateUri", + "type": "string" + } + ], + "name": "CrossChainDisputeRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_arbitrableDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_externalDisputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_templateId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "_templateUri", + "type": "string" + } + ], + "name": "DisputeRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "_templateId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "string", + "name": "_templateTag", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "data", + "type": "string" + } + ], + "name": "DisputeTemplate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_disputeID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_ruling", + "type": "uint256" + } + ], + "name": "Ruling", + "type": "event" + }, + { + "inputs": [], + "name": "arbitrator", + "outputs": [ + { + "internalType": "contract IArbitratorV2", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "arbitratorDisputeIDToLocalID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IArbitratorV2", + "name": "_arbitrator", + "type": "address" + } + ], + "name": "changeArbitrator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_governor", + "type": "address" + } + ], + "name": "changeGovernor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_arbitratorExtraData", + "type": "bytes" + }, + { + "internalType": "string", + "name": "_disputeTemplate", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_numberOfRulingOptions", + "type": "uint256" + } + ], + "name": "createDisputeForTemplate", + "outputs": [ + { + "internalType": "uint256", + "name": "disputeID", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_arbitratorExtraData", + "type": "bytes" + }, + { + "internalType": "string", + "name": "_disputeTemplateUri", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_numberOfRulingOptions", + "type": "uint256" + } + ], + "name": "createDisputeForTemplateUri", + "outputs": [ + { + "internalType": "uint256", + "name": "disputeID", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "disputes", + "outputs": [ + { + "internalType": "bytes", + "name": "arbitratorExtraData", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "isRuled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "ruling", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numberOfRulingOptions", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_externalDisputeID", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_ruling", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x48bb5243e06a6dee8e772e2e69e4fa415d4794edf3c9e35afa348b85021a6868", + "receipt": { + "to": null, + "from": "0xF50E77f2A2B6138D16c6c7511562E5C33c4B15A3", + "contractAddress": "0x433eD78895df1df7668C40b3e82d54410331F942", + "transactionIndex": 0, + "gasUsed": "758346", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x48d38d9df0d5b356f5f6e50085ad042777fca7649e743ba102264e5d67a7c31b", + "transactionHash": "0x48bb5243e06a6dee8e772e2e69e4fa415d4794edf3c9e35afa348b85021a6868", + "logs": [], + "blockNumber": 4448702, + "cumulativeGasUsed": "758346", + "status": 1, + "byzantium": true + }, + "args": [ + "0x573bcD6ee4aEe152eCC9Cafd2c0820Dc548AF6cC" + ], + "numDeployments": 2, + "solcInputHash": "e5cc0e9bf05bbcd7b6145f8ea4d3c9a9", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_arbitrableChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_arbitrable\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_arbitrableDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_templateId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_templateUri\",\"type\":\"string\"}],\"name\":\"CrossChainDisputeRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_arbitrableDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_templateId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"_templateUri\",\"type\":\"string\"}],\"name\":\"DisputeRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_templateId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"_templateTag\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"data\",\"type\":\"string\"}],\"name\":\"DisputeTemplate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"_disputeID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"Ruling\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"arbitrator\",\"outputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"arbitratorDisputeIDToLocalID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IArbitratorV2\",\"name\":\"_arbitrator\",\"type\":\"address\"}],\"name\":\"changeArbitrator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_governor\",\"type\":\"address\"}],\"name\":\"changeGovernor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_disputeTemplate\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"_numberOfRulingOptions\",\"type\":\"uint256\"}],\"name\":\"createDisputeForTemplate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"disputeID\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_disputeTemplateUri\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"_numberOfRulingOptions\",\"type\":\"uint256\"}],\"name\":\"createDisputeForTemplateUri\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"disputeID\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"disputes\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"arbitratorExtraData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"isRuled\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"ruling\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"numberOfRulingOptions\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_externalDisputeID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_ruling\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"CrossChainDisputeRequest(address,uint256,address,uint256,uint256,uint256,string)\":{\"details\":\"To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\",\"params\":{\"_arbitrable\":\"The address of the Arbitrable contract.\",\"_arbitrableChainId\":\"The chain ID of the Arbitrable contract.\",\"_arbitrableDisputeID\":\"The ID of the dispute in the Arbitrable contract.\",\"_arbitrator\":\"The arbitrator of the contract.\",\"_externalDisputeID\":\"An identifier created outside Kleros by the protocol requesting arbitration.\",\"_templateId\":\"The ID of the dispute template. Should not be used with _templateUri.\",\"_templateUri\":\"IPFS path to the dispute template starting with '/ipfs/'. Should not be used with _templateId.\"}},\"DisputeRequest(address,uint256,uint256,uint256,string)\":{\"details\":\"To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\",\"params\":{\"_arbitrableDisputeID\":\"The ID of the dispute in the Arbitrable contract.\",\"_arbitrator\":\"The arbitrator of the contract.\",\"_externalDisputeID\":\"An identifier created outside Kleros by the protocol requesting arbitration.\",\"_templateId\":\"The ID of the dispute template. Should not be used with _templateUri.\",\"_templateUri\":\"The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId.\"}},\"DisputeTemplate(uint256,string,string)\":{\"details\":\"To be emitted when a new dispute template is created.\",\"params\":{\"_templateId\":\"The ID of the dispute template.\",\"_templateTag\":\"An optional tag for the dispute template, such as \\\"registration\\\" or \\\"removal\\\".\",\"data\":\"The template data.\"}},\"Ruling(address,uint256,uint256)\":{\"details\":\"To be raised when a ruling is given.\",\"params\":{\"_arbitrator\":\"The arbitrator giving the ruling.\",\"_disputeID\":\"ID of the dispute in the Arbitrator contract.\",\"_ruling\":\"The ruling which was given.\"}}},\"kind\":\"dev\",\"methods\":{\"changeGovernor(address)\":{\"details\":\"Changes the governor.\",\"params\":{\"_governor\":\"The address of the new governor.\"}},\"constructor\":{\"details\":\"Constructor\",\"params\":{\"_arbitrator\":\"Target global arbitrator for any disputes.\"}},\"createDisputeForTemplate(bytes,string,uint256)\":{\"details\":\"Calls createDispute function of the specified arbitrator to create a dispute. Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\",\"params\":{\"_arbitratorExtraData\":\"Extra data for the arbitrator of the dispute.\",\"_disputeTemplate\":\"Dispute template.\",\"_numberOfRulingOptions\":\"Number of ruling options.\"},\"returns\":{\"disputeID\":\"Dispute id (on arbitrator side) of the created dispute.\"}},\"createDisputeForTemplateUri(bytes,string,uint256)\":{\"details\":\"Calls createDispute function of the specified arbitrator to create a dispute. Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\",\"params\":{\"_arbitratorExtraData\":\"Extra data for the arbitrator of the dispute.\",\"_disputeTemplateUri\":\"The URI to the dispute template. For example on IPFS: starting with '/ipfs/'.\",\"_numberOfRulingOptions\":\"Number of ruling options.\"},\"returns\":{\"disputeID\":\"Dispute id (on arbitrator side) of the created dispute.\"}},\"rule(uint256,uint256)\":{\"details\":\"To be called by the arbitrator of the dispute, to declare the winning ruling.\",\"params\":{\"_externalDisputeID\":\"ID of the dispute in arbitrator contract.\",\"_ruling\":\"The ruling choice of the arbitration.\"}}},\"title\":\"DisputeResolver DisputeResolver contract adapted for V2 from https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/arbitration/arbitrables/DisputeResolver.sol\":\"DisputeResolver\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[]},\"sources\":{\"src/arbitration/IArbitrableV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"./IArbitratorV2.sol\\\";\\n\\n/// @title IArbitrableV2\\n/// @notice Arbitrable interface.\\n/// When developing arbitrable contracts, we need to:\\n/// - Define the action taken when a ruling is received by the contract.\\n/// - Allow dispute creation. For this a function must call arbitrator.createDispute{value: _fee}(_choices,_extraData);\\ninterface IArbitrableV2 {\\n /// @dev To be emitted when a new dispute template is created.\\n /// @param _templateId The ID of the dispute template.\\n /// @param _templateTag An optional tag for the dispute template, such as \\\"registration\\\" or \\\"removal\\\".\\n /// @param data The template data.\\n event DisputeTemplate(uint256 indexed _templateId, string indexed _templateTag, string data);\\n\\n /// @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitrableDisputeID The ID of the dispute in the Arbitrable contract.\\n /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration.\\n /// @param _templateId The ID of the dispute template. Should not be used with _templateUri.\\n /// @param _templateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId.\\n event DisputeRequest(\\n IArbitratorV2 indexed _arbitrator,\\n uint256 indexed _arbitrableDisputeID,\\n uint256 _externalDisputeID,\\n uint256 _templateId,\\n string _templateUri\\n );\\n\\n /// @dev To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.\\n /// @param _arbitrator The arbitrator of the contract.\\n /// @param _arbitrableChainId The chain ID of the Arbitrable contract.\\n /// @param _arbitrable The address of the Arbitrable contract.\\n /// @param _arbitrableDisputeID The ID of the dispute in the Arbitrable contract.\\n /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration.\\n /// @param _templateId The ID of the dispute template. Should not be used with _templateUri.\\n /// @param _templateUri IPFS path to the dispute template starting with '/ipfs/'. Should not be used with _templateId.\\n event CrossChainDisputeRequest(\\n IArbitratorV2 indexed _arbitrator,\\n uint256 _arbitrableChainId,\\n address indexed _arbitrable,\\n uint256 indexed _arbitrableDisputeID,\\n uint256 _externalDisputeID,\\n uint256 _templateId,\\n string _templateUri\\n );\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrator The arbitrator giving the ruling.\\n /// @param _disputeID ID of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitratorV2 indexed _arbitrator, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Give a ruling for a dispute.\\n /// Must be called by the arbitrator.\\n /// The purpose of this function is to ensure that the address calling it has the right to rule on the contract.\\n /// @param _disputeID ID of the dispute in the Arbitrator contract.\\n /// @param _ruling Ruling given by the arbitrator.\\n /// Note that 0 is reserved for \\\"Not able/wanting to make a decision\\\".\\n function rule(uint256 _disputeID, uint256 _ruling) external;\\n}\\n\",\"keccak256\":\"0x4e29b75fbf3d030d231b7e963bcd21b70c624144cbcc039c4ae25055dac95e6a\",\"license\":\"MIT\"},\"src/arbitration/IArbitratorV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"./IArbitrableV2.sol\\\";\\n\\n/// @title Arbitrator\\n/// Arbitrator interface that implements the new arbitration standard.\\n/// Unlike the ERC-792 this standard is not concerned with appeals, so each arbitrator can implement an appeal system that suits it the most.\\n/// When developing arbitrator contracts we need to:\\n/// - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes).\\n/// - Define the functions for cost display (arbitrationCost).\\n/// - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling).\\ninterface IArbitratorV2 {\\n /// @dev To be emitted when a dispute is created.\\n /// @param _disputeID Identifier of the dispute.\\n /// @param _arbitrable The contract which created the dispute.\\n event DisputeCreation(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable);\\n\\n /// @dev To be raised when a ruling is given.\\n /// @param _arbitrable The arbitrable receiving the ruling.\\n /// @param _disputeID Identifier of the dispute in the Arbitrator contract.\\n /// @param _ruling The ruling which was given.\\n event Ruling(IArbitrableV2 indexed _arbitrable, uint256 indexed _disputeID, uint256 _ruling);\\n\\n /// @dev Create a dispute.\\n /// Must be called by the arbitrable contract.\\n /// Must pay at least arbitrationCost(_extraData).\\n /// @param _choices Amount of choices the arbitrator can make in this dispute.\\n /// @param _extraData Can be used to give additional info on the dispute to be created.\\n /// @return disputeID Identifier of the dispute created.\\n function createDispute(uint256 _choices, bytes calldata _extraData) external payable returns (uint256 disputeID);\\n\\n /// @dev Compute the cost of arbitration.\\n /// 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.\\n /// @param _extraData Can be used to give additional info on the dispute to be created.\\n /// @return cost Required cost of arbitration.\\n function arbitrationCost(bytes calldata _extraData) external view returns (uint256 cost);\\n\\n /// @dev Return the current ruling of a dispute.\\n /// This is useful for parties to know if they should appeal.\\n /// @param _disputeID ID of the dispute.\\n /// @return ruling The ruling which has been given or the one which will be given if there is no appeal.\\n function currentRuling(uint _disputeID) external view returns (uint ruling);\\n}\\n\",\"keccak256\":\"0x07d5b8029368fcb701315273eaa3b3845cbee9303f6aad7993d551ed2f4360f2\",\"license\":\"MIT\"},\"src/arbitration/arbitrables/DisputeResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/// @custom:authors: [@ferittuncer, @unknownunknown1, @jaybuidl]\\n/// @custom:reviewers: []\\n/// @custom:auditors: []\\n/// @custom:bounties: []\\n\\nimport \\\"../IArbitrableV2.sol\\\";\\n\\npragma solidity 0.8.18;\\n\\n/// @title DisputeResolver\\n/// DisputeResolver contract adapted for V2 from https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.\\ncontract DisputeResolver is IArbitrableV2 {\\n \\n // ************************************* //\\n // * Enums / Structs * //\\n // ************************************* //\\n \\n struct DisputeStruct {\\n bytes arbitratorExtraData; // Extra data for the dispute.\\n bool isRuled; // True if the dispute has been ruled.\\n uint256 ruling; // Ruling given to the dispute.\\n uint256 numberOfRulingOptions; // The number of choices the arbitrator can give.\\n }\\n\\n // ************************************* //\\n // * Storage * //\\n // ************************************* //\\n \\n address public governor;\\n IArbitratorV2 public arbitrator; // Arbitrator is set in constructor and never changed.\\n DisputeStruct[] public disputes; // Local disputes.\\n mapping(uint256 => uint256) public arbitratorDisputeIDToLocalID; // Maps external (arbitrator side) dispute IDs to local dispute IDs.\\n\\n // ************************************* //\\n // * Constructor * //\\n // ************************************* //\\n\\n /// @dev Constructor\\n /// @param _arbitrator Target global arbitrator for any disputes.\\n constructor(IArbitratorV2 _arbitrator) {\\n governor = msg.sender;\\n arbitrator = _arbitrator;\\n }\\n\\n // ************************************* //\\n // * Governance * //\\n // ************************************* //\\n\\n /// @dev Changes the governor.\\n /// @param _governor The address of the new governor.\\n function changeGovernor(address _governor) external {\\n require(governor == msg.sender, \\\"Access not allowed: Governor only.\\\");\\n governor = _governor;\\n }\\n\\n function changeArbitrator(IArbitratorV2 _arbitrator) external {\\n require(governor == msg.sender, \\\"Access not allowed: Governor only.\\\");\\n arbitrator = _arbitrator;\\n }\\n\\n // ************************************* //\\n // * State Modifiers * //\\n // ************************************* //\\n\\n /// @dev Calls createDispute function of the specified arbitrator to create a dispute.\\n /// Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator of the dispute.\\n /// @param _disputeTemplate Dispute template.\\n /// @param _numberOfRulingOptions Number of ruling options.\\n /// @return disputeID Dispute id (on arbitrator side) of the created dispute.\\n function createDisputeForTemplate(\\n bytes calldata _arbitratorExtraData,\\n string calldata _disputeTemplate,\\n uint256 _numberOfRulingOptions\\n ) external payable returns (uint256 disputeID) {\\n return _createDispute(_arbitratorExtraData, _disputeTemplate, \\\"\\\", _numberOfRulingOptions);\\n }\\n\\n /// @dev Calls createDispute function of the specified arbitrator to create a dispute.\\n /// Note that we don\\u2019t need to check that msg.value is enough to pay arbitration fees as it\\u2019s the responsibility of the arbitrator contract.\\n /// @param _arbitratorExtraData Extra data for the arbitrator of the dispute.\\n /// @param _disputeTemplateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'.\\n /// @param _numberOfRulingOptions Number of ruling options.\\n /// @return disputeID Dispute id (on arbitrator side) of the created dispute.\\n function createDisputeForTemplateUri(\\n bytes calldata _arbitratorExtraData,\\n string calldata _disputeTemplateUri,\\n uint256 _numberOfRulingOptions\\n ) external payable returns (uint256 disputeID) {\\n return _createDispute(_arbitratorExtraData, \\\"\\\", _disputeTemplateUri, _numberOfRulingOptions);\\n }\\n\\n /// @dev To be called by the arbitrator of the dispute, to declare the winning ruling.\\n /// @param _externalDisputeID ID of the dispute in arbitrator contract.\\n /// @param _ruling The ruling choice of the arbitration.\\n function rule(uint256 _externalDisputeID, uint256 _ruling) external override {\\n uint256 localDisputeID = arbitratorDisputeIDToLocalID[_externalDisputeID];\\n DisputeStruct storage dispute = disputes[localDisputeID];\\n require(msg.sender == address(arbitrator), \\\"Only the arbitrator can execute this.\\\");\\n require(_ruling <= dispute.numberOfRulingOptions, \\\"Invalid ruling.\\\");\\n require(!dispute.isRuled, \\\"This dispute has been ruled already.\\\");\\n\\n dispute.isRuled = true;\\n dispute.ruling = _ruling;\\n\\n emit Ruling(IArbitratorV2(msg.sender), _externalDisputeID, dispute.ruling);\\n }\\n\\n // ************************************* //\\n // * Internal * //\\n // ************************************* //\\n\\n function _createDispute(\\n bytes calldata _arbitratorExtraData,\\n string memory _disputeTemplate,\\n string memory _disputeUri,\\n uint256 _numberOfRulingOptions\\n ) internal returns (uint256 disputeID) {\\n require(_numberOfRulingOptions > 1, \\\"Should be at least 2 ruling options.\\\");\\n\\n disputeID = arbitrator.createDispute{value: msg.value}(_numberOfRulingOptions, _arbitratorExtraData);\\n uint256 localDisputeID = disputes.length;\\n disputes.push(\\n DisputeStruct({\\n arbitratorExtraData: _arbitratorExtraData,\\n isRuled: false,\\n ruling: 0,\\n numberOfRulingOptions: _numberOfRulingOptions\\n })\\n );\\n arbitratorDisputeIDToLocalID[disputeID] = localDisputeID;\\n \\n uint256 templateId = localDisputeID;\\n emit DisputeTemplate(templateId, \\\"\\\", _disputeTemplate);\\n emit DisputeRequest(arbitrator, disputeID, localDisputeID, templateId, _disputeUri);\\n }\\n}\\n\",\"keccak256\":\"0x72a8602b50246bbf9829fa61eecd80344842d45c9b63ed606d732cfffe23b341\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610c89380380610c8983398101604081905261002f91610062565b60008054336001600160a01b031991821617909155600180549091166001600160a01b0392909216919091179055610092565b60006020828403121561007457600080fd5b81516001600160a01b038116811461008b57600080fd5b9392505050565b610be8806100a16000396000f3fe6080604052600436106100765760003560e01c80630c340a241461007b57806325fb3977146100b8578063311a6c56146100d9578063564a565d146100fb5780636cc6cde11461012b578063908bb2951461014b578063e09997d91461015e578063e4c0aaf41461018b578063fc548f08146101ab575b600080fd5b34801561008757600080fd5b5060005461009b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cb6100c6366004610811565b6101cb565b6040519081526020016100af565b3480156100e557600080fd5b506100f96100f4366004610885565b610228565b005b34801561010757600080fd5b5061011b6101163660046108a7565b6103c8565b6040516100af9493929190610906565b34801561013757600080fd5b5060015461009b906001600160a01b031681565b6100cb610159366004610811565b610496565b34801561016a57600080fd5b506100cb6101793660046108a7565b60036020526000908152604090205481565b34801561019757600080fd5b506100f96101a636600461094d565b6104eb565b3480156101b757600080fd5b506100f96101c636600461094d565b610537565b600061021e868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292508891506105839050565b9695505050505050565b600082815260036020526040812054600280549192918390811061024e5761024e610971565b6000918252602090912060015460049092020191506001600160a01b031633146102cd5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79207468652061726269747261746f722063616e2065786563757465206044820152643a3434b99760d91b60648201526084015b60405180910390fd5b80600301548311156103135760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b210393ab634b7339760891b60448201526064016102c4565b600181015460ff16156103745760405162461bcd60e51b8152602060048201526024808201527f54686973206469737075746520686173206265656e2072756c656420616c726560448201526330b23c9760e11b60648201526084016102c4565b6001818101805460ff1916909117905560028101839055604051838152849033907f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769060200160405180910390a350505050565b600281815481106103d857600080fd5b90600052602060002090600402016000915090508060000180546103fb90610987565b80601f016020809104026020016040519081016040528092919081815260200182805461042790610987565b80156104745780601f1061044957610100808354040283529160200191610474565b820191906000526020600020905b81548152906001019060200180831161045757829003601f168201915b5050505060018301546002840154600390940154929360ff9091169290915084565b600061021e86866040518060200160405280600081525087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250899250610583915050565b6000546001600160a01b031633146105155760405162461bcd60e51b81526004016102c4906109c1565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105615760405162461bcd60e51b81526004016102c4906109c1565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000600182116105e15760405162461bcd60e51b8152602060048201526024808201527f53686f756c64206265206174206c6561737420322072756c696e67206f70746960448201526337b7399760e11b60648201526084016102c4565b60015460405163c13517e160e01b81526001600160a01b039091169063c13517e19034906106179086908b908b90600401610a03565b60206040518083038185885af1158015610635573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061065a9190610a39565b600280546040805160a06020601f8c018190040282018101909252608081018a8152949550919382918b908b90819085018382808284376000920182905250938552505050602080830182905260408301829052606090920187905283546001810185559381522081519192600402019081906106d79082610ab7565b5060208281015160018301805460ff1916911515919091179055604080840151600284015560609093015160039283015560008581529190528190208290555181907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709082907f9684b36e8ac6332c160d4d4e14a78ea2679b6484c08726432cf097c99ba978409061076a908a90610b77565b60405180910390a360015460405184916001600160a01b0316907f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e27186906107b590869086908b90610b8a565b60405180910390a3505095945050505050565b60008083601f8401126107da57600080fd5b50813567ffffffffffffffff8111156107f257600080fd5b60208301915083602082850101111561080a57600080fd5b9250929050565b60008060008060006060868803121561082957600080fd5b853567ffffffffffffffff8082111561084157600080fd5b61084d89838a016107c8565b9097509550602088013591508082111561086657600080fd5b50610873888289016107c8565b96999598509660400135949350505050565b6000806040838503121561089857600080fd5b50508035926020909101359150565b6000602082840312156108b957600080fd5b5035919050565b6000815180845260005b818110156108e6576020818501810151868301820152016108ca565b506000602082860101526020601f19601f83011685010191505092915050565b60808152600061091960808301876108c0565b9415156020830152506040810192909252606090910152919050565b6001600160a01b038116811461094a57600080fd5b50565b60006020828403121561095f57600080fd5b813561096a81610935565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061099b57607f821691505b6020821081036109bb57634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b606082015260800190565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b600060208284031215610a4b57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610ab257600081815260208120601f850160051c81016020861015610a8f5750805b601f850160051c820191505b81811015610aae57828155600101610a9b565b5050505b505050565b815167ffffffffffffffff811115610ad157610ad1610a52565b610ae581610adf8454610987565b84610a68565b602080601f831160018114610b1a5760008415610b025750858301515b600019600386901b1c1916600185901b178555610aae565b600085815260208120601f198616915b82811015610b4957888601518255948401946001909101908401610b2a565b5085821015610b675787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600061096a60208301846108c0565b838152826020820152606060408201526000610ba960608301846108c0565b9594505050505056fea2646970667358221220a719b050bca90307d777fff41b441c2f1ee3ba5b5292ac5605dfd7ab9b7b043964736f6c63430008120033", + "deployedBytecode": "0x6080604052600436106100765760003560e01c80630c340a241461007b57806325fb3977146100b8578063311a6c56146100d9578063564a565d146100fb5780636cc6cde11461012b578063908bb2951461014b578063e09997d91461015e578063e4c0aaf41461018b578063fc548f08146101ab575b600080fd5b34801561008757600080fd5b5060005461009b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cb6100c6366004610811565b6101cb565b6040519081526020016100af565b3480156100e557600080fd5b506100f96100f4366004610885565b610228565b005b34801561010757600080fd5b5061011b6101163660046108a7565b6103c8565b6040516100af9493929190610906565b34801561013757600080fd5b5060015461009b906001600160a01b031681565b6100cb610159366004610811565b610496565b34801561016a57600080fd5b506100cb6101793660046108a7565b60036020526000908152604090205481565b34801561019757600080fd5b506100f96101a636600461094d565b6104eb565b3480156101b757600080fd5b506100f96101c636600461094d565b610537565b600061021e868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292508891506105839050565b9695505050505050565b600082815260036020526040812054600280549192918390811061024e5761024e610971565b6000918252602090912060015460049092020191506001600160a01b031633146102cd5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79207468652061726269747261746f722063616e2065786563757465206044820152643a3434b99760d91b60648201526084015b60405180910390fd5b80600301548311156103135760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b210393ab634b7339760891b60448201526064016102c4565b600181015460ff16156103745760405162461bcd60e51b8152602060048201526024808201527f54686973206469737075746520686173206265656e2072756c656420616c726560448201526330b23c9760e11b60648201526084016102c4565b6001818101805460ff1916909117905560028101839055604051838152849033907f394027a5fa6e098a1191094d1719d6929b9abc535fcc0c8f448d6a4e756222769060200160405180910390a350505050565b600281815481106103d857600080fd5b90600052602060002090600402016000915090508060000180546103fb90610987565b80601f016020809104026020016040519081016040528092919081815260200182805461042790610987565b80156104745780601f1061044957610100808354040283529160200191610474565b820191906000526020600020905b81548152906001019060200180831161045757829003601f168201915b5050505060018301546002840154600390940154929360ff9091169290915084565b600061021e86866040518060200160405280600081525087878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250899250610583915050565b6000546001600160a01b031633146105155760405162461bcd60e51b81526004016102c4906109c1565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105615760405162461bcd60e51b81526004016102c4906109c1565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000600182116105e15760405162461bcd60e51b8152602060048201526024808201527f53686f756c64206265206174206c6561737420322072756c696e67206f70746960448201526337b7399760e11b60648201526084016102c4565b60015460405163c13517e160e01b81526001600160a01b039091169063c13517e19034906106179086908b908b90600401610a03565b60206040518083038185885af1158015610635573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061065a9190610a39565b600280546040805160a06020601f8c018190040282018101909252608081018a8152949550919382918b908b90819085018382808284376000920182905250938552505050602080830182905260408301829052606090920187905283546001810185559381522081519192600402019081906106d79082610ab7565b5060208281015160018301805460ff1916911515919091179055604080840151600284015560609093015160039283015560008581529190528190208290555181907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709082907f9684b36e8ac6332c160d4d4e14a78ea2679b6484c08726432cf097c99ba978409061076a908a90610b77565b60405180910390a360015460405184916001600160a01b0316907f8bd32f430ff060e6bd204709b3790c9807987263d3230c580dc80b5f89e27186906107b590869086908b90610b8a565b60405180910390a3505095945050505050565b60008083601f8401126107da57600080fd5b50813567ffffffffffffffff8111156107f257600080fd5b60208301915083602082850101111561080a57600080fd5b9250929050565b60008060008060006060868803121561082957600080fd5b853567ffffffffffffffff8082111561084157600080fd5b61084d89838a016107c8565b9097509550602088013591508082111561086657600080fd5b50610873888289016107c8565b96999598509660400135949350505050565b6000806040838503121561089857600080fd5b50508035926020909101359150565b6000602082840312156108b957600080fd5b5035919050565b6000815180845260005b818110156108e6576020818501810151868301820152016108ca565b506000602082860101526020601f19601f83011685010191505092915050565b60808152600061091960808301876108c0565b9415156020830152506040810192909252606090910152919050565b6001600160a01b038116811461094a57600080fd5b50565b60006020828403121561095f57600080fd5b813561096a81610935565b9392505050565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061099b57607f821691505b6020821081036109bb57634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526022908201527f416363657373206e6f7420616c6c6f7765643a20476f7665726e6f72206f6e6c6040820152613c9760f11b606082015260800190565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b600060208284031215610a4b57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b601f821115610ab257600081815260208120601f850160051c81016020861015610a8f5750805b601f850160051c820191505b81811015610aae57828155600101610a9b565b5050505b505050565b815167ffffffffffffffff811115610ad157610ad1610a52565b610ae581610adf8454610987565b84610a68565b602080601f831160018114610b1a5760008415610b025750858301515b600019600386901b1c1916600185901b178555610aae565b600085815260208120601f198616915b82811015610b4957888601518255948401946001909101908401610b2a565b5085821015610b675787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600061096a60208301846108c0565b838152826020820152606060408201526000610ba960608301846108c0565b9594505050505056fea2646970667358221220a719b050bca90307d777fff41b441c2f1ee3ba5b5292ac5605dfd7ab9b7b043964736f6c63430008120033", + "devdoc": { + "events": { + "CrossChainDisputeRequest(address,uint256,address,uint256,uint256,uint256,string)": { + "details": "To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.", + "params": { + "_arbitrable": "The address of the Arbitrable contract.", + "_arbitrableChainId": "The chain ID of the Arbitrable contract.", + "_arbitrableDisputeID": "The ID of the dispute in the Arbitrable contract.", + "_arbitrator": "The arbitrator of the contract.", + "_externalDisputeID": "An identifier created outside Kleros by the protocol requesting arbitration.", + "_templateId": "The ID of the dispute template. Should not be used with _templateUri.", + "_templateUri": "IPFS path to the dispute template starting with '/ipfs/'. Should not be used with _templateId." + } + }, + "DisputeRequest(address,uint256,uint256,uint256,string)": { + "details": "To be emitted when a dispute is created to link the correct meta-evidence to the disputeID.", + "params": { + "_arbitrableDisputeID": "The ID of the dispute in the Arbitrable contract.", + "_arbitrator": "The arbitrator of the contract.", + "_externalDisputeID": "An identifier created outside Kleros by the protocol requesting arbitration.", + "_templateId": "The ID of the dispute template. Should not be used with _templateUri.", + "_templateUri": "The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId." + } + }, + "DisputeTemplate(uint256,string,string)": { + "details": "To be emitted when a new dispute template is created.", + "params": { + "_templateId": "The ID of the dispute template.", + "_templateTag": "An optional tag for the dispute template, such as \"registration\" or \"removal\".", + "data": "The template data." + } + }, + "Ruling(address,uint256,uint256)": { + "details": "To be raised when a ruling is given.", + "params": { + "_arbitrator": "The arbitrator giving the ruling.", + "_disputeID": "ID of the dispute in the Arbitrator contract.", + "_ruling": "The ruling which was given." + } + } + }, + "kind": "dev", + "methods": { + "changeGovernor(address)": { + "details": "Changes the governor.", + "params": { + "_governor": "The address of the new governor." + } + }, + "constructor": { + "details": "Constructor", + "params": { + "_arbitrator": "Target global arbitrator for any disputes." + } + }, + "createDisputeForTemplate(bytes,string,uint256)": { + "details": "Calls createDispute function of the specified arbitrator to create a dispute. Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract.", + "params": { + "_arbitratorExtraData": "Extra data for the arbitrator of the dispute.", + "_disputeTemplate": "Dispute template.", + "_numberOfRulingOptions": "Number of ruling options." + }, + "returns": { + "disputeID": "Dispute id (on arbitrator side) of the created dispute." + } + }, + "createDisputeForTemplateUri(bytes,string,uint256)": { + "details": "Calls createDispute function of the specified arbitrator to create a dispute. Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract.", + "params": { + "_arbitratorExtraData": "Extra data for the arbitrator of the dispute.", + "_disputeTemplateUri": "The URI to the dispute template. For example on IPFS: starting with '/ipfs/'.", + "_numberOfRulingOptions": "Number of ruling options." + }, + "returns": { + "disputeID": "Dispute id (on arbitrator side) of the created dispute." + } + }, + "rule(uint256,uint256)": { + "details": "To be called by the arbitrator of the dispute, to declare the winning ruling.", + "params": { + "_externalDisputeID": "ID of the dispute in arbitrator contract.", + "_ruling": "The ruling choice of the arbitration." + } + } + }, + "title": "DisputeResolver DisputeResolver contract adapted for V2 from https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol.", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 129, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "governor", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 132, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "arbitrator", + "offset": 0, + "slot": "1", + "type": "t_contract(IArbitratorV2)112" + }, + { + "astId": 136, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "disputes", + "offset": 0, + "slot": "2", + "type": "t_array(t_struct(DisputeStruct)127_storage)dyn_storage" + }, + { + "astId": 140, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "arbitratorDisputeIDToLocalID", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(DisputeStruct)127_storage)dyn_storage": { + "base": "t_struct(DisputeStruct)127_storage", + "encoding": "dynamic_array", + "label": "struct DisputeResolver.DisputeStruct[]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IArbitratorV2)112": { + "encoding": "inplace", + "label": "contract IArbitratorV2", + "numberOfBytes": "20" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(DisputeStruct)127_storage": { + "encoding": "inplace", + "label": "struct DisputeResolver.DisputeStruct", + "members": [ + { + "astId": 120, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "arbitratorExtraData", + "offset": 0, + "slot": "0", + "type": "t_bytes_storage" + }, + { + "astId": 122, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "isRuled", + "offset": 0, + "slot": "1", + "type": "t_bool" + }, + { + "astId": 124, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "ruling", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 126, + "contract": "src/arbitration/arbitrables/DisputeResolver.sol:DisputeResolver", + "label": "numberOfRulingOptions", + "offset": 0, + "slot": "3", + "type": "t_uint256" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} diff --git a/contracts/package.json b/contracts/package.json index 3f1dceb05..9f8bfb0dc 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -31,7 +31,7 @@ "watch": "hardhat watch", "docgen": "hardhat docgen", "docserve": "scripts/docPreprocess.sh && forge doc --serve", - "docbuild": "scripts/docPreprocess.sh && forge doc --build --out dist", + "docbuild": "scripts/docPreprocess.sh && forge doc --build --out dist && scripts/docPostprocess.sh", "publish": "yarn npm publish --access public --tag $(cat package.json | jq .version)" }, "devDependencies": { diff --git a/contracts/scripts/console-init-chiado-resolver.ts b/contracts/scripts/console-init-chiado-resolver.ts new file mode 100644 index 000000000..480c7c471 --- /dev/null +++ b/contracts/scripts/console-init-chiado-resolver.ts @@ -0,0 +1,25 @@ +// TODO: SDK utility formatDisputeExtraData(_courtId, _nbOfJurors): string +// TODO: SDK utility formatDisputeExtraData(_courtId, _nbOfJurors, disputeKitId): string + +// On the foreign chain +const extraData = + "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003"; +const template = `{"$schema":"../NewDisputeTemplate.schema.json","title":"Add an entry to Ledger Contract Domain Name registry v2","description":"Someone requested to add an entry to Ledger Contract Domain Name registry v2","question":"Does the entry comply with the required criteria?","answers":[{"title":"Yes, Add It","description":"Select this if you think the entry complies with the required criteria and should be added."},{"title":"No, Don't Add It","description":"Select this if you think the entry does not comply with the required criteria and should not be added."}],"policyURI":"/ipfs/QmdvkC5Djgk8MfX5ijJR3NJzmvGugUqvui7bKuTErSD6cE/contract-domain-name-registry-for-ledger-policy-3-.pdf","frontendUrl":"https://curate.kleros.io/tcr/%s/%s/%s","arbitrableChainID":"100","arbitrableAddress":"0x957A53A994860BE4750810131d9c876b2f52d6E1","arbitratorChainID":"421613","arbitratorAddress":"0xD08Ab99480d02bf9C092828043f611BcDFEA917b","category":"Curated Lists","specification":"KIP88"}`; +const nbOfChoices = 2; +const cost = await foreignGateway.arbitrationCost(extraData); +const tx = await resolver.createDisputeForTemplate(extraData, template, nbOfChoices, { value: cost }); + +// Or to test the fallback to IPFS +const uri = "/ipfs/QmQ9...."; +const tx2 = await resolver.createDisputeForTemplateUri(extraData, uri, nbOfChoices, { value: cost }); + +// Then a relayer must relay the dispute on the HomeGateway... + +core = await ethers.getContract("KlerosCore"); +resolver = await ethers.getContract("DisputeResolver"); +extraData = + "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003"; +template = `{"$schema":"../NewDisputeTemplate.schema.json","title":"Add an entry to Ledger Contract Domain Name registry v2","description":"Someone requested to add an entry to Ledger Contract Domain Name registry v2","question":"Does the entry comply with the required criteria?","answers":[{"title":"Yes, Add It","description":"Select this if you think the entry complies with the required criteria and should be added."},{"title":"No, Don't Add It","description":"Select this if you think the entry does not comply with the required criteria and should not be added."}],"policyURI":"/ipfs/QmdvkC5Djgk8MfX5ijJR3NJzmvGugUqvui7bKuTErSD6cE/contract-domain-name-registry-for-ledger-policy-3-.pdf","frontendUrl":"https://curate.kleros.io/tcr/%s/%s/%s","arbitrableChainID":"100","arbitrableAddress":"0x957A53A994860BE4750810131d9c876b2f52d6E1","arbitratorChainID":"421613","arbitratorAddress":"0xD08Ab99480d02bf9C092828043f611BcDFEA917b","category":"Curated Lists","specification":"KIP88"}`; +nbOfChoices = 2; +cost = await core.arbitrationCost(extraData); +tx = await resolver.createDisputeForTemplate(extraData, template, nbOfChoices, { value: cost }); diff --git a/contracts/scripts/console-init-chiado.ts b/contracts/scripts/console-init-chiado.ts index 559e5a5e9..97d9e2ac1 100644 --- a/contracts/scripts/console-init-chiado.ts +++ b/contracts/scripts/console-init-chiado.ts @@ -1,7 +1,6 @@ // .load scripts/console-init-chiado.ts receiver = await ethers.getContract("VeaInboxArbToGnosisDevnet"); -// gateway = await ethers.getContract("ForeignGatewayOnGnosis"); -gateway = await ethers.getContractAt("ForeignGatewayOnGnosis", "0x8F1a2B8F9b04320375856580Fc6B1669Cb12a9EE"); +gateway = await ethers.getContract("ForeignGatewayOnGnosis"); weth = await ethers.getContract("WETH"); wethFaucet = await ethers.getContract("WETHFaucet"); wpnk = await ethers.getContract("WrappedPinakionV2"); diff --git a/contracts/scripts/docPostprocess.sh b/contracts/scripts/docPostprocess.sh new file mode 100755 index 000000000..a52c0878c --- /dev/null +++ b/contracts/scripts/docPostprocess.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Forge doc assumes that the code is in the top-level folder. +# We need to add contracts/ to the path +find $SCRIPT_DIR/../dist -type f \( -name "*.md" -o -name "*.html" \) \ + | xargs sed -i.bak 's|\(github.com/kleros/kleros-v2/.*\)\(/src\)|\1/contracts\2|g' + diff --git a/contracts/src/arbitration/CentralizedArbitrator.sol b/contracts/src/arbitration/CentralizedArbitrator.sol index 7879d89cd..7cfd4768b 100644 --- a/contracts/src/arbitration/CentralizedArbitrator.sol +++ b/contracts/src/arbitration/CentralizedArbitrator.sol @@ -2,12 +2,12 @@ pragma solidity 0.8.18; -import "./IArbitrator.sol"; +import {IArbitrableV2, IArbitratorV2} from "./interfaces/IArbitratorV2.sol"; /// @title Centralized Arbitrator -/// @dev This is a centralized arbitrator deciding alone on the result of disputes. It illustrates how IArbitrator interface can be implemented. +/// @dev This is a centralized arbitrator deciding alone on the result of disputes. It illustrates how IArbitratorV2 interface can be implemented. /// Note that this contract supports appeals. The ruling given by the arbitrator can be appealed by crowdfunding a desired choice. -contract CentralizedArbitrator is IArbitrator { +contract CentralizedArbitrator is IArbitratorV2 { // ************************************* // // * Enums / Structs * // // ************************************* // @@ -19,7 +19,7 @@ contract CentralizedArbitrator is IArbitrator { } struct DisputeStruct { - IArbitrable arbitrated; // The address of the arbitrable contract. + IArbitrableV2 arbitrated; // The address of the arbitrable contract. bytes arbitratorExtraData; // Extra data for the arbitrator. uint256 choices; // The number of choices the arbitrator can choose from. uint256 appealPeriodStart; // Time when the appeal funding becomes possible. @@ -61,12 +61,12 @@ contract CentralizedArbitrator is IArbitrator { /// @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); + event AppealPossible(uint256 indexed _disputeID, IArbitrableV2 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); + event AppealDecision(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable); /// @dev Raised when a contribution is made, inside fundAppeal function. /// @param _disputeID ID of the dispute. @@ -151,11 +151,7 @@ contract CentralizedArbitrator is IArbitrator { // * State Modifiers * // // ************************************* // - /// @dev Create a dispute. Must be called by the arbitrable contract. - /// Must be paid at least arbitrationCost(). - /// @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. + /// @inheritdoc IArbitratorV2 function createDispute( uint256 _choices, bytes calldata _extraData @@ -164,7 +160,7 @@ contract CentralizedArbitrator is IArbitrator { disputeID = disputes.length; disputes.push( DisputeStruct({ - arbitrated: IArbitrable(msg.sender), + arbitrated: IArbitrableV2(msg.sender), arbitratorExtraData: _extraData, choices: _choices, appealPeriodStart: 0, @@ -175,10 +171,10 @@ contract CentralizedArbitrator is IArbitrator { ); disputeIDtoRoundArray[disputeID].push(); - emit DisputeCreation(disputeID, IArbitrable(msg.sender)); + emit DisputeCreation(disputeID, IArbitrableV2(msg.sender)); } - /// @inheritdoc IArbitrator + /// @inheritdoc IArbitratorV2 function createDispute( uint256 /*_choices*/, bytes calldata /*_extraData*/, @@ -188,7 +184,7 @@ contract CentralizedArbitrator is IArbitrator { revert("Not supported"); } - /// @dev TRUSTED. Manages contributions, and appeals a dispute if at least two choices are fully funded. This function allows the appeals to be crowdfunded. + /// @dev Manages contributions, and appeals a dispute if at least two choices are fully funded. This function allows the appeals to be crowdfunded. /// Note that the surplus deposit will be reimbursed. /// @param _disputeID Index of the dispute to appeal. /// @param _choice A choice that receives funding. @@ -366,4 +362,10 @@ contract CentralizedArbitrator is IArbitrator { } return (start, end); } + + function currentRuling( + uint256 /*_disputeID*/ + ) public pure returns (uint256 /*ruling*/, bool /*tied*/, bool /*overridden*/) { + revert("Not supported"); + } } diff --git a/contracts/src/arbitration/IArbitrable.sol b/contracts/src/arbitration/IArbitrable.sol deleted file mode 100644 index cac0fa6af..000000000 --- a/contracts/src/arbitration/IArbitrable.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.18; - -import "./IArbitrator.sol"; - -/// @title IArbitrable -/// Arbitrable interface. Note that this interface follows the ERC-792 standard. -/// 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; -} diff --git a/contracts/src/arbitration/KlerosCore.sol b/contracts/src/arbitration/KlerosCore.sol index ead08ac47..882e5b57d 100644 --- a/contracts/src/arbitration/KlerosCore.sol +++ b/contracts/src/arbitration/KlerosCore.sol @@ -9,14 +9,14 @@ pragma solidity 0.8.18; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "./IArbitrator.sol"; -import "./IDisputeKit.sol"; -import "./ISortitionModule.sol"; +import {IArbitrableV2, IArbitratorV2} from "./interfaces/IArbitratorV2.sol"; +import "./interfaces/IDisputeKit.sol"; +import "./interfaces/ISortitionModule.sol"; /// @title KlerosCore /// Core arbitrator contract for Kleros v2. /// Note that this contract trusts the token and the dispute kit contracts. -contract KlerosCore is IArbitrator { +contract KlerosCore is IArbitratorV2 { // ************************************* // // * Enums / Structs * // // ************************************* // @@ -44,7 +44,7 @@ contract KlerosCore is IArbitrator { struct Dispute { uint96 courtID; // The ID of the court the dispute is in. - IArbitrable arbitrated; // The arbitrable contract. + IArbitrableV2 arbitrated; // The arbitrable contract. Period period; // The current period of the dispute. bool ruled; // True if the ruling has been executed, false otherwise. uint256 lastPeriodChange; // The last time the period was changed. @@ -126,8 +126,8 @@ contract KlerosCore is IArbitrator { event StakeSet(address indexed _address, uint256 _courtID, uint256 _amount); event StakeDelayed(address indexed _address, uint256 _courtID, uint256 _amount, uint256 _penalty); event NewPeriod(uint256 indexed _disputeID, Period _period); - event AppealPossible(uint256 indexed _disputeID, IArbitrable indexed _arbitrable); - event AppealDecision(uint256 indexed _disputeID, IArbitrable indexed _arbitrable); + event AppealPossible(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable); + event AppealDecision(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable); event Draw(address indexed _address, uint256 indexed _disputeID, uint256 _roundID, uint256 _voteID); event CourtCreated( uint256 indexed _courtID, @@ -496,7 +496,7 @@ contract KlerosCore is IArbitrator { _setStakeForAccount(_account, _courtID, _stake, _penalty); } - /// @inheritdoc IArbitrator + /// @inheritdoc IArbitratorV2 function createDispute( uint256 _numberOfChoices, bytes memory _extraData @@ -509,7 +509,7 @@ contract KlerosCore is IArbitrator { disputeID = disputes.length; Dispute storage dispute = disputes.push(); dispute.courtID = courtID; - dispute.arbitrated = IArbitrable(msg.sender); + dispute.arbitrated = IArbitrableV2(msg.sender); dispute.lastPeriodChange = block.timestamp; IDisputeKit disputeKit = disputeKitNodes[disputeKitID].disputeKit; @@ -523,10 +523,10 @@ contract KlerosCore is IArbitrator { sortitionModule.createDisputeHook(disputeID, 0); // Default round ID. disputeKit.createDispute(disputeID, _numberOfChoices, _extraData, round.nbVotes); - emit DisputeCreation(disputeID, IArbitrable(msg.sender)); + emit DisputeCreation(disputeID, IArbitrableV2(msg.sender)); } - /// @inheritdoc IArbitrator + /// @inheritdoc IArbitratorV2 function createDispute( uint256 _numberOfChoices, bytes calldata _extraData, @@ -543,7 +543,7 @@ contract KlerosCore is IArbitrator { disputeID = disputes.length; Dispute storage dispute = disputes.push(); dispute.courtID = courtID; - dispute.arbitrated = IArbitrable(msg.sender); + dispute.arbitrated = IArbitrableV2(msg.sender); dispute.lastPeriodChange = block.timestamp; IDisputeKit disputeKit = disputeKitNodes[disputeKitID].disputeKit; @@ -560,7 +560,7 @@ contract KlerosCore is IArbitrator { sortitionModule.createDisputeHook(disputeID, 0); // Default round ID. disputeKit.createDispute(disputeID, _numberOfChoices, _extraData, round.nbVotes); - emit DisputeCreation(disputeID, IArbitrable(msg.sender)); + emit DisputeCreation(disputeID, IArbitrableV2(msg.sender)); } /// @dev Passes the period of a specified dispute. @@ -904,7 +904,7 @@ contract KlerosCore is IArbitrator { } } - /// @dev Executes a specified dispute's ruling. UNTRUSTED. + /// @dev Executes a specified dispute's ruling. /// @param _disputeID The ID of the dispute. function executeRuling(uint256 _disputeID) external { Dispute storage dispute = disputes[_disputeID]; diff --git a/contracts/src/arbitration/KlerosGovernor.sol b/contracts/src/arbitration/KlerosGovernor.sol index 20af82ff5..32b4f8c33 100644 --- a/contracts/src/arbitration/KlerosGovernor.sol +++ b/contracts/src/arbitration/KlerosGovernor.sol @@ -7,12 +7,11 @@ pragma solidity 0.8.18; -import "./IArbitrable.sol"; -import "../evidence/IMetaEvidence.sol"; +import {IArbitrableV2, IArbitratorV2} from "./interfaces/IArbitrableV2.sol"; import "../libraries/CappedMath.sol"; /// @title KlerosGovernor for V2. Note that appeal functionality and evidence submission will be handled by the court. -contract KlerosGovernor is IArbitrable, IMetaEvidence { +contract KlerosGovernor is IArbitrableV2 { using CappedMath for uint256; // ************************************* // @@ -52,9 +51,9 @@ contract KlerosGovernor is IArbitrable, IMetaEvidence { uint256 approvalTime; // The time when the list was approved. } - IArbitrator public arbitrator; // Arbitrator contract. + IArbitratorV2 public arbitrator; // Arbitrator contract. bytes public arbitratorExtraData; // Extra data for arbitrator. - uint256 public metaEvidenceUpdates; // The number of times the meta evidence has been updated. Used to track the latest meta evidence ID. + uint256 public disputeTemplates; // The number of dispute templates created. uint256 public submissionBaseDeposit; // The base deposit in wei that needs to be paid in order to submit the list. uint256 public submissionTimeout; // Time in seconds allowed for submitting the lists. Once it's passed the contract enters the approval period. @@ -115,15 +114,15 @@ contract KlerosGovernor is IArbitrable, IMetaEvidence { /// @dev Constructor. /// @param _arbitrator The arbitrator of the contract. /// @param _arbitratorExtraData Extra data for the arbitrator. - /// @param _metaEvidence The URI of the meta evidence file. + /// @param _templateData The dispute template data. /// @param _submissionBaseDeposit The base deposit required for submission. /// @param _submissionTimeout Time in seconds allocated for submitting transaction list. /// @param _executionTimeout Time in seconds after approval that allows to execute transactions of the approved list. /// @param _withdrawTimeout Time in seconds after submission that allows to withdraw submitted list. constructor( - IArbitrator _arbitrator, + IArbitratorV2 _arbitrator, bytes memory _arbitratorExtraData, - string memory _metaEvidence, + string memory _templateData, uint256 _submissionBaseDeposit, uint256 _submissionTimeout, uint256 _executionTimeout, @@ -139,7 +138,7 @@ contract KlerosGovernor is IArbitrable, IMetaEvidence { withdrawTimeout = _withdrawTimeout; sessions.push(); - emit MetaEvidence(metaEvidenceUpdates, _metaEvidence); + emit DisputeTemplate(disputeTemplates++, "", _templateData); } /// @dev Changes the value of the base deposit required for submitting a list. @@ -171,18 +170,17 @@ contract KlerosGovernor is IArbitrable, IMetaEvidence { /// @param _arbitrator The new trusted arbitrator. /// @param _arbitratorExtraData The extra data used by the new arbitrator. function changeArbitrator( - IArbitrator _arbitrator, + IArbitratorV2 _arbitrator, bytes memory _arbitratorExtraData ) external onlyByGovernor duringSubmissionPeriod { arbitrator = _arbitrator; arbitratorExtraData = _arbitratorExtraData; } - /// @dev Update the meta evidence used for disputes. - /// @param _metaEvidence URI to the new meta evidence file. - function changeMetaEvidence(string memory _metaEvidence) external onlyByGovernor { - metaEvidenceUpdates++; - emit MetaEvidence(metaEvidenceUpdates, _metaEvidence); + /// @dev Update the dispute template data. + /// @param _templateData The new dispute template data. + function changeDisputeTemplate(string memory _templateData) external onlyByGovernor { + emit DisputeTemplate(disputeTemplates++, "", _templateData); } /// @dev Creates transaction list based on input parameters and submits it for potential approval and execution. @@ -265,7 +263,7 @@ contract KlerosGovernor is IArbitrable, IMetaEvidence { reservedETH = reservedETH.subCap(submission.deposit); } - /// @dev Approves a transaction list or creates a dispute if more than one list was submitted. TRUSTED. + /// @dev Approves a transaction list or creates a dispute if more than one list was submitted. /// If nothing was submitted changes session. function executeSubmissions() external duringApprovalPeriod { Session storage session = sessions[sessions.length - 1]; @@ -296,7 +294,7 @@ contract KlerosGovernor is IArbitrable, IMetaEvidence { session.sumDeposit = session.sumDeposit.subCap(arbitrationCost); reservedETH = reservedETH.subCap(arbitrationCost); - emit Dispute(arbitrator, session.disputeID, metaEvidenceUpdates, sessions.length - 1); + emit DisputeRequest(arbitrator, session.disputeID, sessions.length - 1, disputeTemplates, ""); } } @@ -325,10 +323,10 @@ contract KlerosGovernor is IArbitrable, IMetaEvidence { session.ruling = _ruling; sessions.push(); - emit Ruling(IArbitrator(msg.sender), _disputeID, _ruling); + emit Ruling(IArbitratorV2(msg.sender), _disputeID, _ruling); } - /// @dev Executes selected transactions of the list. UNTRUSTED. + /// @dev Executes selected transactions of the list. /// @param _listID The index of the transaction list in the array of lists. /// @param _cursor Index of the transaction from which to start executing. /// @param _count Number of transactions to execute. Executes until the end if set to "0" or number higher than number of transactions in the list. diff --git a/contracts/src/arbitration/SortitionModule.sol b/contracts/src/arbitration/SortitionModule.sol index 23e652c39..ac9eef13a 100644 --- a/contracts/src/arbitration/SortitionModule.sol +++ b/contracts/src/arbitration/SortitionModule.sol @@ -10,9 +10,9 @@ pragma solidity 0.8.18; -import "../arbitration/KlerosCore.sol"; -import "./ISortitionModule.sol"; -import "../arbitration/IDisputeKit.sol"; +import "./KlerosCore.sol"; +import "./interfaces/ISortitionModule.sol"; +import "./interfaces/IDisputeKit.sol"; import "../rng/RNG.sol"; /// @title SortitionModule diff --git a/contracts/src/arbitration/arbitrables/ArbitrableExample.sol b/contracts/src/arbitration/arbitrables/ArbitrableExample.sol index 06d0f9330..ee3ab26f1 100644 --- a/contracts/src/arbitration/arbitrables/ArbitrableExample.sol +++ b/contracts/src/arbitration/arbitrables/ArbitrableExample.sol @@ -3,85 +3,87 @@ pragma solidity 0.8.18; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "../IArbitrable.sol"; -import "../../evidence/IMetaEvidence.sol"; +import {IArbitrableV2, IArbitratorV2} from "../interfaces/IArbitrableV2.sol"; /// @title ArbitrableExample /// An example of an arbitrable contract which connects to the arbitator that implements the updated interface. -contract ArbitrableExample is IArbitrable, IMetaEvidence { +contract ArbitrableExample is IArbitrableV2 { struct DisputeStruct { bool isRuled; // Whether the dispute has been ruled or not. uint256 ruling; // Ruling given by the arbitrator. uint256 numberOfRulingOptions; // The number of choices the arbitrator can give. } + event Action(string indexed _action); + address public immutable governor; - IArbitrator public arbitrator; // Arbitrator is set in constructor and never changed. + IArbitratorV2 public arbitrator; // Arbitrator is set in constructor. + uint256 public disputeTemplates; // The number of dispute templates created. ERC20 public immutable weth; // The WETH token. mapping(uint256 => uint256) public externalIDtoLocalID; // Maps external (arbitrator side) dispute IDs to local dispute IDs. DisputeStruct[] public disputes; // Stores the disputes' info. disputes[disputeID]. /// @dev Constructor /// @param _arbitrator The arbitrator to rule on created disputes. - /// @param _metaEvidenceID Unique identifier of meta-evidence. - /// @param _metaEvidence The URI of the meta evidence object for evidence submissions requests. - constructor(IArbitrator _arbitrator, uint256 _metaEvidenceID, string memory _metaEvidence, ERC20 _weth) { + /// @param _templateData The dispute template data. + /// @param _weth The WETH token. + constructor(IArbitratorV2 _arbitrator, string memory _templateData, ERC20 _weth) { governor = msg.sender; arbitrator = _arbitrator; weth = _weth; - emit MetaEvidence(_metaEvidenceID, _metaEvidence); + emit DisputeTemplate(disputeTemplates++, "", _templateData); } - /// @dev TRUSTED. Calls createDispute function of the specified arbitrator to create a dispute. + /// @dev Calls createDispute function of the specified arbitrator to create a dispute. /// Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract. - /// @param _numberOfRulingOptions Number of ruling options. Must be greater than 1, otherwise there is nothing to choose from. + /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri. + /// @param _action The action that requires arbitration. /// @param _arbitratorExtraData Extra data for the arbitrator. - /// @param _evidenceGroupID Unique identifier of the evidence group that is linked to this dispute. /// @return disputeID Dispute id (on arbitrator side) of the dispute created. function createDispute( - uint256 _numberOfRulingOptions, - bytes calldata _arbitratorExtraData, - uint256 _metaEvidenceID, - uint256 _evidenceGroupID + uint256 _templateId, + string calldata _action, + bytes calldata _arbitratorExtraData ) external payable returns (uint256 disputeID) { - require(_numberOfRulingOptions > 1, "Incorrect number of choices"); + emit Action(_action); + uint256 numberOfRulingOptions = 2; uint256 localDisputeID = disputes.length; - disputes.push(DisputeStruct({isRuled: false, ruling: 0, numberOfRulingOptions: _numberOfRulingOptions})); - - disputeID = arbitrator.createDispute{value: msg.value}(_numberOfRulingOptions, _arbitratorExtraData); + disputes.push(DisputeStruct({isRuled: false, ruling: 0, numberOfRulingOptions: numberOfRulingOptions})); + disputeID = arbitrator.createDispute{value: msg.value}(numberOfRulingOptions, _arbitratorExtraData); externalIDtoLocalID[disputeID] = localDisputeID; - emit Dispute(arbitrator, disputeID, _metaEvidenceID, _evidenceGroupID); + uint256 externalDisputeID = uint256(keccak256(abi.encodePacked(_action))); + emit DisputeRequest(arbitrator, disputeID, externalDisputeID, _templateId, ""); } - /// @dev TRUSTED. Calls createDispute function of the specified arbitrator to create a dispute. + /// @dev Calls createDispute function of the specified arbitrator to create a dispute. /// Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract. - /// @param _numberOfRulingOptions Number of ruling options. Must be greater than 1, otherwise there is nothing to choose from. + /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri. + /// @param _action The action that requires arbitration. /// @param _arbitratorExtraData Extra data for the arbitrator. - /// @param _metaEvidenceID Unique identifier of meta-evidence. - /// @param _evidenceGroupID Unique identifier of the evidence group that is linked to this dispute. /// @param _feeInWeth Amount of fees in WETH for the arbitrator. /// @return disputeID Dispute id (on arbitrator side) of the dispute created. function createDispute( - uint256 _numberOfRulingOptions, + uint256 _templateId, + string calldata _action, bytes calldata _arbitratorExtraData, - uint256 _metaEvidenceID, - uint256 _evidenceGroupID, uint256 _feeInWeth ) external payable returns (uint256 disputeID) { - require(_numberOfRulingOptions > 1, "Incorrect number of choices"); + emit Action(_action); + uint256 numberOfRulingOptions = 2; uint256 localDisputeID = disputes.length; - disputes.push(DisputeStruct({isRuled: false, ruling: 0, numberOfRulingOptions: _numberOfRulingOptions})); + disputes.push(DisputeStruct({isRuled: false, ruling: 0, numberOfRulingOptions: numberOfRulingOptions})); require(weth.transferFrom(msg.sender, address(this), _feeInWeth), "Not enough WETH for arbitration"); weth.increaseAllowance(address(arbitrator), _feeInWeth); - disputeID = arbitrator.createDispute(_numberOfRulingOptions, _arbitratorExtraData, address(weth), _feeInWeth); + disputeID = arbitrator.createDispute(numberOfRulingOptions, _arbitratorExtraData); externalIDtoLocalID[disputeID] = localDisputeID; - emit Dispute(arbitrator, disputeID, _metaEvidenceID, _evidenceGroupID); + uint256 externalDisputeID = uint256(keccak256(abi.encodePacked(_action))); + emit DisputeRequest(arbitrator, disputeID, externalDisputeID, _templateId, ""); } /// @dev To be called by the arbitrator of the dispute, to declare the winning ruling. @@ -97,15 +99,15 @@ contract ArbitrableExample is IArbitrable, IMetaEvidence { dispute.isRuled = true; dispute.ruling = _ruling; - emit Ruling(IArbitrator(msg.sender), _externalDisputeID, dispute.ruling); + emit Ruling(IArbitratorV2(msg.sender), _externalDisputeID, dispute.ruling); } - function changeMetaEvidence(uint256 _metaEvidenceID, string memory _metaEvidence) external { + function changeDisputeTemplate(string memory _templateData) external { require(msg.sender == governor, "Not authorized: governor only."); - emit MetaEvidence(_metaEvidenceID, _metaEvidence); + emit DisputeTemplate(disputeTemplates++, "", _templateData); } - function changeArbitrator(IArbitrator _arbitrator) external { + function changeArbitrator(IArbitratorV2 _arbitrator) external { require(msg.sender == governor, "Not authorized: governor only."); arbitrator = _arbitrator; } diff --git a/contracts/src/arbitration/arbitrables/DisputeResolver.sol b/contracts/src/arbitration/arbitrables/DisputeResolver.sol index 92171199e..3ba9c1f4c 100644 --- a/contracts/src/arbitration/arbitrables/DisputeResolver.sol +++ b/contracts/src/arbitration/arbitrables/DisputeResolver.sol @@ -1,18 +1,21 @@ // SPDX-License-Identifier: MIT -/// @custom:authors: [@ferittuncer, @unknownunknown1] +/// @custom:authors: [@ferittuncer, @unknownunknown1, @jaybuidl] /// @custom:reviewers: [] /// @custom:auditors: [] /// @custom:bounties: [] -import "../IArbitrable.sol"; -import "../../evidence/IMetaEvidence.sol"; +import "../interfaces/IArbitrableV2.sol"; pragma solidity 0.8.18; /// @title DisputeResolver -/// DisputeResolver contract adapted for V2 https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol. -contract DisputeResolver is IArbitrable, IMetaEvidence { +/// DisputeResolver contract adapted for V2 from https://github.com/kleros/arbitrable-proxy-contracts/blob/master/contracts/ArbitrableProxy.sol. +contract DisputeResolver is IArbitrableV2 { + // ************************************* // + // * Enums / Structs * // + // ************************************* // + struct DisputeStruct { bytes arbitratorExtraData; // Extra data for the dispute. bool isRuled; // True if the dispute has been ruled. @@ -20,52 +23,79 @@ contract DisputeResolver is IArbitrable, IMetaEvidence { uint256 numberOfRulingOptions; // The number of choices the arbitrator can give. } - IArbitrator public immutable arbitrator; // Arbitrator is set in constructor and never changed. + // ************************************* // + // * Storage * // + // ************************************* // + address public governor; // The governor. + IArbitratorV2 public arbitrator; // The arbitrator. DisputeStruct[] public disputes; // Local disputes. - mapping(uint256 => uint256) public externalIDtoLocalID; // Maps external (arbitrator side) dispute IDs to local dispute IDs. + mapping(uint256 => uint256) public arbitratorDisputeIDToLocalID; // Maps arbitrator-side dispute IDs to local dispute IDs. + + // ************************************* // + // * Constructor * // + // ************************************* // /// @dev Constructor /// @param _arbitrator Target global arbitrator for any disputes. - constructor(IArbitrator _arbitrator) { + constructor(IArbitratorV2 _arbitrator) { + governor = msg.sender; + arbitrator = _arbitrator; + } + + // ************************************* // + // * Governance * // + // ************************************* // + + /// @dev Changes the governor. + /// @param _governor The address of the new governor. + function changeGovernor(address _governor) external { + require(governor == msg.sender, "Access not allowed: Governor only."); + governor = _governor; + } + + function changeArbitrator(IArbitratorV2 _arbitrator) external { + require(governor == msg.sender, "Access not allowed: Governor only."); arbitrator = _arbitrator; } - /// @dev TRUSTED. Calls createDispute function of the specified arbitrator to create a dispute. + // ************************************* // + // * State Modifiers * // + // ************************************* // + + /// @dev Calls createDispute function of the specified arbitrator to create a dispute. /// Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract. /// @param _arbitratorExtraData Extra data for the arbitrator of the dispute. - /// @param _metaevidenceURI Link to metaevidence of the dispute. + /// @param _disputeTemplate Dispute template. /// @param _numberOfRulingOptions Number of ruling options. /// @return disputeID Dispute id (on arbitrator side) of the created dispute. - function createDispute( + function createDisputeForTemplate( bytes calldata _arbitratorExtraData, - string calldata _metaevidenceURI, + string calldata _disputeTemplate, uint256 _numberOfRulingOptions ) external payable returns (uint256 disputeID) { - require(_numberOfRulingOptions > 1, "Should be at least 2 ruling options."); - - disputeID = arbitrator.createDispute{value: msg.value}(_numberOfRulingOptions, _arbitratorExtraData); - uint256 localDisputeID = disputes.length; - disputes.push( - DisputeStruct({ - arbitratorExtraData: _arbitratorExtraData, - isRuled: false, - ruling: 0, - numberOfRulingOptions: _numberOfRulingOptions - }) - ); - - externalIDtoLocalID[disputeID] = localDisputeID; + return _createDispute(_arbitratorExtraData, _disputeTemplate, "", _numberOfRulingOptions); + } - emit MetaEvidence(localDisputeID, _metaevidenceURI); - emit Dispute(arbitrator, disputeID, localDisputeID, localDisputeID); + /// @dev Calls createDispute function of the specified arbitrator to create a dispute. + /// Note that we don’t need to check that msg.value is enough to pay arbitration fees as it’s the responsibility of the arbitrator contract. + /// @param _arbitratorExtraData Extra data for the arbitrator of the dispute. + /// @param _disputeTemplateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. + /// @param _numberOfRulingOptions Number of ruling options. + /// @return disputeID Dispute id (on arbitrator side) of the created dispute. + function createDisputeForTemplateUri( + bytes calldata _arbitratorExtraData, + string calldata _disputeTemplateUri, + uint256 _numberOfRulingOptions + ) external payable returns (uint256 disputeID) { + return _createDispute(_arbitratorExtraData, "", _disputeTemplateUri, _numberOfRulingOptions); } /// @dev To be called by the arbitrator of the dispute, to declare the winning ruling. /// @param _externalDisputeID ID of the dispute in arbitrator contract. /// @param _ruling The ruling choice of the arbitration. function rule(uint256 _externalDisputeID, uint256 _ruling) external override { - uint256 localDisputeID = externalIDtoLocalID[_externalDisputeID]; + uint256 localDisputeID = arbitratorDisputeIDToLocalID[_externalDisputeID]; DisputeStruct storage dispute = disputes[localDisputeID]; require(msg.sender == address(arbitrator), "Only the arbitrator can execute this."); require(_ruling <= dispute.numberOfRulingOptions, "Invalid ruling."); @@ -74,6 +104,35 @@ contract DisputeResolver is IArbitrable, IMetaEvidence { dispute.isRuled = true; dispute.ruling = _ruling; - emit Ruling(IArbitrator(msg.sender), _externalDisputeID, dispute.ruling); + emit Ruling(IArbitratorV2(msg.sender), _externalDisputeID, dispute.ruling); + } + + // ************************************* // + // * Internal * // + // ************************************* // + + function _createDispute( + bytes calldata _arbitratorExtraData, + string memory _disputeTemplate, + string memory _disputeTemplateUri, + uint256 _numberOfRulingOptions + ) internal returns (uint256 disputeID) { + require(_numberOfRulingOptions > 1, "Should be at least 2 ruling options."); + + disputeID = arbitrator.createDispute{value: msg.value}(_numberOfRulingOptions, _arbitratorExtraData); + uint256 localDisputeID = disputes.length; + disputes.push( + DisputeStruct({ + arbitratorExtraData: _arbitratorExtraData, + isRuled: false, + ruling: 0, + numberOfRulingOptions: _numberOfRulingOptions + }) + ); + arbitratorDisputeIDToLocalID[disputeID] = localDisputeID; + + uint256 templateId = localDisputeID; + emit DisputeTemplate(templateId, "", _disputeTemplate); + emit DisputeRequest(arbitrator, disputeID, localDisputeID, templateId, _disputeTemplateUri); } } diff --git a/contracts/src/arbitration/dispute-kits/BaseDisputeKit.sol b/contracts/src/arbitration/dispute-kits/BaseDisputeKit.sol index 6e81c241b..878cf99bf 100644 --- a/contracts/src/arbitration/dispute-kits/BaseDisputeKit.sol +++ b/contracts/src/arbitration/dispute-kits/BaseDisputeKit.sol @@ -8,7 +8,7 @@ pragma solidity 0.8.18; -import "../IDisputeKit.sol"; +import "../interfaces/IDisputeKit.sol"; import "../KlerosCore.sol"; /// @title BaseDisputeKit diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol b/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol index 068cedac6..c31fb9b2f 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol @@ -9,7 +9,7 @@ pragma solidity 0.8.18; import "./BaseDisputeKit.sol"; -import "../../evidence/IEvidence.sol"; +import "../interfaces/IEvidence.sol"; /// @title DisputeKitClassic /// Dispute kit implementation of the Kleros v1 features including: @@ -375,11 +375,11 @@ contract DisputeKitClassic is BaseDisputeKit, IEvidence { } } - /// @dev Submits evidence. - /// @param _evidenceGroupID Unique identifier of the evidence group the evidence belongs to. It's the submitter responsability to submit the right evidence group ID. + /// @dev Submits evidence for a dispute. + /// @param _externalDisputeID Unique identifier for this dispute outside Kleros. It's the submitter responsability to submit the right evidence group ID. /// @param _evidence IPFS path to evidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/evidence.json'. - function submitEvidence(uint256 _evidenceGroupID, string calldata _evidence) external { - emit Evidence(_evidenceGroupID, msg.sender, _evidence); + function submitEvidence(uint256 _externalDisputeID, string calldata _evidence) external { + emit Evidence(_externalDisputeID, msg.sender, _evidence); } // ************************************* // diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol b/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol index 624067146..16d27c9aa 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol @@ -9,7 +9,7 @@ pragma solidity 0.8.18; import "./BaseDisputeKit.sol"; -import "../../evidence/IEvidence.sol"; +import "../interfaces//IEvidence.sol"; interface IProofOfHumanity { /// @dev Return true if the submission is registered and not expired. @@ -395,11 +395,11 @@ contract DisputeKitSybilResistant is BaseDisputeKit, IEvidence { } } - /// @dev Submits evidence. - /// @param _evidenceGroupID Unique identifier of the evidence group the evidence belongs to. It's the submitter responsability to submit the right evidence group ID. + /// @dev Submits evidence for a dispute. + /// @param _externalDisputeID Unique identifier for this dispute outside Kleros. It's the submitter responsability to submit the right evidence group ID. /// @param _evidence IPFS path to evidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/evidence.json'. - function submitEvidence(uint256 _evidenceGroupID, string calldata _evidence) external { - emit Evidence(_evidenceGroupID, msg.sender, _evidence); + function submitEvidence(uint256 _externalDisputeID, string calldata _evidence) external { + emit Evidence(_externalDisputeID, msg.sender, _evidence); } // ************************************* // diff --git a/contracts/src/evidence/EvidenceModule.sol b/contracts/src/arbitration/evidence/EvidenceModule.sol similarity index 86% rename from contracts/src/evidence/EvidenceModule.sol rename to contracts/src/arbitration/evidence/EvidenceModule.sol index ada5c7449..be2b076da 100644 --- a/contracts/src/evidence/EvidenceModule.sol +++ b/contracts/src/arbitration/evidence/EvidenceModule.sol @@ -10,20 +10,20 @@ pragma solidity 0.8.18; // TODO: standard interfaces should be placed in a separated repo (?) -import "../arbitration/IArbitrator.sol"; +import "../interfaces/IArbitratorV2.sol"; /// @title Implementation of the Evidence Standard for cross-chain submissions contract EvidenceModule { - IArbitrator public arbitrator; + IArbitratorV2 public arbitrator; event Evidence( - IArbitrator indexed _arbitrator, + IArbitratorV2 indexed _arbitrator, uint256 indexed _evidenceGroupID, address indexed _party, string _evidence ); - constructor(IArbitrator _arbitrator) { + constructor(IArbitratorV2 _arbitrator) { arbitrator = _arbitrator; } diff --git a/contracts/src/evidence/ModeratedEvidenceModule.sol b/contracts/src/arbitration/evidence/ModeratedEvidenceModule.sol similarity index 92% rename from contracts/src/evidence/ModeratedEvidenceModule.sol rename to contracts/src/arbitration/evidence/ModeratedEvidenceModule.sol index e98c1144c..0cdb300d8 100644 --- a/contracts/src/evidence/ModeratedEvidenceModule.sol +++ b/contracts/src/arbitration/evidence/ModeratedEvidenceModule.sol @@ -10,13 +10,11 @@ pragma solidity 0.8.18; // TODO: standard interfaces should be placed in a separated repo (?) -import "../arbitration/IArbitrable.sol"; -import "../arbitration/IArbitrator.sol"; -import "./IMetaEvidence.sol"; -import "../libraries/CappedMath.sol"; +import {IArbitrableV2, IArbitratorV2} from "../interfaces/IArbitrableV2.sol"; +import "../../libraries/CappedMath.sol"; /// @title Implementation of the Evidence Standard with Moderated Submissions -contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { +contract ModeratedEvidenceModule is IArbitrableV2 { using CappedMath for uint256; // ************************************* // @@ -48,7 +46,7 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { } struct ArbitratorData { - uint256 metaEvidenceUpdates; // The meta evidence to be used in disputes. + uint256 disputeTemplateId; // The ID of the dispute template used by the arbitrator. bytes arbitratorExtraData; // Extra data for the arbitrator. } @@ -61,8 +59,7 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { mapping(bytes32 => EvidenceData) evidences; // Maps the evidence ID to its data. evidences[evidenceID]. mapping(uint256 => bytes32) public disputeIDtoEvidenceID; // One-to-one relationship between the dispute and the evidence. ArbitratorData[] public arbitratorDataList; // Stores the arbitrator data of the contract. Updated each time the data is changed. - - IArbitrator public immutable arbitrator; // The trusted arbitrator to resolve potential disputes. If it needs to be changed, a new contract can be deployed. + IArbitratorV2 public immutable arbitrator; // The trusted arbitrator to resolve potential disputes. If it needs to be changed, a new contract can be deployed. address public governor; // The address that can make governance changes to the parameters of the contract. uint256 public bondTimeout; // The time in seconds during which the last moderation status can be challenged. uint256 public totalCostMultiplier; // Multiplier of arbitration fees that must be ultimately paid as fee stake. In basis points. @@ -81,14 +78,14 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { // * Events * // // ************************************* // - /// @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). + /// @dev To be raised when a moderated 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 _externalDisputeID Unique identifier for this dispute outside Kleros. It's the submitter responsability to submit the right evidence group ID. /// @param _party The address of the party submiting the evidence. Note that 0x0 refers to evidence not submitted by any party. /// @param _evidence IPFS path to evidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/evidence.json' - event Evidence( - IArbitrator indexed _arbitrator, - uint256 indexed _evidenceGroupID, + event ModeratedEvidence( + IArbitratorV2 indexed _arbitrator, + uint256 indexed _externalDisputeID, address indexed _party, string _evidence ); @@ -109,15 +106,15 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { /// @param _initialDepositMultiplier Multiplier of arbitration fees that must be paid as initial stake for submitting evidence. In basis points. /// @param _bondTimeout The time in seconds during which the last moderation status can be challenged. /// @param _arbitratorExtraData Extra data for the trusted arbitrator contract. - /// @param _metaEvidence The URI of the meta evidence object for evidence submissions requests. + /// @param _templateData The dispute template data. constructor( - IArbitrator _arbitrator, + IArbitratorV2 _arbitrator, address _governor, uint256 _totalCostMultiplier, uint256 _initialDepositMultiplier, uint256 _bondTimeout, bytes memory _arbitratorExtraData, - string memory _metaEvidence + string memory _templateData ) { arbitrator = _arbitrator; governor = _governor; @@ -128,7 +125,7 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { ArbitratorData storage arbitratorData = arbitratorDataList.push(); arbitratorData.arbitratorExtraData = _arbitratorExtraData; - emit MetaEvidence(0, _metaEvidence); + emit DisputeTemplate(arbitratorData.disputeTemplateId, "", _templateData); } // ************************************* // @@ -160,18 +157,18 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { bondTimeout = _bondTimeout; } - /// @dev Update the meta evidence used for disputes. - /// @param _newMetaEvidence The meta evidence to be used for future registration request disputes. - function changeMetaEvidence(string calldata _newMetaEvidence) external onlyGovernor { + /// @dev Update the dispute template data. + /// @param _templateData The new dispute template data. + function changeDisputeTemplate(string calldata _templateData) external onlyGovernor { ArbitratorData storage arbitratorData = arbitratorDataList[arbitratorDataList.length - 1]; - uint256 newMetaEvidenceUpdates = arbitratorData.metaEvidenceUpdates + 1; + uint256 newDisputeTemplateId = arbitratorData.disputeTemplateId + 1; arbitratorDataList.push( ArbitratorData({ - metaEvidenceUpdates: newMetaEvidenceUpdates, + disputeTemplateId: newDisputeTemplateId, arbitratorExtraData: arbitratorData.arbitratorExtraData }) ); - emit MetaEvidence(newMetaEvidenceUpdates, _newMetaEvidence); + emit DisputeTemplate(newDisputeTemplateId, "", _templateData); } /// @dev Change the arbitrator to be used for disputes that may be raised in the next requests. The arbitrator is trusted to support appeal period and not reenter. @@ -180,7 +177,7 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { ArbitratorData storage arbitratorData = arbitratorDataList[arbitratorDataList.length - 1]; arbitratorDataList.push( ArbitratorData({ - metaEvidenceUpdates: arbitratorData.metaEvidenceUpdates, + disputeTemplateId: arbitratorData.disputeTemplateId, arbitratorExtraData: _arbitratorExtraData }) ); @@ -215,7 +212,7 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { moderation.arbitratorDataID = arbitratorDataList.length - 1; // When evidence is submitted for a foreign arbitrable, the arbitrator field of Evidence is ignored. - emit Evidence(arbitrator, _evidenceGroupID, msg.sender, _evidence); + emit ModeratedEvidence(arbitrator, _evidenceGroupID, msg.sender, _evidence); } /// @dev Moderates an evidence submission. Requires the contester to at least double the accumulated stake of the oposing party. @@ -266,7 +263,13 @@ contract ModeratedEvidenceModule is IArbitrable, IMetaEvidence { ); disputeIDtoEvidenceID[evidenceData.disputeID] = _evidenceID; - emit Dispute(arbitrator, evidenceData.disputeID, arbitratorData.metaEvidenceUpdates, uint256(_evidenceID)); + emit DisputeRequest( + arbitrator, + evidenceData.disputeID, + uint256(_evidenceID), + arbitratorData.disputeTemplateId, + "" + ); evidenceData.disputed = true; moderation.bondDeadline = 0; moderation.currentWinner = Party.None; diff --git a/contracts/src/arbitration/interfaces/IArbitrableV2.sol b/contracts/src/arbitration/interfaces/IArbitrableV2.sol new file mode 100644 index 000000000..bd782e451 --- /dev/null +++ b/contracts/src/arbitration/interfaces/IArbitrableV2.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.18; + +import "./IArbitratorV2.sol"; + +/// @title IArbitrableV2 +/// @notice 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 IArbitrableV2 { + /// @dev To be emitted when a new dispute template is created. + /// @param _templateId The identifier of the dispute template. + /// @param _templateTag An optional tag for the dispute template, such as "registration" or "removal". + /// @param _templateData The template data. + event DisputeTemplate(uint256 indexed _templateId, string indexed _templateTag, string _templateData); + + /// @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 _arbitrableDisputeID The identifier of the dispute in the Arbitrable contract. + /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration. + /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri. + /// @param _templateUri The URI to the dispute template. For example on IPFS: starting with '/ipfs/'. Should not be used with _templateId. + event DisputeRequest( + IArbitratorV2 indexed _arbitrator, + uint256 indexed _arbitrableDisputeID, + uint256 _externalDisputeID, + uint256 _templateId, + string _templateUri + ); + + /// @dev To be raised when a ruling is given. + /// @param _arbitrator The arbitrator giving the ruling. + /// @param _disputeID The identifier of the dispute in the Arbitrator contract. + /// @param _ruling The ruling which was given. + event Ruling(IArbitratorV2 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 The identifier 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; +} diff --git a/contracts/src/arbitration/IArbitrator.sol b/contracts/src/arbitration/interfaces/IArbitratorV2.sol similarity index 68% rename from contracts/src/arbitration/IArbitrator.sol rename to contracts/src/arbitration/interfaces/IArbitratorV2.sol index 8229d1105..ac613c838 100644 --- a/contracts/src/arbitration/IArbitrator.sol +++ b/contracts/src/arbitration/interfaces/IArbitratorV2.sol @@ -2,37 +2,38 @@ pragma solidity 0.8.18; -import "./IArbitrable.sol"; +import "./IArbitrableV2.sol"; /// @title Arbitrator /// Arbitrator interface that implements the new arbitration standard. -/// Unlike the ERC-792 this standard doesn't have anything related to appeals, so each arbitrator can implement an appeal system that suits it the most. +/// Unlike the ERC-792 this standard is not concerned with appeals, so each arbitrator can implement an appeal system that suits it the most. /// When developing arbitrator contracts we need to: /// - Define the functions for dispute creation (createDispute). Don't forget to store the arbitrated contract and the disputeID (which should be unique, may nbDisputes). /// - Define the functions for cost display (arbitrationCost). /// - Allow giving rulings. For this a function must call arbitrable.rule(disputeID, ruling). -interface IArbitrator { +interface IArbitratorV2 { /// @dev To be emitted when a dispute is created. - /// @param _disputeID ID of the dispute. + /// @param _disputeID The identifier of the dispute in the Arbitrator contract. /// @param _arbitrable The contract which created the dispute. - event DisputeCreation(uint256 indexed _disputeID, IArbitrable indexed _arbitrable); + event DisputeCreation(uint256 indexed _disputeID, IArbitrableV2 indexed _arbitrable); /// @dev To be raised when a ruling is given. /// @param _arbitrable The arbitrable receiving the ruling. - /// @param _disputeID ID of the dispute in the Arbitrator contract. + /// @param _disputeID The identifier of the dispute in the Arbitrator contract. /// @param _ruling The ruling which was given. - event Ruling(IArbitrable indexed _arbitrable, uint256 indexed _disputeID, uint256 _ruling); + event Ruling(IArbitrableV2 indexed _arbitrable, uint256 indexed _disputeID, uint256 _ruling); /// @dev To be emitted when an ERC20 token is added or removed as a method to pay fees. /// @param _token The ERC20 token. /// @param _accepted Whether the token is accepted or not. event AcceptedFeeToken(address indexed _token, bool indexed _accepted); - /// @dev Create a dispute. Must be called by the arbitrable contract. + /// @dev Create a dispute. + /// Must be called by the arbitrable contract. /// Must pay at least arbitrationCost(_extraData). /// @param _numberOfChoices The number of choices the arbitrator can choose from in this dispute. /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes). - /// @return disputeID ID of the dispute created. + /// @return disputeID The identifier of the dispute created. function createDispute( uint256 _numberOfChoices, bytes calldata _extraData @@ -45,7 +46,7 @@ interface IArbitrator { /// @param _extraData Additional info about the dispute. We use it to pass the ID of the dispute's court (first 32 bytes), the minimum number of jurors required (next 32 bytes) and the ID of the specific dispute kit (last 32 bytes). /// @param _feeToken Address of the ERC20 token used to pay fees. /// @param _feeAmount Amount of the ERC20 token used to pay fees. - /// @return disputeID ID of the dispute created. + /// @return disputeID The identifier of the dispute created. function createDispute( uint256 _numberOfChoices, bytes calldata _extraData, @@ -53,8 +54,16 @@ interface IArbitrator { uint256 _feeAmount ) external 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. + /// @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 Required cost of arbitration. function arbitrationCost(bytes calldata _extraData) external view returns (uint256 cost); + + /// @dev Gets the current ruling of a specified dispute. + /// @param _disputeID The ID of the dispute. + /// @return ruling The current ruling. + /// @return tied Whether it's a tie or not. + /// @return overridden Whether the ruling was overridden by appeal funding or not. + function currentRuling(uint256 _disputeID) external view returns (uint256 ruling, bool tied, bool overridden); } diff --git a/contracts/src/arbitration/IDisputeKit.sol b/contracts/src/arbitration/interfaces/IDisputeKit.sol similarity index 99% rename from contracts/src/arbitration/IDisputeKit.sol rename to contracts/src/arbitration/interfaces/IDisputeKit.sol index 1212a580c..4070bfe94 100644 --- a/contracts/src/arbitration/IDisputeKit.sol +++ b/contracts/src/arbitration/interfaces/IDisputeKit.sol @@ -8,7 +8,7 @@ pragma solidity 0.8.18; -import "./IArbitrator.sol"; +import "./IArbitratorV2.sol"; /// @title IDisputeKit /// An abstraction of the Dispute Kits intended for interfacing with KlerosCore. diff --git a/contracts/src/evidence/IEvidence.sol b/contracts/src/arbitration/interfaces/IEvidence.sol similarity index 66% rename from contracts/src/evidence/IEvidence.sol rename to contracts/src/arbitration/interfaces/IEvidence.sol index 808396b62..54b9146a1 100644 --- a/contracts/src/evidence/IEvidence.sol +++ b/contracts/src/arbitration/interfaces/IEvidence.sol @@ -2,13 +2,11 @@ pragma solidity 0.8.18; -import "../arbitration/IArbitrator.sol"; - /// @title IEvidence interface IEvidence { /// @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 _evidenceGroupID Unique identifier of the evidence group the evidence belongs to. + /// @param _externalDisputeID Unique identifier for this dispute outside Kleros. It's the submitter responsability to submit the right external dispute ID. /// @param _party The address of the party submiting the evidence. Note that 0x0 refers to evidence not submitted by any party. /// @param _evidence IPFS path to evidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/evidence.json' - event Evidence(uint256 indexed _evidenceGroupID, address indexed _party, string _evidence); + event Evidence(uint256 indexed _externalDisputeID, address indexed _party, string _evidence); } diff --git a/contracts/src/arbitration/ISortitionModule.sol b/contracts/src/arbitration/interfaces/ISortitionModule.sol similarity index 100% rename from contracts/src/arbitration/ISortitionModule.sol rename to contracts/src/arbitration/interfaces/ISortitionModule.sol diff --git a/contracts/src/gateway/ForeignGateway.sol b/contracts/src/gateway/ForeignGateway.sol index 66b14017c..c2bb41d57 100644 --- a/contracts/src/gateway/ForeignGateway.sol +++ b/contracts/src/gateway/ForeignGateway.sol @@ -8,7 +8,6 @@ pragma solidity 0.8.18; -import "../arbitration/IArbitrable.sol"; import "./interfaces/IForeignGateway.sol"; /// Foreign Gateway @@ -30,15 +29,6 @@ contract ForeignGateway is IForeignGateway { // * Events * // // ************************************* // - event OutgoingDispute( - bytes32 disputeHash, - bytes32 blockhash, - uint256 localDisputeID, - uint256 _choices, - bytes _extraData, - address arbitrable - ); - event ArbitrationCostModified(uint96 indexed _courtID, uint256 _feeForJuror); // ************************************* // @@ -47,7 +37,7 @@ contract ForeignGateway is IForeignGateway { uint256 public constant DEFAULT_NB_OF_JURORS = 3; // The default number of jurors in a dispute. uint256 internal localDisputeID = 1; // The disputeID must start from 1 as the KlerosV1 proxy governor depends on this implementation. We now also depend on localDisputeID not ever being zero. - mapping(uint96 => uint256) public feeForJuror; // feeForJuror[courtID], it mirrors the value on KlerosCore. + mapping(uint96 => uint256) public feeForJuror; // feeForJuror[v2CourtID], it mirrors the value on KlerosCore. address public governor; address public veaOutbox; uint256 public immutable override homeChainID; @@ -115,7 +105,7 @@ contract ForeignGateway is IForeignGateway { } /// @dev Changes the `feeForJuror` property value of a specified court. - /// @param _courtID The ID of the court. + /// @param _courtID The ID of the court on the v2 arbitrator. Not to be confused with the courtID on KlerosLiquid. /// @param _feeForJuror The new value for the `feeForJuror` property value. function changeCourtJurorFee(uint96 _courtID, uint256 _feeForJuror) external onlyByGovernor { feeForJuror[_courtID] = _feeForJuror; @@ -126,7 +116,7 @@ contract ForeignGateway is IForeignGateway { // * State Modifiers * // // ************************************* // - /// @inheritdoc IArbitrator + /// @inheritdoc IArbitratorV2 function createDispute( uint256 _choices, bytes calldata _extraData @@ -140,13 +130,13 @@ contract ForeignGateway is IForeignGateway { } bytes32 disputeHash = keccak256( abi.encodePacked( - chainID, - blockhash(block.number - 1), "createDispute", + blockhash(block.number - 1), + chainID, + msg.sender, disputeID, _choices, - _extraData, - msg.sender + _extraData ) ); @@ -158,11 +148,10 @@ contract ForeignGateway is IForeignGateway { ruled: false }); - emit OutgoingDispute(disputeHash, blockhash(block.number - 1), disputeID, _choices, _extraData, msg.sender); - emit DisputeCreation(disputeID, IArbitrable(msg.sender)); + emit CrossChainDisputeOutgoing(blockhash(block.number - 1), msg.sender, disputeID, _choices, _extraData); } - /// @inheritdoc IArbitrator + /// @inheritdoc IArbitratorV2 function createDispute( uint256 /*_choices*/, bytes calldata /*_extraData*/, @@ -172,7 +161,7 @@ contract ForeignGateway is IForeignGateway { revert("Not supported"); } - /// @inheritdoc IArbitrator + /// @inheritdoc IArbitratorV2 function arbitrationCost(bytes calldata _extraData) public view override returns (uint256 cost) { (uint96 courtID, uint256 minJurors) = extraDataToCourtIDMinJurors(_extraData); cost = feeForJuror[courtID] * minJurors; @@ -193,7 +182,7 @@ contract ForeignGateway is IForeignGateway { dispute.ruled = true; dispute.relayer = _relayer; - IArbitrable arbitrable = IArbitrable(dispute.arbitrable); + IArbitrableV2 arbitrable = IArbitrableV2(dispute.arbitrable); arbitrable.rule(dispute.id, _ruling); } @@ -222,6 +211,12 @@ contract ForeignGateway is IForeignGateway { return homeGateway; } + function currentRuling( + uint256 /*_disputeID*/ + ) public pure returns (uint256 /*ruling*/, bool /*tied*/, bool /*overridden*/) { + revert("Not supported"); + } + // ************************ // // * Internal * // // ************************ // diff --git a/contracts/src/gateway/HomeGateway.sol b/contracts/src/gateway/HomeGateway.sol index 860c289c7..76e652f43 100644 --- a/contracts/src/gateway/HomeGateway.sol +++ b/contracts/src/gateway/HomeGateway.sol @@ -8,7 +8,6 @@ pragma solidity 0.8.18; -import "../arbitration/IArbitrator.sol"; import "./interfaces/IForeignGateway.sol"; import "./interfaces/IHomeGateway.sol"; @@ -29,7 +28,7 @@ contract HomeGateway is IHomeGateway { // ************************************* // address public governor; - IArbitrator public arbitrator; + IArbitratorV2 public arbitrator; IVeaInbox public veaInbox; uint256 public immutable override foreignChainID; address public override foreignGateway; @@ -43,7 +42,7 @@ contract HomeGateway is IHomeGateway { constructor( address _governor, - IArbitrator _arbitrator, + IArbitratorV2 _arbitrator, IVeaInbox _veaInbox, uint256 _foreignChainID, address _foreignGateway @@ -53,8 +52,6 @@ contract HomeGateway is IHomeGateway { veaInbox = _veaInbox; foreignChainID = _foreignChainID; foreignGateway = _foreignGateway; - - emit MetaEvidence(0, "BRIDGE"); } // ************************************* // @@ -70,7 +67,7 @@ contract HomeGateway is IHomeGateway { /// @dev Changes the arbitrator. /// @param _arbitrator The address of the new arbitrator. - function changeArbitrator(IArbitrator _arbitrator) external { + function changeArbitrator(IArbitratorV2 _arbitrator) external { require(governor == msg.sender, "Access not allowed: Governor only."); arbitrator = _arbitrator; } @@ -93,44 +90,47 @@ contract HomeGateway is IHomeGateway { // * State Modifiers * // // ************************************* // - /// @inheritdoc IHomeGateway - function relayCreateDispute( - uint256 _foreignChainID, - bytes32 _foreignBlockHash, - uint256 _foreignDisputeID, - uint256 _choices, - bytes calldata _extraData, - address _arbitrable - ) external payable override { + /// @dev Provide the same parameters as on the foreignChain while creating a dispute. Providing incorrect parameters will create a different hash than on the foreignChain and will not affect the actual dispute/arbitrable's ruling. + /// @param _params The parameters of the dispute, see `RelayCreateDisputeParams`. + function relayCreateDispute(RelayCreateDisputeParams memory _params) external payable override { bytes32 disputeHash = keccak256( abi.encodePacked( - _foreignChainID, - _foreignBlockHash, "createDispute", - _foreignDisputeID, - _choices, - _extraData, - _arbitrable + _params.foreignBlockHash, + _params.foreignChainID, + _params.foreignArbitrable, + _params.foreignDisputeID, + _params.choices, + _params.extraData ) ); - require(_foreignChainID == foreignChainID, "Foreign chain ID not supported"); + require(_params.foreignChainID == foreignChainID, "Foreign chain ID not supported"); RelayedData storage relayedData = disputeHashtoRelayedData[disputeHash]; require(relayedData.relayer == address(0), "Dispute already relayed"); - // TODO: will mostly be replaced by the actual arbitrationCost paid on the foreignChain. - relayedData.arbitrationCost = arbitrator.arbitrationCost(_extraData); + relayedData.arbitrationCost = arbitrator.arbitrationCost(_params.extraData); require(msg.value >= relayedData.arbitrationCost, "Not enough arbitration cost paid"); - uint256 disputeID = arbitrator.createDispute{value: msg.value}(_choices, _extraData); + uint256 disputeID = arbitrator.createDispute{value: msg.value}(_params.choices, _params.extraData); disputeIDtoHash[disputeID] = disputeHash; disputeHashtoID[disputeHash] = disputeID; relayedData.relayer = msg.sender; - emit Dispute(arbitrator, disputeID, 0, 0); + emit DisputeRequest(arbitrator, disputeID, _params.externalDisputeID, _params.templateId, _params.templateUri); + + emit CrossChainDisputeIncoming( + arbitrator, + _params.foreignChainID, + _params.foreignArbitrable, + _params.foreignDisputeID, + _params.externalDisputeID, + _params.templateId, + _params.templateUri + ); } - /// @inheritdoc IArbitrable + /// @inheritdoc IArbitrableV2 function rule(uint256 _disputeID, uint256 _ruling) external override { require(msg.sender == address(arbitrator), "Only Arbitrator"); diff --git a/contracts/src/gateway/interfaces/IForeignGateway.sol b/contracts/src/gateway/interfaces/IForeignGateway.sol index e1fa537da..ac43f5e2c 100644 --- a/contracts/src/gateway/interfaces/IForeignGateway.sol +++ b/contracts/src/gateway/interfaces/IForeignGateway.sol @@ -8,11 +8,22 @@ pragma solidity 0.8.18; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "../../arbitration/interfaces/IArbitratorV2.sol"; import "@kleros/vea-contracts/src/interfaces/gateways/IReceiverGateway.sol"; -import "../../arbitration/IArbitrator.sol"; -interface IForeignGateway is IArbitrator, IReceiverGateway { +interface IForeignGateway is IArbitratorV2, IReceiverGateway { + /// @dev To be emitted when a dispute is sent to the IHomeGateway. + /// @param _foreignBlockHash foreignBlockHash + /// @param _foreignArbitrable The address of the Arbitrable contract. + /// @param _foreignDisputeID The identifier of the dispute in the Arbitrable contract. + event CrossChainDisputeOutgoing( + bytes32 _foreignBlockHash, + address indexed _foreignArbitrable, + uint256 indexed _foreignDisputeID, + uint256 _choices, + bytes _extraData + ); + /// Relay the rule call from the home gateway to the arbitrable. function relayRule(address _messageSender, bytes32 _disputeHash, uint256 _ruling, address _forwarder) external; diff --git a/contracts/src/gateway/interfaces/IHomeGateway.sol b/contracts/src/gateway/interfaces/IHomeGateway.sol index 63284e250..d108d290a 100644 --- a/contracts/src/gateway/interfaces/IHomeGateway.sol +++ b/contracts/src/gateway/interfaces/IHomeGateway.sol @@ -8,29 +8,48 @@ pragma solidity 0.8.18; -import "../../arbitration/IArbitrable.sol"; -import "../../evidence/IMetaEvidence.sol"; +import "../../arbitration/interfaces/IArbitrableV2.sol"; import "@kleros/vea-contracts/src/interfaces/gateways/ISenderGateway.sol"; -interface IHomeGateway is IArbitrable, IMetaEvidence, ISenderGateway { +interface IHomeGateway is IArbitrableV2, ISenderGateway { + /// @dev To be emitted when a dispute is received from the IForeignGateway. + /// @param _arbitrator The arbitrator of the contract. + /// @param _arbitrableChainId The chain identifier where the Arbitrable contract is deployed. + /// @param _arbitrable The address of the Arbitrable contract. + /// @param _arbitrableDisputeID The identifier of the dispute in the Arbitrable contract. + /// @param _externalDisputeID An identifier created outside Kleros by the protocol requesting arbitration. + /// @param _templateId The identifier of the dispute template. Should not be used with _templateUri. + /// @param _templateUri IPFS path to the dispute template starting with '/ipfs/'. Should not be used with _templateId. + event CrossChainDisputeIncoming( + IArbitratorV2 indexed _arbitrator, + uint256 _arbitrableChainId, + address indexed _arbitrable, + uint256 indexed _arbitrableDisputeID, + uint256 _externalDisputeID, + uint256 _templateId, + string _templateUri + ); + + // Workaround stack too deep for relayCreateDispute() + struct RelayCreateDisputeParams { + bytes32 foreignBlockHash; + uint256 foreignChainID; + address foreignArbitrable; + uint256 foreignDisputeID; + uint256 externalDisputeID; + uint256 templateId; + string templateUri; + uint256 choices; + bytes extraData; + } + /// @dev Provide the same parameters as on the foreignChain while creating a dispute. Providing incorrect parameters will create a different hash than on the foreignChain and will not affect the actual dispute/arbitrable's ruling. - /// @param _foreignChainID foreignChainId - /// @param _foreignBlockHash foreignBlockHash - /// @param _foreignDisputeID foreignDisputeID - /// @param _choices number of ruling choices - /// @param _extraData extraData - /// @param _arbitrable arbitrable - function relayCreateDispute( - uint256 _foreignChainID, - bytes32 _foreignBlockHash, - uint256 _foreignDisputeID, - uint256 _choices, - bytes calldata _extraData, - address _arbitrable - ) external payable; - - /// @dev Looks up the local home disputeID for a disputeHash + /// @param _params The parameters of the dispute, see `RelayCreateDisputeParams`. + function relayCreateDispute(RelayCreateDisputeParams memory _params) external payable; + + /// @dev Looks up the local home disputeID for a disputeHash. /// @param _disputeHash dispute hash + /// @return disputeID dispute identifier on the home chain function disputeHashToHomeID(bytes32 _disputeHash) external view returns (uint256); /// @return The chain ID where the corresponding foreign gateway is deployed. diff --git a/contracts/src/evidence/IMetaEvidence.sol b/contracts/src/kleros-v1/interfaces/IEvidenceV1.sol similarity index 52% rename from contracts/src/evidence/IMetaEvidence.sol rename to contracts/src/kleros-v1/interfaces/IEvidenceV1.sol index 05a673b5c..2e53be127 100644 --- a/contracts/src/evidence/IMetaEvidence.sol +++ b/contracts/src/kleros-v1/interfaces/IEvidenceV1.sol @@ -2,23 +2,42 @@ pragma solidity 0.8.18; -import "../arbitration/IArbitrator.sol"; +/** + * @authors: [@ferittuncer, @hbarcelos] + * @reviewers: [] + * @auditors: [] + * @bounties: [] + * @deployments: [] + */ +import "./IArbitratorV1.sol"; /// @title IMetaEvidence /// ERC-1497: Evidence Standard excluding evidence emission as it will be handled by the arbitrator. -interface IMetaEvidence { +interface IEvidenceV1 { /// @dev To be emitted when meta-evidence is submitted. /// @param _metaEvidenceID Unique identifier of meta-evidence. /// @param _evidence IPFS path to metaevidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/metaevidence.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 IPFS path to evidence, example: '/ipfs/Qmarwkf7C9RuzDEJNnarT3WZ7kem5bk8DZAzx78acJjMFH/evidence.json' + event Evidence( + IArbitratorV1 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, + IArbitratorV1 indexed _arbitrator, uint256 indexed _disputeID, uint256 _metaEvidenceID, uint256 _evidenceGroupID diff --git a/contracts/src/kleros-v1/kleros-liquid-xdai/xKlerosLiquidV2.sol b/contracts/src/kleros-v1/kleros-liquid-xdai/xKlerosLiquidV2.sol index c20afb88c..54d94a15a 100644 --- a/contracts/src/kleros-v1/kleros-liquid-xdai/xKlerosLiquidV2.sol +++ b/contracts/src/kleros-v1/kleros-liquid-xdai/xKlerosLiquidV2.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.18; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {IArbitrator, IArbitrable} from "../../arbitration/IArbitrator.sol"; +import {IArbitratorV2, IArbitrableV2} from "../../arbitration/interfaces/IArbitratorV2.sol"; import {ITokenController} from "../interfaces/ITokenController.sol"; import {WrappedPinakion} from "./WrappedPinakion.sol"; import {IRandomAuRa} from "./interfaces/IRandomAuRa.sol"; @@ -16,7 +16,7 @@ import "../../gateway/interfaces/IForeignGateway.sol"; /// @dev This contract is an adaption of Mainnet's KlerosLiquid (https://github.com/kleros/kleros/blob/69cfbfb2128c29f1625b3a99a3183540772fda08/contracts/kleros/KlerosLiquid.sol) /// for xDai chain. Notice that variables referring to ETH values in this contract, will hold the native token values of the chain on which xKlerosLiquid is deployed. /// When this contract gets deployed on xDai chain, ETH variables will hold xDai values. -contract xKlerosLiquidV2 is Initializable, ITokenController, IArbitrator { +contract xKlerosLiquidV2 is Initializable, ITokenController, IArbitratorV2 { // ************************************* // // * Enums / Structs * // // ************************************* // @@ -71,7 +71,7 @@ contract xKlerosLiquidV2 is Initializable, ITokenController, IArbitrator { struct Dispute { // Note that appeal `0` is equivalent to the first round of the dispute. uint96 subcourtID; // The ID of the subcourt the dispute is in. - IArbitrable arbitrated; // The arbitrated arbitrable contract. + IArbitrableV2 arbitrated; // The arbitrated arbitrable contract. // The number of choices jurors have when voting. This does not include choice `0` which is reserved for "refuse to arbitrate"/"no ruling". uint256 numberOfChoices; Period period; // The current period of the dispute. @@ -463,17 +463,17 @@ contract xKlerosLiquidV2 is Initializable, ITokenController, IArbitrator { disputeID = totalDisputes++; Dispute storage dispute = disputes[disputeID]; - dispute.arbitrated = IArbitrable(msg.sender); + dispute.arbitrated = IArbitrableV2(msg.sender); // The V2 subcourtID is off by one (uint96 subcourtID, uint256 minJurors) = extraDataToSubcourtIDAndMinJurors(_extraData); bytes memory extraDataV2 = abi.encode(uint256(subcourtID + 1), minJurors); foreignGateway.createDispute{value: msg.value}(_numberOfChoices, extraDataV2); - emit DisputeCreation(disputeID, IArbitrable(msg.sender)); + emit DisputeCreation(disputeID, IArbitrableV2(msg.sender)); } - /// @inheritdoc IArbitrator + /// @inheritdoc IArbitratorV2 function createDispute( uint256 /*_choices*/, bytes calldata /*_extraData*/, @@ -625,14 +625,15 @@ contract xKlerosLiquidV2 is Initializable, ITokenController, IArbitrator { /// @dev Gets the current ruling of a specified dispute. /// @param _disputeID The ID of the dispute. /// @return ruling The current ruling. - function currentRuling(uint256 _disputeID) public view returns (uint256 ruling) { + /// @return tied Whether it's a tie or not. + /// @return overridden Whether the ruling was overridden by appeal funding or not. + function currentRuling(uint256 _disputeID) public view returns (uint256 ruling, bool tied, bool /*overridden*/) { Dispute storage dispute = disputes[_disputeID]; if (dispute.voteCounters.length == 0) { ruling = disputesRuling[_disputeID]; } else { - ruling = dispute.voteCounters[dispute.voteCounters.length - 1].tied - ? 0 - : dispute.voteCounters[dispute.voteCounters.length - 1].winningChoice; + tied = dispute.voteCounters[dispute.voteCounters.length - 1].tied; + ruling = tied ? 0 : dispute.voteCounters[dispute.voteCounters.length - 1].winningChoice; } } diff --git a/contracts/src/kleros-v1/kleros-liquid/KlerosLiquidToV2Governor.sol b/contracts/src/kleros-v1/kleros-liquid/KlerosLiquidToV2Governor.sol index 4675b98ab..e8cf617af 100644 --- a/contracts/src/kleros-v1/kleros-liquid/KlerosLiquidToV2Governor.sol +++ b/contracts/src/kleros-v1/kleros-liquid/KlerosLiquidToV2Governor.sol @@ -4,43 +4,61 @@ pragma solidity 0.8.18; import "../interfaces/IKlerosLiquid.sol"; import "../interfaces/ITokenController.sol"; -import "../../arbitration/IArbitrable.sol"; -import "../../arbitration/IArbitrator.sol"; +import {IArbitratorV2, IArbitrableV2} from "../../arbitration/interfaces/IArbitratorV2.sol"; interface IPinakion { function balanceOf(address who) external view returns (uint256); } -contract KlerosLiquidToV2Governor is IArbitrable, ITokenController { +contract KlerosLiquidToV2Governor is IArbitrableV2, ITokenController { + // ************************************* // + // * Enums / Structs * // + // ************************************* // + struct DisputeData { uint256 klerosLiquidDisputeID; bool ruled; } - IArbitrator public immutable foreignGateway; + // ************************************* // + // * Storage * // + // ************************************* // + + IArbitratorV2 public immutable foreignGateway; IKlerosLiquid public immutable klerosLiquid; address public governor; - mapping(uint256 => uint256) public klerosLiquidDisputeIDtoGatewayDisputeID; mapping(uint256 => DisputeData) public disputes; // disputes[gatewayDisputeID] mapping(address => uint256) public frozenTokens; // frozenTokens[account] locked token which shouldn't have been blocked. mapping(uint256 => mapping(uint256 => bool)) public isDisputeNotified; // isDisputeNotified[disputeID][roundID] used to track the notification of frozen tokens. + // ************************************* // + // * Function Modifiers * // + // ************************************* // + modifier onlyByGovernor() { require(governor == msg.sender); _; } + // ************************************* // + // * Constructor * // + // ************************************* // + /// @dev Constructor. Before this contract is made the new governor of KlerosLiquid, the evidence period of all subcourts has to be set to uint(-1). /// @param _klerosLiquid The trusted arbitrator to resolve potential disputes. /// @param _governor The trusted governor of the contract. /// @param _foreignGateway The trusted gateway that acts as an arbitrator, relaying disputes to v2. - constructor(IKlerosLiquid _klerosLiquid, address _governor, IArbitrator _foreignGateway) { + constructor(IKlerosLiquid _klerosLiquid, address _governor, IArbitratorV2 _foreignGateway) { klerosLiquid = _klerosLiquid; governor = _governor; foreignGateway = _foreignGateway; } + // ************************************* // + // * Governance * // + // ************************************* // + /// @dev Lets the governor call anything on behalf of the contract. /// @param _destination The destination of the call. /// @param _amount The value sent with the call. @@ -60,6 +78,10 @@ contract KlerosLiquidToV2Governor is IArbitrable, ITokenController { governor = _governor; } + // ************************************* // + // * State Modifiers * // + // ************************************* // + /// @dev Relays disputes from KlerosLiquid to Kleros v2. Only disputes in the evidence period of the initial round can be realyed. /// @param _disputeID The ID of the dispute as defined in KlerosLiquid. function relayDispute(uint256 _disputeID) external { @@ -89,11 +111,8 @@ contract KlerosLiquidToV2Governor is IArbitrable, ITokenController { dispute.klerosLiquidDisputeID = _disputeID; } - /// @dev Give a ruling for a dispute. Can only be called by the arbitrator. TRUSTED. - /// Triggers rule() from KlerosLiquid to the arbitrable contract which created the dispute. - /// @param _disputeID ID of the dispute in the arbitrator contract. - /// @param _ruling Ruling given by the arbitrator. Note that 0 is reserved for "Refused to arbitrate". - function rule(uint256 _disputeID, uint256 _ruling) public { + /// @inheritdoc IArbitrableV2 + function rule(uint256 _disputeID, uint256 _ruling) public override { require(msg.sender == address(foreignGateway), "Not the arbitrator."); DisputeData storage dispute = disputes[_disputeID]; require(dispute.klerosLiquidDisputeID != 0, "Dispute does not exist."); @@ -105,7 +124,7 @@ contract KlerosLiquidToV2Governor is IArbitrable, ITokenController { IKlerosLiquid.Dispute memory klerosLiquidDispute = klerosLiquid.disputes(dispute.klerosLiquidDisputeID); - bytes memory data = abi.encodeCall(IArbitrable.rule, (dispute.klerosLiquidDisputeID, _ruling)); + bytes memory data = abi.encodeCall(IArbitrableV2.rule, (dispute.klerosLiquidDisputeID, _ruling)); klerosLiquid.executeGovernorProposal(klerosLiquidDispute.arbitrated, 0, data); } @@ -133,19 +152,13 @@ contract KlerosLiquidToV2Governor is IArbitrable, ITokenController { } } - /// @dev Called when `_owner` sends ether to the MiniMe Token contract. - /// @param _owner The address that sent the ether to create tokens. - /// @return allowed Whether the operation should be allowed or not. - function proxyPayment(address _owner) external payable returns (bool allowed) { + /// @inheritdoc ITokenController + function proxyPayment(address /*_owner*/) external payable override returns (bool allowed) { allowed = false; } - /// @dev Notifies the controller about a token transfer allowing the controller to react if desired. - /// @param _from The origin of the transfer. - /// @param _to The destination of the transfer. - /// @param _amount The amount of the transfer. - /// @return allowed Whether the operation should be allowed or not. - function onTransfer(address _from, address _to, uint256 _amount) external returns (bool allowed) { + /// @inheritdoc ITokenController + function onTransfer(address _from, address /*_to*/, uint256 _amount) external view override returns (bool allowed) { if (klerosLiquid.lockInsolventTransfers()) { // Never block penalties or rewards. IPinakion pinakion = IPinakion(klerosLiquid.pinakion()); @@ -159,12 +172,12 @@ contract KlerosLiquidToV2Governor is IArbitrable, ITokenController { allowed = true; } - /// @dev Notifies the controller about an approval allowing the controller to react if desired. - /// @param _owner The address that calls `approve()`. - /// @param _spender The spender in the `approve()` call. - /// @param _amount The amount in the `approve()` call. - /// @return allowed Whether the operation should be allowed or not. - function onApprove(address _owner, address _spender, uint256 _amount) external returns (bool allowed) { + /// @inheritdoc ITokenController + function onApprove( + address /*_owner*/, + address /*_spender*/, + uint256 /*_amount*/ + ) external pure override returns (bool allowed) { allowed = true; } diff --git a/contracts/test/arbitration/draw.ts b/contracts/test/arbitration/draw.ts index 1d5abaca0..16ab8368a 100644 --- a/contracts/test/arbitration/draw.ts +++ b/contracts/test/arbitration/draw.ts @@ -5,7 +5,7 @@ import { PNK, KlerosCore, ArbitrableExample, - HomeGatewayToEthereum, + HomeGateway, DisputeKitClassic, RandomizerRNG, RandomizerMock, @@ -65,7 +65,7 @@ describe("Draw Benchmark", async () => { disputeKit = (await ethers.getContract("DisputeKitClassic")) as DisputeKitClassic; pnk = (await ethers.getContract("PNK")) as PNK; core = (await ethers.getContract("KlerosCore")) as KlerosCore; - homeGateway = (await ethers.getContract("HomeGatewayToEthereum")) as HomeGatewayToEthereum; + homeGateway = (await ethers.getContract("HomeGatewayToEthereum")) as HomeGateway; arbitrable = (await ethers.getContract("ArbitrableExample")) as ArbitrableExample; rng = (await ethers.getContract("RandomizerRNG")) as RandomizerRNG; randomizer = (await ethers.getContract("RandomizerMock")) as RandomizerMock; @@ -94,7 +94,7 @@ describe("Draw Benchmark", async () => { } // Create a dispute - const tx = await arbitrable.functions["createDispute(uint256,bytes,uint256,uint256)"](2, "0x00", 0, 0, { + const tx = await arbitrable.functions["createDispute(uint256,string,bytes)"](0, "future of france", "0x00", { value: arbitrationCost, }); const trace = await network.provider.send("debug_traceTransaction", [tx.hash]); @@ -102,11 +102,20 @@ describe("Draw Benchmark", async () => { const lastBlock = await ethers.provider.getBlock(tx.blockNumber - 1); // Relayer tx - const tx2 = await homeGateway - .connect(await ethers.getSigner(relayer)) - .relayCreateDispute(31337, lastBlock.hash, disputeId, 2, "0x00", arbitrable.address, { - value: arbitrationCost, - }); + const tx2 = await homeGateway.connect(await ethers.getSigner(relayer)).relayCreateDispute( + { + foreignBlockHash: lastBlock.hash, + foreignChainID: 31337, + foreignArbitrable: arbitrable.address, + foreignDisputeID: disputeId, + externalDisputeID: ethers.utils.keccak256(ethers.utils.toUtf8Bytes("future of france")), + templateId: 0, + templateUri: "", + choices: 2, + extraData: "0x00", + }, + { value: arbitrationCost } + ); await network.provider.send("evm_increaseTime", [2000]); // Wait for minStakingTime await network.provider.send("evm_mine"); diff --git a/contracts/test/evidence/index.ts b/contracts/test/evidence/index.ts index 71a7466aa..281dc119f 100644 --- a/contracts/test/evidence/index.ts +++ b/contracts/test/evidence/index.ts @@ -21,7 +21,7 @@ describe("Home Evidence contract", async () => { const bondTimeout = 60 * 10; const totalCostMultiplier = 15000; const initialDepositMultiplier = 625; - const metaEvidenceUri = "https://kleros.io"; + const disputeTemplate = '{ "disputeTemplate": "foo"}'; const MULTIPLIER_DIVISOR = BigNumber.from(10000); const totalCost = BigNumber.from(arbitrationFee).mul(BigNumber.from(totalCostMultiplier)).div(MULTIPLIER_DIVISOR); const minRequiredDeposit = totalCost.mul(BigNumber.from(initialDepositMultiplier)).div(MULTIPLIER_DIVISOR); @@ -51,7 +51,7 @@ describe("Home Evidence contract", async () => { initialDepositMultiplier, bondTimeout, arbitratorExtraData, - metaEvidenceUri + disputeTemplate ); }); @@ -71,20 +71,18 @@ describe("Home Evidence contract", async () => { await evidenceModule.changeBondTimeout(1); expect(await evidenceModule.bondTimeout()).to.equal(1); - const newMetaEvidenceUri = "https://kleros.io/new"; - let tx = await evidenceModule.changeMetaEvidence(newMetaEvidenceUri); + const newDisputeTemplate = '{ "disputeTemplate": "bar"}'; + let tx = await evidenceModule.changeDisputeTemplate(newDisputeTemplate); let receipt = await tx.wait(); let lastArbitratorIndex = await evidenceModule.getCurrentArbitratorIndex(); let newArbitratorData = await evidenceModule.arbitratorDataList(lastArbitratorIndex); let oldArbitratorData = await evidenceModule.arbitratorDataList(lastArbitratorIndex.sub(BigNumber.from(1))); - expect(newArbitratorData.metaEvidenceUpdates).to.equal( - oldArbitratorData.metaEvidenceUpdates.add(BigNumber.from(1)) - ); + expect(newArbitratorData.disputeTemplateId).to.equal(oldArbitratorData.disputeTemplateId.add(BigNumber.from(1))); expect(newArbitratorData.arbitratorExtraData).to.equal(oldArbitratorData.arbitratorExtraData); - const [newMetaEvidenceUpdates, newMetaEvidence] = getEmittedEvent("MetaEvidence", receipt).args; - expect(newMetaEvidence).to.equal(newMetaEvidenceUri, "Wrong MetaEvidence."); - expect(newMetaEvidenceUpdates).to.equal(newArbitratorData.metaEvidenceUpdates, "Wrong MetaEvidence ID."); + const [_templateId, _, _templateData] = getEmittedEvent("DisputeTemplate", receipt).args; + expect(_templateData).to.equal(newDisputeTemplate, "Wrong Template Data."); + expect(_templateId).to.equal(newArbitratorData.disputeTemplateId, "Wrong Template ID."); const newArbitratorExtraData = "0x86"; await evidenceModule.changeArbitratorExtraData(newArbitratorExtraData); @@ -109,7 +107,7 @@ describe("Home Evidence contract", async () => { "The caller must be the governor" ); - await expect(evidenceModule.connect(user2).changeMetaEvidence(metaEvidenceUri)).to.be.revertedWith( + await expect(evidenceModule.connect(user2).changeDisputeTemplate(disputeTemplate)).to.be.revertedWith( "The caller must be the governor" ); @@ -128,11 +126,11 @@ describe("Home Evidence contract", async () => { const receipt = await tx.wait(); const evidenceID = ethers.utils.solidityKeccak256(["uint", "string"], [1234, newEvidence]); - const [arbitratorAddress, evidenceGroupID, submitter, evidenceStr] = getEmittedEvent("Evidence", receipt).args; - expect(arbitratorAddress).to.equal(arbitrator.address, "Wrong arbitrator."); - expect(evidenceGroupID).to.equal(1234, "Wrong evidence group ID."); - expect(submitter).to.equal(user1.address, "Wrong submitter."); - expect(evidenceStr).to.equal(newEvidence, "Wrong evidence message."); + const [_arbitrator, _externalDisputeID, _party, _evidence] = getEmittedEvent("ModeratedEvidence", receipt).args; + expect(_arbitrator).to.equal(arbitrator.address, "Wrong arbitrator."); + expect(_externalDisputeID).to.equal(1234, "Wrong external dispute ID."); + expect(_party).to.equal(user1.address, "Wrong submitter."); + expect(_evidence).to.equal(newEvidence, "Wrong evidence message."); let contributions = await evidenceModule.getContributions(evidenceID, 0, user1.address); expect(contributions[0]).to.equal(ZERO); // it's 1am and to.deep.equal() won't work, can't be bothered @@ -141,7 +139,7 @@ describe("Home Evidence contract", async () => { expect(contributions.length).to.equal(3); }); - it("Should not allowed the same evidence twice for the same evidence group id.", async () => { + it("Should not allowed the same evidence twice for the same external dispute id.", async () => { const newEvidence = "Irrefutable evidence"; await evidenceModule.submitEvidence(1234, newEvidence, { value: minRequiredDeposit, @@ -235,11 +233,14 @@ describe("Home Evidence contract", async () => { }); let receipt = await tx.wait(); - let [_arbitrator, disputeID, metaEvidenceID, _evidenceID] = getEmittedEvent("Dispute", receipt).args; + let [_arbitrator, _arbitrableDisputeID, _externalDisputeID, _templateId, _templateUri] = getEmittedEvent( + "DisputeRequest", + receipt + ).args; expect(_arbitrator).to.equal(arbitrator.address, "Wrong arbitrator."); - expect(disputeID).to.equal(0, "Wrong dispute ID."); - expect(metaEvidenceID).to.equal(0, "Wrong meta-evidence ID."); - expect(_evidenceID).to.equal(evidenceID, "Wrong evidence ID."); + expect(_arbitrableDisputeID).to.equal(0, "Wrong dispute ID."); + expect(_templateId).to.equal(0, "Wrong template ID."); + expect(_externalDisputeID).to.equal(evidenceID, "Wrong external dispute ID."); await expect( evidenceModule.connect(user2).moderate(evidenceID, Party.Moderator, { diff --git a/contracts/test/integration/index.ts b/contracts/test/integration/index.ts index 4ee461eed..81f7a8a15 100644 --- a/contracts/test/integration/index.ts +++ b/contracts/test/integration/index.ts @@ -4,15 +4,16 @@ import { BigNumber } from "ethers"; import { PNK, KlerosCore, - ForeignGatewayOnEthereum, + ForeignGateway, ArbitrableExample, - HomeGatewayToEthereum, + HomeGateway, VeaMock, DisputeKitClassic, RandomizerRNG, RandomizerMock, SortitionModule, } from "../../typechain-types"; +import { keccak256 } from "ethers/lib/utils"; /* eslint-disable no-unused-vars */ /* eslint-disable no-unused-expressions */ // https://github.com/standard/standard/issues/690#issuecomment-278533482 @@ -56,15 +57,15 @@ describe("Integration tests", async () => { pnk = (await ethers.getContract("PNK")) as PNK; core = (await ethers.getContract("KlerosCore")) as KlerosCore; vea = (await ethers.getContract("VeaMock")) as VeaMock; - foreignGateway = (await ethers.getContract("ForeignGatewayOnEthereum")) as ForeignGatewayOnEthereum; + foreignGateway = (await ethers.getContract("ForeignGatewayOnEthereum")) as ForeignGateway; arbitrable = (await ethers.getContract("ArbitrableExample")) as ArbitrableExample; - homeGateway = (await ethers.getContract("HomeGatewayToEthereum")) as HomeGatewayToEthereum; + homeGateway = (await ethers.getContract("HomeGatewayToEthereum")) as HomeGateway; sortitionModule = (await ethers.getContract("SortitionModule")) as SortitionModule; }); it("Resolves a dispute on the home chain with no appeal", async () => { const arbitrationCost = ONE_TENTH_ETH.mul(3); - const [bridger, challenger, relayer] = await ethers.getSigners(); + const [, , relayer] = await ethers.getSigners(); await pnk.approve(core.address, ONE_THOUSAND_PNK.mul(100)); @@ -95,7 +96,7 @@ describe("Integration tests", async () => { expect(result.locked).to.equal(0); logJurorBalance(result); }); - const tx = await arbitrable.functions["createDispute(uint256,bytes,uint256,uint256)"](2, "0x00", 0, 0, { + const tx = await arbitrable.functions["createDispute(uint256,string,bytes)"](0, "future of france", "0x00", { value: arbitrationCost, }); const trace = await network.provider.send("debug_traceTransaction", [tx.hash]); @@ -107,18 +108,26 @@ describe("Integration tests", async () => { const lastBlock = await ethers.provider.getBlock(tx.blockNumber - 1); const disputeHash = ethers.utils.solidityKeccak256( - ["uint", "bytes", "bytes", "uint", "uint", "bytes", "address"], - [31337, lastBlock.hash, ethers.utils.toUtf8Bytes("createDispute"), disputeId, 2, "0x00", arbitrable.address] + ["bytes", "bytes32", "uint256", "address", "uint256", "uint256", "bytes"], + [ethers.utils.toUtf8Bytes("createDispute"), lastBlock.hash, 31337, arbitrable.address, disputeId, 2, "0x00"] ); - const events = (await tx.wait()).events; // Relayer tx - const tx2 = await homeGateway - .connect(relayer) - .relayCreateDispute(31337, lastBlock.hash, disputeId, 2, "0x00", arbitrable.address, { - value: arbitrationCost, - }); + const tx2 = await homeGateway.connect(relayer).relayCreateDispute( + { + foreignBlockHash: lastBlock.hash, + foreignChainID: 31337, + foreignArbitrable: arbitrable.address, + foreignDisputeID: disputeId, + externalDisputeID: ethers.utils.keccak256(ethers.utils.toUtf8Bytes("future of france")), + templateId: 0, + templateUri: "", + choices: 2, + extraData: "0x00", + }, + { value: arbitrationCost } + ); expect(tx2).to.emit(homeGateway, "Dispute"); const events2 = (await tx2.wait()).events; diff --git a/kleros-ts/README.md b/kleros-sdk/README.md similarity index 59% rename from kleros-ts/README.md rename to kleros-sdk/README.md index 11fd1e0ed..247be318a 100644 --- a/kleros-ts/README.md +++ b/kleros-sdk/README.md @@ -1,4 +1,4 @@ -# @kleros/kleros-v2-klerosjs +# @kleros/kleros-v2-sdk _Archon's successor_ diff --git a/kleros-sdk/config/v1-metaevidence/escrow.json b/kleros-sdk/config/v1-metaevidence/escrow.json new file mode 100644 index 000000000..f2b0e7c93 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/escrow.json @@ -0,0 +1,38 @@ +{ + "subCategory": "General Service", + "arbitrableAddress": "0x0d67440946949fe293b45c52efd8a9b3d51e2522", + "title": "Jenkins the Valet Yacht Licensing Contract", + "description": "Agreement between Bostonbob (bb) and AC (ac). \n\nbb will pay a one time yacht leasing fee of 4 eth to ac.\n\nIn return, ac will lease his yacht to bb by submitting bb’s MAYC and his back story in the Jenkins the valet author portal. Ac’s WAGMI Yacht #1047 will be attached to bb’s MAYC #1353, casting 1353 for a role in the book. \n\nIn addition, a royalty split will be put into place between the two parties. 80% for ac/20% for bb (managed and paid out by Jenkins team at a later date)\n\n*All names in contract are Twitter profile names as of 12/8.", + "sender": "0x45E6564631809F5531fd008f4829f1C5B0c29A7f", + "receiver": "0x45E6564631809F5531fd008f4829f1C5B0c29A7f", + "amount": "4", + "timeout": 8640000000000000, + "token": { + "name": "Ethereum", + "ticker": "ETH", + "symbolURI": "/static/media/eth.33901ab6.png", + "address": null, + "decimals": 18 + }, + "extraData": { + "Contract Information": "Agreement between Bostonbob (bb) and AC (ac). \n\nbb will pay a one time yacht leasing fee of 4 eth to ac.\n\nIn return, ac will lease his yacht to bb by submitting bb’s MAYC and his back story in the Jenkins the valet author portal. Ac’s WAGMI Yacht #1047 will be attached to bb’s MAYC #1353, casting 1353 for a role in the book. \n\nIn addition, a royalty split will be put into place between the two parties. 80% for ac/20% for bb (managed and paid out by Jenkins team at a later date)\n\n*All names in contract are Twitter profile names as of 12/8." + }, + "invoice": true, + "category": "Escrow", + "question": "Which party abided by terms of the contract?", + "rulingOptions": { + "type": "single-select", + "titles": [ + "Refund Sender", + "Pay Receiver" + ], + "descriptions": [ + "Select to return funds to the Sender", + "Select to release funds to the Receiver" + ] + }, + "evidenceDisplayInterfaceURI": "/ipfs/QmfPnVdcCjApHdiCC8wAmyg5iR246JvVuQGQjQYgtF8gZU/index.html", + "aliases": { + "0x45E6564631809F5531fd008f4829f1C5B0c29A7f": "receiver" + } +} diff --git a/kleros-sdk/config/v1-metaevidence/escrow2.json b/kleros-sdk/config/v1-metaevidence/escrow2.json new file mode 100644 index 000000000..fcc13d4ff --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/escrow2.json @@ -0,0 +1,39 @@ +{ + "subCategory": "General Service", + "arbitrableAddress": "0x0d67440946949fe293b45c52efd8a9b3d51e2522", + "title": "Mente Vs Cooperative Kleros", + "description": "\n\nThe challenger believes due to a UI bug they were not able to challenge case 164 and this dispute is against the cooperative for potential lost winnings.\n\n", + "sender": "0x96559b33D6A9042b1C34b3e8978Ca922146cB79a", + "receiver": "0xa07f5Ffd166Ca3Ff7567e96a0430F1496cdb470a", + "amount": "5", + "timeout": 8640000000000000, + "token": { + "name": "Ethereum", + "ticker": "ETH", + "symbolURI": "/static/media/eth.33901ab6.png", + "address": null, + "decimals": 18 + }, + "extraData": { + "Contract Information": "\n\nThe challenger believes due to a UI bug they were not able to challenge case 164 and this dispute is against the cooperative for potential lost winnings.\n\n" + }, + "invoice": false, + "category": "Escrow", + "question": "Which party abided by terms of the contract?", + "rulingOptions": { + "type": "single-select", + "titles": [ + "Refund Sender", + "Pay Receiver" + ], + "descriptions": [ + "Select to return funds to the Sender", + "Select to release funds to the Receiver" + ] + }, + "evidenceDisplayInterfaceURI": "/ipfs/QmfPnVdcCjApHdiCC8wAmyg5iR246JvVuQGQjQYgtF8gZU/index.html", + "aliases": { + "0x96559b33D6A9042b1C34b3e8978Ca922146cB79a": "sender", + "0xa07f5Ffd166Ca3Ff7567e96a0430F1496cdb470a": "receiver" + } +} diff --git a/kleros-sdk/config/v1-metaevidence/lgtcr1.json b/kleros-sdk/config/v1-metaevidence/lgtcr1.json new file mode 100644 index 000000000..08fb21ffa --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/lgtcr1.json @@ -0,0 +1,50 @@ +{ + "title": "Add a list to Consensus Layer Withdrawal Protection enabled badges", + "description": "Someone requested to add a list to Consensus Layer Withdrawal Protection enabled badges.", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the list complies with the required criteria and should be added.", + "Select this if you think the list does not comply with the required criteria and should not be added." + ] + }, + "category": "Curated Lists", + "question": "Does the list comply with the required criteria?", + "fileURI": "/ipfs/QmZ7RVU7re1g8nXDbAFMHV99pyie3dn4cY7Ga2X4h8mDpV/reject-all-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmQjJio59WkrQDzPC5kSP3EiGaqrWxjGfkvhmD2mWwm41M/index.html", + "metadata": { + "tcrTitle": "Consensus Layer Withdrawal Protection enabled badges", + "tcrDescription": "A List of lists related to Consensus Layer Withdrawal Protection", + "columns": [ + { + "label": "Address", + "description": "The Badges list address", + "type": "GTCR address", + "isIdentifier": true + }, + { + "label": "Match File URI", + "description": "The URI to the JSON file for matching columns for each list.", + "type": "text" + } + ], + "itemName": "list", + "itemNamePlural": "lists", + "isConnectedTCR": true, + "requireRemovalEvidence": true, + "isTCRofTCRs": true, + "parentTCRAddress": "0x479083b5343aB89bb39608e3176D750c8A6957B5", + "relTcrDisabled": true + }, + "_v": "1.0.0", + "evidenceDisplayInterfaceRequiredParams": [ + "disputeID", + "arbitrableContractAddress", + "arbitratorContractAddress", + "arbitrableChainID", + "arbitrableJsonRpcUrl" + ] +} diff --git a/kleros-sdk/config/v1-metaevidence/lgtcr2.json b/kleros-sdk/config/v1-metaevidence/lgtcr2.json new file mode 100644 index 000000000..8aa949743 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/lgtcr2.json @@ -0,0 +1,50 @@ +{ + "title": "Remove a list from Consensus Layer Withdrawal Protection enabled badges", + "description": "Someone requested to remove a list from Consensus Layer Withdrawal Protection enabled badges.", + "rulingOptions": { + "titles": [ + "Yes, Remove It", + "No, Don't Remove It" + ], + "descriptions": [ + "Select this if you think the list does not comply with the required criteria and should be removed.", + "Select this if you think the list complies with the required criteria and should not be removed." + ] + }, + "category": "Curated Lists", + "question": "Does the list comply with the required criteria?", + "fileURI": "/ipfs/QmZ7RVU7re1g8nXDbAFMHV99pyie3dn4cY7Ga2X4h8mDpV/reject-all-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmQjJio59WkrQDzPC5kSP3EiGaqrWxjGfkvhmD2mWwm41M/index.html", + "metadata": { + "tcrTitle": "Consensus Layer Withdrawal Protection enabled badges", + "tcrDescription": "A List of lists related to Consensus Layer Withdrawal Protection", + "columns": [ + { + "label": "Address", + "description": "The Badges list address", + "type": "GTCR address", + "isIdentifier": true + }, + { + "label": "Match File URI", + "description": "The URI to the JSON file for matching columns for each list.", + "type": "text" + } + ], + "itemName": "list", + "itemNamePlural": "lists", + "isConnectedTCR": true, + "requireRemovalEvidence": true, + "isTCRofTCRs": true, + "parentTCRAddress": "0x479083b5343aB89bb39608e3176D750c8A6957B5", + "relTcrDisabled": true + }, + "_v": "1.0.0", + "evidenceDisplayInterfaceRequiredParams": [ + "disputeID", + "arbitrableContractAddress", + "arbitratorContractAddress", + "arbitrableChainID", + "arbitrableJsonRpcUrl" + ] +} diff --git a/kleros-sdk/config/v1-metaevidence/lgtcr3.json b/kleros-sdk/config/v1-metaevidence/lgtcr3.json new file mode 100644 index 000000000..80d174641 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/lgtcr3.json @@ -0,0 +1,66 @@ +{ + "title": "Add a validator to Consensus Layer Withdrawal Protection", + "description": "Someone requested to add a validator to Consensus Layer Withdrawal Protection", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the validator complies with the required criteria and should be added.", + "Select this if you think the validator does not comply with the required criteria and should not be added." + ] + }, + "category": "Curated Lists", + "question": "Does the validator comply with the required criteria?", + "fileURI": "/ipfs/QmPtXtFKfVc3w5aGVNYrmBZWEHBLpk2XMLkYCnEioxwy43/clwp-acceptance-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmQjJio59WkrQDzPC5kSP3EiGaqrWxjGfkvhmD2mWwm41M/index.html", + "metadata": { + "tcrTitle": "Consensus Layer Withdrawal Protection", + "tcrDescription": "Ethereum validators using CLWP to set their withdrawal address", + "columns": [ + { + "label": "validator_index", + "description": "The validator in question (integer) [required]", + "type": "number", + "isIdentifier": true + }, + { + "label": "from_bls_pubkey", + "description": "The public key of the validator withdrawal key (string) [required]", + "type": "text", + "isIdentifier": true + }, + { + "label": "to_execution_address", + "description": "An Ethereum execution layer withdrawal address (address) [required]", + "type": "address", + "isIdentifier": true + }, + { + "label": "CLWP File", + "description": "A text file which is named as the validator_index.json (file) [required]", + "type": "file", + "allowedFileTypes": "json" + }, + { + "label": "Item to supersede", + "description": "In case there is already an entry on the list for the same validator_index, this field needs to be populated with the ItemID of the other item in this Kleros Curate registry that this entry is meant to supersede. (string) [optional]", + "type": "text", + "isIdentifier": true + }, + { + "label": "Additional Information", + "description": "A .pdf file containing any evidence and proof to prove that you are the rightful owner of the validator node. (file) [optional]", + "type": "file", + "allowedFileTypes": "pdf" + } + ], + "itemName": "validator", + "itemNamePlural": "validators", + "logoURI": "/ipfs/QmXkGcS9Nw7jqaSaZZoKh3UQo8pwE8LWsdoUtjx1zTFLmJ/clwp-100-100-px-.svg", + "requireRemovalEvidence": true, + "isTCRofTCRs": false, + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/lgtcr4.json b/kleros-sdk/config/v1-metaevidence/lgtcr4.json new file mode 100644 index 000000000..aec3e12b9 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/lgtcr4.json @@ -0,0 +1,66 @@ +{ + "title": "Remove a validator from Consensus Layer Withdrawal Protection", + "description": "Someone requested to remove a validator from Consensus Layer Withdrawal Protection", + "rulingOptions": { + "titles": [ + "Yes, Remove It", + "No, Don't Remove It" + ], + "descriptions": [ + "Select this if you think the validator does not comply with the required criteria and should be removed.", + "Select this if you think the validator complies with the required criteria and should not be removed." + ] + }, + "category": "Curated Lists", + "question": "Does the validator comply with the required criteria?", + "fileURI": "/ipfs/QmPtXtFKfVc3w5aGVNYrmBZWEHBLpk2XMLkYCnEioxwy43/clwp-acceptance-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmQjJio59WkrQDzPC5kSP3EiGaqrWxjGfkvhmD2mWwm41M/index.html", + "metadata": { + "tcrTitle": "Consensus Layer Withdrawal Protection", + "tcrDescription": "Ethereum validators using CLWP to set their withdrawal address", + "columns": [ + { + "label": "validator_index", + "description": "The validator in question (integer) [required]", + "type": "number", + "isIdentifier": true + }, + { + "label": "from_bls_pubkey", + "description": "The public key of the validator withdrawal key (string) [required]", + "type": "text", + "isIdentifier": true + }, + { + "label": "to_execution_address", + "description": "An Ethereum execution layer withdrawal address (address) [required]", + "type": "address", + "isIdentifier": true + }, + { + "label": "CLWP File", + "description": "A text file which is named as the validator_index.json (file) [required]", + "type": "file", + "allowedFileTypes": "json" + }, + { + "label": "Item to supersede", + "description": "In case there is already an entry on the list for the same validator_index, this field needs to be populated with the ItemID of the other item in this Kleros Curate registry that this entry is meant to supersede. (string) [optional]", + "type": "text", + "isIdentifier": true + }, + { + "label": "Additional Information", + "description": "A .pdf file containing any evidence and proof to prove that you are the rightful owner of the validator node. (file) [optional]", + "type": "file", + "allowedFileTypes": "pdf" + } + ], + "itemName": "validator", + "itemNamePlural": "validators", + "logoURI": "/ipfs/QmXkGcS9Nw7jqaSaZZoKh3UQo8pwE8LWsdoUtjx1zTFLmJ/clwp-100-100-px-.svg", + "requireRemovalEvidence": true, + "isTCRofTCRs": false, + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/lgtcr5.json b/kleros-sdk/config/v1-metaevidence/lgtcr5.json new file mode 100644 index 000000000..66e7424b8 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/lgtcr5.json @@ -0,0 +1,48 @@ +{ + "title": "Add an entry to Ledger Contract Domain Name registry v2", + "description": "Someone requested to add an entry to Ledger Contract Domain Name registry v2", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the entry complies with the required criteria and should be added.", + "Select this if you think the entry does not comply with the required criteria and should not be added." + ] + }, + "category": "Curated Lists", + "question": "Does the entry comply with the required criteria?", + "fileURI": "/ipfs/QmdvkC5Djgk8MfX5ijJR3NJzmvGugUqvui7bKuTErSD6cE/contract-domain-name-registry-for-ledger-policy-3-.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmNhJXtMrxeJu4fpchPruGrL93bm2M4VmDZ8pj4x6FqnHJ/index.html", + "metadata": { + "tcrTitle": "Ledger Contract Domain Name registry v2", + "tcrDescription": "A list of contract addresses and the domain names they are meant to be used from .", + "columns": [ + { + "label": "Contract address", + "description": "The address of the contract in question. Case-sensitive only if required by the blockchain that the address pertains to (e.g. Solana). ", + "type": "rich address", + "isIdentifier": true + }, + { + "label": "Domain name", + "description": "The specific (sub)domain name of the dApp where this contract is meant to be accessed from. Wildcards (*) are acceptable as part of this field if proof can be shown that the contract is intended to be used across multiple domains.", + "type": "text", + "isIdentifier": true + }, + { + "label": "Visual proof", + "description": "If the domain is a specific root or subdomain, this must be a screenshot of the exact page and setup where this particular address can be interacted from.", + "type": "image", + "isIdentifier": false + } + ], + "itemName": "entry", + "itemNamePlural": "entries", + "logoURI": "/ipfs/QmNNSDkpyDX1wB4NNFdAzaHsJihpvgNVV89zCH8FH9CVAz/ledger-white.png", + "requireRemovalEvidence": true, + "isTCRofTCRs": false, + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/lgtcr6.json b/kleros-sdk/config/v1-metaevidence/lgtcr6.json new file mode 100644 index 000000000..1dca32efa --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/lgtcr6.json @@ -0,0 +1,48 @@ +{ + "title": "Remove an entry from Ledger Contract Domain Name registry v2", + "description": "Someone requested to remove an entry from Ledger Contract Domain Name registry v2", + "rulingOptions": { + "titles": [ + "Yes, Remove It", + "No, Don't Remove It" + ], + "descriptions": [ + "Select this if you think the entry does not comply with the required criteria and should be removed.", + "Select this if you think the entry complies with the required criteria and should not be removed." + ] + }, + "category": "Curated Lists", + "question": "Does the entry comply with the required criteria?", + "fileURI": "/ipfs/QmdvkC5Djgk8MfX5ijJR3NJzmvGugUqvui7bKuTErSD6cE/contract-domain-name-registry-for-ledger-policy-3-.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmNhJXtMrxeJu4fpchPruGrL93bm2M4VmDZ8pj4x6FqnHJ/index.html", + "metadata": { + "tcrTitle": "Ledger Contract Domain Name registry v2", + "tcrDescription": "A list of contract addresses and the domain names they are meant to be used from .", + "columns": [ + { + "label": "Contract address", + "description": "The address of the contract in question. Case-sensitive only if required by the blockchain that the address pertains to (e.g. Solana). ", + "type": "rich address", + "isIdentifier": true + }, + { + "label": "Domain name", + "description": "The specific (sub)domain name of the dApp where this contract is meant to be accessed from. Wildcards (*) are acceptable as part of this field if proof can be shown that the contract is intended to be used across multiple domains.", + "type": "text", + "isIdentifier": true + }, + { + "label": "Visual proof", + "description": "If the domain is a specific root or subdomain, this must be a screenshot of the exact page and setup where this particular address can be interacted from.", + "type": "image", + "isIdentifier": false + } + ], + "itemName": "entry", + "itemNamePlural": "entries", + "logoURI": "/ipfs/QmNNSDkpyDX1wB4NNFdAzaHsJihpvgNVV89zCH8FH9CVAz/ledger-white.png", + "requireRemovalEvidence": true, + "isTCRofTCRs": false, + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/linguo-meta-evidence1.json b/kleros-sdk/config/v1-metaevidence/linguo-meta-evidence1.json new file mode 100644 index 000000000..f26134ee9 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/linguo-meta-evidence1.json @@ -0,0 +1,44 @@ +{ + "title": "Review a translation from Linguo", + "description": "Someone challenged a translation", + "rulingOptions": { + "titles": [ + "Yes, the translation should be accepted", + "No, the translation should not be accepted" + ], + "descriptions": [ + "Select this if you think the translation complies with the required criteria.", + "Select this if you think the translation does not comply with the required criteria." + ] + }, + "aliases": { + "0xc3600bfC9Ec2c20E4c7d22c9235b6ddE63BA99a8": "Requester" + }, + "category": "Translation", + "question": "Does the translation comply with the required criteria?", + "fileURI": "/ipfs/QmVabp1VjJNYzXDxbcWFdeK17RvvA9eQy6eJVf1T1AzS1a/linguo-translation-quality-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/Qmb5n6PgbshktJqGpwMAxP1moXEPaqq7ZvRufeXXhSPXxW/linguo-evidence-display/index.html", + "dynamicScriptURI": "/ipfs/QmPAHCRtSU844fdjNoEws8AgTpzzwsYwMF2wydtpvXAcoZ/linguo-script.js", + "dynamicScriptRequiredParams": [ + "disputeID", + "arbitrableContractAddress", + "arbitratorContractAddress", + "chainID", + "jsonRpcUrl" + ], + "metadata": { + "deadline": 1680307199, + "minPrice": "0", + "maxPrice": "500000000000000000000", + "sourceLanguage": "en-us", + "targetLanguage": "es", + "expectedQuality": "professional", + "title": "What do I think about network states?", + "wordCount": 7900, + "originalTextUrl": "https://vitalik.ca/general/2022/07/13/networkstates.html", + "originalTextFile": "/ipfs/QmY16SsM1uk7i2TLxGhUZR8iW74w4Luphry3SJeN6XyCTf/What do I think about network states.docx", + "__v": "1" + }, + "arbitrableChainID": 100, + "_v": "1.0.0" +} diff --git a/kleros-sdk/config/v1-metaevidence/linguo-meta-evidence2.json b/kleros-sdk/config/v1-metaevidence/linguo-meta-evidence2.json new file mode 100644 index 000000000..a16247f43 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/linguo-meta-evidence2.json @@ -0,0 +1,44 @@ +{ + "title": "Review a translation from Linguo", + "description": "Someone challenged a translation", + "rulingOptions": { + "titles": [ + "Yes, the translation should be accepted", + "No, the translation should not be accepted" + ], + "descriptions": [ + "Select this if you think the translation complies with the required criteria.", + "Select this if you think the translation does not comply with the required criteria." + ] + }, + "aliases": { + "0xc3600bfC9Ec2c20E4c7d22c9235b6ddE63BA99a8": "Requester" + }, + "category": "Translation", + "question": "Does the translation comply with the required criteria?", + "fileURI": "/ipfs/QmVabp1VjJNYzXDxbcWFdeK17RvvA9eQy6eJVf1T1AzS1a/linguo-translation-quality-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/Qmb5n6PgbshktJqGpwMAxP1moXEPaqq7ZvRufeXXhSPXxW/linguo-evidence-display/index.html", + "dynamicScriptURI": "/ipfs/QmPAHCRtSU844fdjNoEws8AgTpzzwsYwMF2wydtpvXAcoZ/linguo-script.js", + "dynamicScriptRequiredParams": [ + "disputeID", + "arbitrableContractAddress", + "arbitratorContractAddress", + "chainID", + "jsonRpcUrl" + ], + "metadata": { + "deadline": 1704067199, + "minPrice": "0", + "maxPrice": "500000000000000000000", + "sourceLanguage": "en-us", + "targetLanguage": "es", + "expectedQuality": "professional", + "title": "Moving beyond coin voting governance", + "wordCount": 5100, + "originalTextUrl": "https://vitalik.ca/general/2021/08/16/voting3.html", + "originalTextFile": "/ipfs/Qmaq181thsnUyUknbnbQfJUHYRTFvA8z83f9BKY68t5pnf/Moving beyond coin voting governance.docx", + "__v": "1" + }, + "arbitrableChainID": 100, + "_v": "1.0.0" +} diff --git a/kleros-sdk/config/v1-metaevidence/omen1.json b/kleros-sdk/config/v1-metaevidence/omen1.json new file mode 100644 index 000000000..a8ad1643a --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/omen1.json @@ -0,0 +1,43 @@ +{ + "title": "Add a list to Omen Verified Market enabled badges", + "description": "Someone requested to add a list to Omen Verified Market enabled badges.", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the list complies with the required criteria and should be added.", + "Select this if you think the list does not comply with the required criteria and should not be added." + ] + }, + "category": "Curated Lists", + "question": "Does the list comply with the required criteria?", + "fileURI": "/ipfs/QmZ7RVU7re1g8nXDbAFMHV99pyie3dn4cY7Ga2X4h8mDpV/reject-all-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmUbBGRTCH3zxTFSNJ1asUFtpwvyXasrzhzLxYVMoEW8Nc/index.html", + "evidenceDisplayInterfaceHash": "Bcd2grgxgJ1i88wpbF6iD4kaGkjp4gZfcsYxKJVMELZQLGurwLXQMPMJiNmn5Q6ctUbgwDUpXXwLspTTaWQWEoceE5", + "metadata": { + "tcrTitle": "Omen Verified Market enabled badges", + "tcrDescription": "A List of lists related to Omen Verified Market", + "columns": [ + { + "label": "Address", + "description": "The Badges list address", + "type": "GTCR address", + "isIdentifier": true + }, + { + "label": "Match File URI", + "description": "The URI to the JSON file for matching columns for each list.", + "type": "text" + } + ], + "itemName": "list", + "itemNamePlural": "lists", + "isConnectedTCR": true, + "requireRemovalEvidence": true, + "isTCRofTCRs": true, + "parentTCRAddress": "0xb72103eE8819F2480c25d306eEAb7c3382fBA612", + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/omen2.json b/kleros-sdk/config/v1-metaevidence/omen2.json new file mode 100644 index 000000000..851954c68 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/omen2.json @@ -0,0 +1,43 @@ +{ + "title": "Remove a list from Omen Verified Market enabled badges", + "description": "Someone requested to remove a list from Omen Verified Market enabled badges.", + "rulingOptions": { + "titles": [ + "Yes, Remove It", + "No, Don't Remove It" + ], + "descriptions": [ + "Select this if you think the list does not comply with the required criteria and should be removed.", + "Select this if you think the list complies with the required criteria and should not be removed." + ] + }, + "category": "Curated Lists", + "question": "Does the list comply with the required criteria?", + "fileURI": "/ipfs/QmZ7RVU7re1g8nXDbAFMHV99pyie3dn4cY7Ga2X4h8mDpV/reject-all-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmUbBGRTCH3zxTFSNJ1asUFtpwvyXasrzhzLxYVMoEW8Nc/index.html", + "evidenceDisplayInterfaceHash": "Bcd2grgxgJ1i88wpbF6iD4kaGkjp4gZfcsYxKJVMELZQLGurwLXQMPMJiNmn5Q6ctUbgwDUpXXwLspTTaWQWEoceE5", + "metadata": { + "tcrTitle": "Omen Verified Market enabled badges", + "tcrDescription": "A List of lists related to Omen Verified Market", + "columns": [ + { + "label": "Address", + "description": "The Badges list address", + "type": "GTCR address", + "isIdentifier": true + }, + { + "label": "Match File URI", + "description": "The URI to the JSON file for matching columns for each list.", + "type": "text" + } + ], + "itemName": "list", + "itemNamePlural": "lists", + "isConnectedTCR": true, + "requireRemovalEvidence": true, + "isTCRofTCRs": true, + "parentTCRAddress": "0xb72103eE8819F2480c25d306eEAb7c3382fBA612", + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/omen3.json b/kleros-sdk/config/v1-metaevidence/omen3.json new file mode 100644 index 000000000..f47dd55e9 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/omen3.json @@ -0,0 +1,43 @@ +{ + "title": "Add a market to Omen Verified Market", + "description": "Someone requested to add a market to Omen Verified Market", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the market complies with the required criteria and should be added.", + "Select this if you think the market does not comply with the required criteria and should not be added." + ] + }, + "category": "Curated Lists", + "question": "Does the market comply with the required criteria?", + "fileURI": "/ipfs/QmPhEBstumEP84eSftx9MwBmSXBCGRFJMPZauKVa9gBizh/omen-verified-market.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmUbBGRTCH3zxTFSNJ1asUFtpwvyXasrzhzLxYVMoEW8Nc/index.html", + "evidenceDisplayInterfaceHash": "Bcd2grgxgJ1i88wpbF6iD4kaGkjp4gZfcsYxKJVMELZQLGurwLXQMPMJiNmn5Q6ctUbgwDUpXXwLspTTaWQWEoceE5", + "metadata": { + "tcrTitle": "Omen Verified Market", + "tcrDescription": "Safe Omen markets which are unlikely to be considered invalid and are not tricky", + "columns": [ + { + "label": "Question", + "description": "The question of the market", + "type": "text", + "isIdentifier": true + }, + { + "label": "Market URL", + "description": "Link to the Omen market in the form https://omen.eth.link/#/MARKET_ADDRESS", + "type": "link", + "isIdentifier": true + } + ], + "itemName": "market", + "itemNamePlural": "markets", + "logoURI": "/ipfs/QmSvhGvYvwzWVeBPSvTmttAyFU3PLHczRtMMexVcSmfbbh/omen-badge-tcr-.png", + "requireRemovalEvidence": true, + "isTCRofTCRs": false, + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/omen4.json b/kleros-sdk/config/v1-metaevidence/omen4.json new file mode 100644 index 000000000..c2665fec0 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/omen4.json @@ -0,0 +1,43 @@ +{ + "title": "Remove a market from Omen Verified Market", + "description": "Someone requested to remove a market from Omen Verified Market", + "rulingOptions": { + "titles": [ + "Yes, Remove It", + "No, Don't Remove It" + ], + "descriptions": [ + "Select this if you think the market does not comply with the required criteria and should be removed.", + "Select this if you think the market complies with the required criteria and should not be removed." + ] + }, + "category": "Curated Lists", + "question": "Does the market comply with the required criteria?", + "fileURI": "/ipfs/QmPhEBstumEP84eSftx9MwBmSXBCGRFJMPZauKVa9gBizh/omen-verified-market.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmUbBGRTCH3zxTFSNJ1asUFtpwvyXasrzhzLxYVMoEW8Nc/index.html", + "evidenceDisplayInterfaceHash": "Bcd2grgxgJ1i88wpbF6iD4kaGkjp4gZfcsYxKJVMELZQLGurwLXQMPMJiNmn5Q6ctUbgwDUpXXwLspTTaWQWEoceE5", + "metadata": { + "tcrTitle": "Omen Verified Market", + "tcrDescription": "Safe Omen markets which are unlikely to be considered invalid and are not tricky", + "columns": [ + { + "label": "Question", + "description": "The question of the market", + "type": "text", + "isIdentifier": true + }, + { + "label": "Market URL", + "description": "Link to the Omen market in the form https://omen.eth.link/#/MARKET_ADDRESS", + "type": "link", + "isIdentifier": true + } + ], + "itemName": "market", + "itemNamePlural": "markets", + "logoURI": "/ipfs/QmSvhGvYvwzWVeBPSvTmttAyFU3PLHczRtMMexVcSmfbbh/omen-badge-tcr-.png", + "requireRemovalEvidence": true, + "isTCRofTCRs": false, + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/omen5.json b/kleros-sdk/config/v1-metaevidence/omen5.json new file mode 100644 index 000000000..8b6329f2b --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/omen5.json @@ -0,0 +1,43 @@ +{ + "title": "Add a list to The Registry enabled badges", + "description": "Someone requested to add a list to The Registry enabled badges.", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the list complies with the required criteria and should be added.", + "Select this if you think the list does not comply with the required criteria and should not be added." + ] + }, + "category": "Curated Lists", + "question": "Does the list comply with the required criteria?", + "fileURI": "/ipfs/QmZ7RVU7re1g8nXDbAFMHV99pyie3dn4cY7Ga2X4h8mDpV/reject-all-policy.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmWYu43qp5VTH9LFaUfFv7qDRfkSr7ZLNXZNxYqdpww3ts/index.html", + "evidenceDisplayInterfaceHash": "Bccx364PTgwmxVLmpoWgQMNMJLSAscbp7gbYf6aA9guUDW2wkzQHapcZNrgDcuxFVhngv8U8NAjrFUXfucSPUQ1b1W", + "metadata": { + "tcrTitle": "The Registry enabled badges", + "tcrDescription": "A List of lists related to The Registry", + "columns": [ + { + "label": "Address", + "description": "The Badges list address", + "type": "GTCR address", + "isIdentifier": true + }, + { + "label": "Match File URI", + "description": "The URI to the JSON file for matching columns for each list.", + "type": "text" + } + ], + "itemName": "list", + "itemNamePlural": "lists", + "isConnectedTCR": true, + "requireRemovalEvidence": true, + "isTCRofTCRs": true, + "parentTCRAddress": "0xbA0304273a54dfeC1Fc7f4BCCbf4b15519AEcF15", + "relTcrDisabled": true + } +} diff --git a/kleros-sdk/config/v1-metaevidence/poh1.json b/kleros-sdk/config/v1-metaevidence/poh1.json new file mode 100644 index 000000000..868e4dfd4 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/poh1.json @@ -0,0 +1,19 @@ +{ + "category": "Curated List", + "title": "Proof of Humanity Registration Request", + "description": "A request to register the specified entry to a list of provable humans.", + "question": "Should the request to register be accepted?", + "fileURI": "/ipfs/QmXDiiBAizCPoLqHvcfTzuMT7uvFEe1j3s4TgoWWd4k5np/proof-of-humanity-registry-policy-v1.3.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmSL8d82dMhcThwERWaF4LtmCa4hgV7TyPjAo4fKCzPVkv/index.html", + "rulingOptions": { + "type": "single-select", + "titles": [ + "Yes", + "No" + ], + "descriptions": [ + "Accept the request to register the entry.", + "Deny the request." + ] + } +} diff --git a/kleros-sdk/config/v1-metaevidence/poh2.json b/kleros-sdk/config/v1-metaevidence/poh2.json new file mode 100644 index 000000000..a3dcd1efe --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/poh2.json @@ -0,0 +1,19 @@ +{ + "category": "Curated List", + "title": "Proof of Humanity Clearing Request", + "description": "A request to remove the specified entry from a list of provable humans.", + "question": "Should the request to remove be accepted?", + "fileURI": "/ipfs/QmXDiiBAizCPoLqHvcfTzuMT7uvFEe1j3s4TgoWWd4k5np/proof-of-humanity-registry-policy-v1.3.pdf", + "evidenceDisplayInterfaceURI": "/ipfs/QmSL8d82dMhcThwERWaF4LtmCa4hgV7TyPjAo4fKCzPVkv/index.html", + "rulingOptions": { + "type": "single-select", + "titles": [ + "Yes", + "No" + ], + "descriptions": [ + "Accept the request to remove the entry.", + "Deny the request." + ] + } +} diff --git a/kleros-sdk/config/v1-metaevidence/reality.json b/kleros-sdk/config/v1-metaevidence/reality.json new file mode 100644 index 000000000..3be4c7834 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/reality.json @@ -0,0 +1,8 @@ +{ + "category": "Oracle", + "title": "Realitio Question", + "description": "A Realitio question has been raised to arbitration.", + "question": "Give the answer to the question.", + "evidenceDisplayInterfaceURI": "/ipfs/QmQTnGNbRFpsS8zevPZTZA2ZioBKWM6u1HVCf9vLWkRuEH/index.html", + "dynamicScriptURI": "/ipfs/QmNhs2mo7t8pydn7gg6ycrtT4mhfvhARLEoyMYgs9SDkH2" +} diff --git a/kleros-sdk/config/v1-metaevidence/realityWithAppeals-gnosis-moderate.json b/kleros-sdk/config/v1-metaevidence/realityWithAppeals-gnosis-moderate.json new file mode 100644 index 000000000..3c2dbcd71 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/realityWithAppeals-gnosis-moderate.json @@ -0,0 +1,21 @@ +{ + "category": "Oracle", + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "Give an answer to the question.", + "evidenceDisplayInterfaceURI": "/ipfs/QmVXEiTexPd4EcQTjrxbFa88ZNFkBB8kT8BQUxtVn8fZJB/index.html", + "dynamicScriptURI": "/ipfs/QmWWsDmvjhR9UVRgkcG75vAKzfK3vB85EkZzudnaxwfAWr/bundle.js", + "fileURI": "/ipfs/QmW4zDA8X95cyfAsW9Nq1t7XNTyP3sMQAWNRFoQhMpgAv7/Kleros%2520Moderate%2520x%2520Reality.eth%2520Oracle%2520-%2520Telegram%2520Content%2520Moderation%2520Question%2520Resolution%2520Policy.pdf", + "arbitrableChainID": "100", + "arbitratorChainID": "100", + "dynamicScriptRequiredParams": [ + "arbitrableChainID", + "arbitrableJsonRpcUrl", + "arbitrableContractAddress" + ], + "evidenceDisplayInterfaceRequiredParams": [ + "arbitrableChainID", + "arbitrableJsonRpcUrl", + "arbitrableContractAddress" + ] +} diff --git a/kleros-sdk/config/v1-metaevidence/realityWithAppeals-gnosis.json b/kleros-sdk/config/v1-metaevidence/realityWithAppeals-gnosis.json new file mode 100644 index 000000000..ff785421f --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/realityWithAppeals-gnosis.json @@ -0,0 +1,21 @@ +{ + "category": "Oracle", + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "Give an answer to the question.", + "evidenceDisplayInterfaceURI": "/ipfs/QmVXEiTexPd4EcQTjrxbFa88ZNFkBB8kT8BQUxtVn8fZJB/index.html", + "dynamicScriptURI": "/ipfs/QmceDSKpVa9o3ycQ1GD2mTTkAZ4AjPncucV4BcMdV4pazv/bundle.js", + "fileURI": "/ipfs/QmaUr6hnSVxYD899xdcn2GUVtXVjXoSXKZbce3zFtGWw4H/Question_Resolution_Policy.pdf", + "arbitrableChainID": "100", + "arbitratorChainID": "100", + "dynamicScriptRequiredParams": [ + "arbitrableChainID", + "arbitrableJsonRpcUrl", + "arbitrableContractAddress" + ], + "evidenceDisplayInterfaceRequiredParams": [ + "arbitrableChainID", + "arbitrableJsonRpcUrl", + "arbitrableContractAddress" + ] +} diff --git a/kleros-sdk/config/v1-metaevidence/realityWithAppeals.json b/kleros-sdk/config/v1-metaevidence/realityWithAppeals.json new file mode 100644 index 000000000..70ba17c44 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/realityWithAppeals.json @@ -0,0 +1,21 @@ +{ + "category": "Oracle", + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "Give an answer to the question.", + "evidenceDisplayInterfaceURI": "/ipfs/QmWCmzMB4zbzii8HV9HFGa8Evgt5i63GyveJtw2umxRrcX/reality-evidence-display-4/index.html", + "dynamicScriptURI": "/ipfs/QmWWsDmvjhR9UVRgkcG75vAKzfK3vB85EkZzudnaxwfAWr/bundle.js", + "fileURI": "/ipfs/QmaUr6hnSVxYD899xdcn2GUVtXVjXoSXKZbce3zFtGWw4H/Question_Resolution_Policy.pdf", + "arbitrableChainID": "1", + "arbitratorChainID": "1", + "dynamicScriptRequiredParams": [ + "arbitrableChainID", + "arbitrableJsonRpcUrl", + "arbitrableContractAddress" + ], + "evidenceDisplayInterfaceRequiredParams": [ + "arbitrableChainID", + "arbitrableJsonRpcUrl", + "arbitrableContractAddress" + ] +} diff --git a/kleros-sdk/config/v1-metaevidence/resolver.json b/kleros-sdk/config/v1-metaevidence/resolver.json new file mode 100644 index 000000000..660c5bb3e --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/resolver.json @@ -0,0 +1,20 @@ +{ + "title": "The Assassination Plot: The Case of Draco Malfoy vs. Albus Dumbledore", + "category": "Fictional", + "description": "In the Harry Potter and the Half-Blood Prince movie, there is a dispute between Albus Dumbledore and Draco Malfoy over the attempted assassination of Dumbledore.\n\n#Background: \nDraco Malfoy, a student at Hogwarts School of Witchcraft and Wizardry and a member of the pure-blood Malfoy family, is entrusted with the task of assassinating Dumbledore by Lord Voldemort. Dumbledore becomes aware of the plot and confronts Malfoy, offering him a chance to back out and revealing the true extent of the danger and moral implications of his actions. However, Malfoy ultimately decides to go through with the assassination attempt, leading to a confrontation between Dumbledore and Malfoy.\n\nAfter considering all the evidence, the jurors would have to decide whether Malfoy was guilty of attempted murder or if he was acting under duress. The Kleros Court's decision would be final and binding, bringing a resolution to the dispute.", + "aliases": {}, + "question": "Was Draco Malfoy guilty of attempted murder in the assassination plot against Albus Dumbledore?", + "rulingOptions": { + "type": "single-select", + "titles": [ + "Yes", + "No" + ], + "descriptions": [ + "Draco Malfoy is guilty of attempted murder in the assassination plot against Albus Dumbledore.", + "Draco Malfoy is not guilty of attempted murder in the assassination plot against Albus Dumbledore." + ] + }, + "fileURI": "", + "dynamicScriptURI": "/ipfs/QmZZHwVaXWtvChdFPG4UeXStKaC9aHamwQkNTEAfRmT2Fj" +} diff --git a/kleros-sdk/config/v1-metaevidence/tokens-ethfinex1.json b/kleros-sdk/config/v1-metaevidence/tokens-ethfinex1.json new file mode 100644 index 000000000..689ec2e79 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/tokens-ethfinex1.json @@ -0,0 +1,28 @@ +{ + "category": "Curated Lists", + "title": "Add Ethfinex Badge to Token", + "description": "Someone requested to add the the Ethfinex badge to a token.\n\nDescription\n\nTokens with the Ethfinex badge can participate in the Ethfinex Community Vote to become traded on the Ethfinex platform. To be eligible to receive the badge, the project and it's associated token must comply with the minimum set of criteria defined in the criteria document.", + "aliases": { + "0x988b3a538b618c7a603e1c11ab82cd16dbe28069": "Arbitrator" + }, + "question": "Should the badge be added to the token?", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the token and project comply with the required criteria and the badge should be added.", + "Select this if you think the token and/or project do(es) not comply with the required criteria and the badge should not be added." + ] + }, + "fileURI": "/ipfs/QmVzwEBpGsbFY3UgyjA3SxgGXx3r5gFGynNpaoXkp6jenu/Ethfinex%20Court%20Policy.pdf", + "evidenceDisplayInterfaceURL": "https://badge-evidence.netlify.com", + "evidenceDisplayInterfaceHash": "Bccx3a2NSSihnHisifP6H67uYw7BeECZkXKYnBB8Vb9zbACNwzLWFyBbyudkJuGZMtNphEnyuwq5zup8ewdAyEmhjb", + "variables": { + "title": "Ethfinex Listing", + "symbolURI": "/ipfs/QmW3JLmpHnf7qNT4FYaguAF1Awma8adk81jUTuFWY1HVge/ethfinex.svg", + "description": "Tokens compliant with the Ethfinex Listing Criteria are eligible to participate in the Ethfinex Community Vote and become traded on the Ethfinex platform.", + "criteriaDescription": "To be eligible to receive the badge, the project and it's associated token must comply with the Ethfinex Listing Criteria." + } +} diff --git a/kleros-sdk/config/v1-metaevidence/tokens-ethfinex2.json b/kleros-sdk/config/v1-metaevidence/tokens-ethfinex2.json new file mode 100644 index 000000000..c5261f96f --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/tokens-ethfinex2.json @@ -0,0 +1,28 @@ +{ + "category": "Curated Lists", + "title": "Remove Ethfinex Badge From Token", + "description": "Someone requested to remove the the Ethfinex badge from a token.\n\nDescription\n\nTokens with the Ethfinex badge can participate in the Ethfinex Community Vote to become traded on the Ethfinex platform. To be eligible to receive the badge, the project and it's associated token must comply with the minimum set of criteria defined in the criteria document.", + "aliases": { + "0x988b3a538b618c7a603e1c11ab82cd16dbe28069": "Arbitrator" + }, + "question": "Should the badge be removed from the token?", + "rulingOptions": { + "titles": [ + "Yes, Remove It", + "No, Don't Remove It" + ], + "descriptions": [ + "Select this if you think the token and/or project do(es) not comply with the required criteria and the badge should be removed.", + "Select this if you think the token and project comply with the required criteria and the badge should be kept." + ] + }, + "fileURI": "/ipfs/QmVzwEBpGsbFY3UgyjA3SxgGXx3r5gFGynNpaoXkp6jenu/Ethfinex%20Court%20Policy.pdf", + "evidenceDisplayInterfaceURL": "https://badge-evidence.netlify.com", + "evidenceDisplayInterfaceHash": "Bccx3a2NSSihnHisifP6H67uYw7BeECZkXKYnBB8Vb9zbACNwzLWFyBbyudkJuGZMtNphEnyuwq5zup8ewdAyEmhjb", + "variables": { + "title": "Ethfinex Listing", + "symbolURI": "/ipfs/QmW3JLmpHnf7qNT4FYaguAF1Awma8adk81jUTuFWY1HVge/ethfinex.svg", + "description": "Tokens compliant with the Ethfinex Listing Criteria are eligible to participate in the Ethfinex Community Vote and become traded on the Ethfinex platform.", + "criteriaDescription": "To be eligible to receive the badge, the project and it's associated token must comply with the Ethfinex Listing Criteria." + } +} diff --git a/kleros-sdk/config/v1-metaevidence/tokens1.json b/kleros-sdk/config/v1-metaevidence/tokens1.json new file mode 100644 index 000000000..737e2381e --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/tokens1.json @@ -0,0 +1,21 @@ +{ + "category": "Curated Lists", + "title": "Add Token to Registry", + "description": "Someone requested to add a token to the token curated registry of tokens.", + "aliases": { + "0x988b3a538b618c7a603e1c11ab82cd16dbe28069": "Arbitrator" + }, + "question": "Should the token be added to the registry?", + "rulingOptions": { + "titles": [ + "Yes, Add It", + "No, Don't Add It" + ], + "descriptions": [ + "Select this if you think the token information is correct and the token should be added to the registry.", + "Select this if you think the token information is incorrect and the token should be not be added to the registry." + ] + }, + "fileURI": "/ipfs/QmTL1SCKpRcr7NRbVpXW6z9QoQXRHJT5cQr6PEge5qoLwU/t2cr-primary-document.pdf", + "evidenceDisplayInterfaceURL": "https://ipfs.kleros.io/ipfs/QmYs17mAJTaQwYeXNTb6n4idoQXmRcAjREeUdjJShNSeKh/index.html" +} diff --git a/kleros-sdk/config/v1-metaevidence/tokens2.json b/kleros-sdk/config/v1-metaevidence/tokens2.json new file mode 100644 index 000000000..63793dedc --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/tokens2.json @@ -0,0 +1,21 @@ +{ + "category": "Curated Lists", + "title": "Remove Token from Registry", + "description": "Someone requested to remove a token from a token curated registry of tokens.", + "aliases": { + "0x988b3a538b618c7a603e1c11ab82cd16dbe28069": "Arbitrator" + }, + "question": "Should the token be removed from the registry?", + "rulingOptions": { + "titles": [ + "Yes, Remove It", + "No, Keep It" + ], + "descriptions": [ + "Select this if you think the token information is incorrect and the token should be removed from the registry.", + "Select this if you think the token information is correct and the token should not be removed from the registry." + ] + }, + "fileURI": "/ipfs/QmTL1SCKpRcr7NRbVpXW6z9QoQXRHJT5cQr6PEge5qoLwU/t2cr-primary-document.pdf", + "evidenceDisplayInterfaceURL": "https://ipfs.kleros.io/ipfs/QmYs17mAJTaQwYeXNTb6n4idoQXmRcAjREeUdjJShNSeKh/index.html" +} diff --git a/kleros-sdk/config/v1-metaevidence/unslashed.json b/kleros-sdk/config/v1-metaevidence/unslashed.json new file mode 100644 index 000000000..5745cda90 --- /dev/null +++ b/kleros-sdk/config/v1-metaevidence/unslashed.json @@ -0,0 +1,19 @@ +{ + "category": "Insurance", + "title": "Unslashed insurance claim", + "description": "The claimant requested a compensation for damages covered by Unslashed insurance in the provided amount.", + "question": "Should their claim be paid out?", + "rulingOptions": { + "type": "single-select", + "titles": [ + "Accept the claim", + "Reject the claim" + ], + "descriptions": [ + "Accept the claim if the claimant 1) incurred the alleged damages, 2) is covered by a relevant policy, 3) the damages and their cover are at least the claimed amount at the moment when the claim was filled.", + "Reject the claim if any of the acceptance criteria do not hold." + ] + }, + "fileURI": "/ipfs/QmeTBY7jZe2ut5WjifNASADo3E4zBxkMd62WwBpXtwP9pg", + "evidenceDisplayInterfaceURI": "https://app.unslashed.finance/embed/claims" +} diff --git a/kleros-sdk/config/v2-disputetemplate/DisputeDetails.default.jsonc b/kleros-sdk/config/v2-disputetemplate/DisputeDetails.default.jsonc new file mode 100644 index 000000000..32decb39f --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/DisputeDetails.default.jsonc @@ -0,0 +1,23 @@ +{ + // Sensible defaults which are not expected to be specified by the arbitrable. + "type": "single-select", + "answers": [ + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "reserved": false + }, + { + "id": "0x02", + "reserved": false + } + ], + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "lang": "en_US", + "specification": "KIP000" +} diff --git a/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json b/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json new file mode 100644 index 000000000..bb94f67b2 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/NewDisputeTemplate.schema.json @@ -0,0 +1,348 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "NewDisputeTemplate.schema.json", + "type": "object", + "default": {}, + "title": "Root Schema", + "required": [ + "title", + "description", + "question", + "frontendUrl", + "policyURI", + "arbitrableChainID", + "arbitrableAddress", + "arbitratorChainID", + "arbitratorAddress" + ], + "additionalProperties": false, + "properties": { + "$schema": { + "description": "JSON Schema URI (used by some editors)", + "type": "string", + "default": "NewDisputeTemplate.schema.json" + }, + "category": { + "type": "string", + "default": "", + "title": "The category Schema", + "examples": [ + "Oracle" + ] + }, + "lang": { + "type": "string", + "default": "", + "title": "The lang Schema", + "examples": [ + "en_US" + ] + }, + "title": { + "type": "string", + "default": "", + "title": "The title Schema", + "examples": [ + "A reality.eth question", + "Add Ethfinex Badge to Token", + "Add Token to Registry", + "Add a list to Consensus Layer Withdrawal Protection enabled badges", + "Add a list to Omen Verified Market enabled badges", + "Add a list to The Registry enabled badges", + "Add a market to Omen Verified Market", + "Add a validator to Consensus Layer Withdrawal Protection", + "Add an entry to Ledger Contract Domain Name registry v2", + "Proof of Humanity Clearing Request", + "Proof of Humanity Registration Request", + "Realitio Question", + "Remove Ethfinex Badge From Token", + "Remove Token from Registry", + "Remove a list from Consensus Layer Withdrawal Protection enabled badges", + "Remove a list from Omen Verified Market enabled badges", + "Remove a market from Omen Verified Market", + "Remove a validator from Consensus Layer Withdrawal Protection", + "Remove an entry from Ledger Contract Domain Name registry v2", + "Review a translation from Linguo", + "Unslashed insurance claim" + ] + }, + "description": { + "type": "string", + "default": "", + "title": "The description Schema", + "examples": [ + "A Reality.eth question has been raised to arbitration.", + "A request to register the specified entry to a list of provable humans.", + "A request to remove the specified entry from a list of provable humans.", + "Someone challenged a translation", + "Someone requested to add a list to Consensus Layer Withdrawal Protection enabled badges.", + "Someone requested to add a list to Omen Verified Market enabled badges.", + "Someone requested to add a list to The Registry enabled badges.", + "Someone requested to add a market to Omen Verified Market", + "Someone requested to add a token to the token curated registry of tokens.", + "Someone requested to add a validator to Consensus Layer Withdrawal Protection", + "Someone requested to add an entry to Ledger Contract Domain Name registry v2", + "Someone requested to add the the Ethfinex badge to a token.\n\nDescription\n\nTokens with the Ethfinex badge can participate in the Ethfinex Community Vote to become traded on the Ethfinex platform. To be eligible to receive the badge, the project and it's associated token must comply with the minimum set of criteria defined in the criteria document.", + "Someone requested to remove a list from Consensus Layer Withdrawal Protection enabled badges.", + "Someone requested to remove a list from Omen Verified Market enabled badges.", + "Someone requested to remove a market from Omen Verified Market", + "Someone requested to remove a token from a token curated registry of tokens.", + "Someone requested to remove a validator from Consensus Layer Withdrawal Protection", + "Someone requested to remove an entry from Ledger Contract Domain Name registry v2", + "Someone requested to remove the the Ethfinex badge from a token.\n\nDescription\n\nTokens with the Ethfinex badge can participate in the Ethfinex Community Vote to become traded on the Ethfinex platform. To be eligible to receive the badge, the project and it's associated token must comply with the minimum set of criteria defined in the criteria document.", + "The claimant requested a compensation for damages covered by Unslashed insurance in the provided amount." + ] + }, + "question": { + "type": "string", + "default": "", + "title": "The question Schema", + "examples": [ + "Does the entry comply with the required criteria?", + "Does the list comply with the required criteria?", + "Does the market comply with the required criteria?", + "Does the translation comply with the required criteria?", + "Does the validator comply with the required criteria?", + "Give the answer to the question.", + "Should the badge be added to the token?", + "Should the badge be removed from the token?", + "Should the request to register be accepted?", + "Should the request to remove be accepted?", + "Should the token be added to the registry?", + "Should the token be removed from the registry?", + "Should their claim be paid out?", + "Which party abided by terms of the contract?" + ] + }, + "type": { + "title": "The type Schema", + "description": "An explanation about the purpose of this instance.", + "type": "string", + "default": "single-select", + "examples": [ + "single-select" + ], + "enum": [ + "bool", + "uint", + "single-select", + "multiple-select", + "datetime" + ] + }, + "answers": { + "type": "array", + "default": [ + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Yes", + "description": "Accept the request.", + "reserved": false + }, + { + "id": "0x02", + "title": "No", + "description": "Refuse the request.", + "reserved": false + } + ], + "title": "The answers Schema", + "items": { + "type": "object", + "default": {}, + "title": "A Schema", + "required": [ + "title" + ], + "dependentSchemas": { + "id": { + "properties": { + "reserved": { + "const": true + } + } + } + }, + "if": { + "properties": { + "reserved": { + "const": true + } + } + }, + "then": { + "dependentRequired": { + "id": true + } + }, + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "default": "", + "title": "The id Schema", + "examples": [ + "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + "title": { + "type": "string", + "default": "", + "title": "The title Schema", + "examples": [ + "Accept the claim", + "No", + "No, Don't Add It", + "No, Don't Remove It", + "No, Keep It", + "No, the translation should not be accepted", + "Pay Receiver", + "Refund Sender", + "Reject the claim", + "Yes", + "Yes, Add It", + "Yes, Remove It", + "Yes, the translation should be accepted", + "Answered Too Soon", + "Invalid/Refuse to Arbitrate" + ] + }, + "description": { + "type": "string", + "default": "", + "title": "The description Schema", + "examples": [ + "Accept the request to register the entry.", + "Accept the request to remove the entry.", + "Deny the request.", + "Reject the claim if any of the acceptance criteria do not hold.", + "Select this if you think the entry complies with the required criteria and should be added.", + "Select this if you think the entry complies with the required criteria and should not be removed.", + "Select this if you think the entry does not comply with the required criteria and should be removed.", + "Select this if you think the entry does not comply with the required criteria and should not be added.", + "Select this if you think the list complies with the required criteria and should be added.", + "Select this if you think the list complies with the required criteria and should not be removed.", + "Select this if you think the list does not comply with the required criteria and should be removed.", + "Select this if you think the list does not comply with the required criteria and should not be added.", + "Select this if you think the market complies with the required criteria and should be added.", + "Select this if you think the market complies with the required criteria and should not be removed.", + "Select this if you think the market does not comply with the required criteria and should be removed.", + "Select this if you think the market does not comply with the required criteria and should not be added.", + "Select this if you think the token and project comply with the required criteria and the badge should be added.", + "Select this if you think the token and project comply with the required criteria and the badge should be kept.", + "Select this if you think the token and/or project do(es) not comply with the required criteria and the badge should be removed.", + "Select this if you think the token and/or project do(es) not comply with the required criteria and the badge should not be added.", + "Select this if you think the token information is correct and the token should be added to the registry.", + "Select this if you think the token information is correct and the token should not be removed from the registry.", + "Select this if you think the token information is incorrect and the token should be not be added to the registry.", + "Select this if you think the token information is incorrect and the token should be removed from the registry.", + "Select this if you think the translation complies with the required criteria.", + "Select this if you think the translation does not comply with the required criteria.", + "Select this if you think the validator complies with the required criteria and should be added.", + "Select this if you think the validator complies with the required criteria and should not be removed.", + "Select this if you think the validator does not comply with the required criteria and should be removed.", + "Select this if you think the validator does not comply with the required criteria and should not be added.", + "Select to release funds to the Receiver", + "Select to return funds to the Sender" + ] + }, + "reserved": { + "type": "boolean", + "default": false, + "title": "The reserved Schema", + "examples": [ + true, + false + ] + } + }, + "examples": [ + { + "title": "Yes", + "description": "Accept the request." + }, + { + "title": "No", + "description": "Refuse the request." + } + ] + } + }, + "frontendUrl": { + "type": "string", + "default": "", + "title": "The frontendUrl Schema", + "examples": [ + "https://curate.kleros.io/tcr/1/0x0000000000000000000000000000000000000000/0x0000000000000000000000000000000000000000000000000000000000000000", + "https://reality.eth.link/app/#!/question/0x0000000000000000000000000000000000000000000000000000000000000000/0" + ] + }, + "policyURI": { + "type": "string", + "default": "", + "title": "The policyURI Schema", + "examples": [ + "/ipfs/QmPhEBstumEP84eSftx9MwBmSXBCGRFJMPZauKVa9gBizh/omen-verified-market.pdf", + "/ipfs/QmPtXtFKfVc3w5aGVNYrmBZWEHBLpk2XMLkYCnEioxwy43/clwp-acceptance-policy.pdf", + "/ipfs/QmTL1SCKpRcr7NRbVpXW6z9QoQXRHJT5cQr6PEge5qoLwU/t2cr-primary-document.pdf", + "/ipfs/QmVabp1VjJNYzXDxbcWFdeK17RvvA9eQy6eJVf1T1AzS1a/linguo-translation-quality-policy.pdf", + "/ipfs/QmVzwEBpGsbFY3UgyjA3SxgGXx3r5gFGynNpaoXkp6jenu/Ethfinex%20Court%20Policy.pdf", + "/ipfs/QmW4zDA8X95cyfAsW9Nq1t7XNTyP3sMQAWNRFoQhMpgAv7/Kleros%2520Moderate%2520x%2520Reality.eth%2520Oracle%2520-%2520Telegram%2520Content%2520Moderation%2520Question%2520Resolution%2520Policy.pdf", + "/ipfs/QmXDiiBAizCPoLqHvcfTzuMT7uvFEe1j3s4TgoWWd4k5np/proof-of-humanity-registry-policy-v1.3.pdf", + "/ipfs/QmZ7RVU7re1g8nXDbAFMHV99pyie3dn4cY7Ga2X4h8mDpV/reject-all-policy.pdf", + "/ipfs/QmaUr6hnSVxYD899xdcn2GUVtXVjXoSXKZbce3zFtGWw4H/Question_Resolution_Policy.pdf", + "/ipfs/QmdvkC5Djgk8MfX5ijJR3NJzmvGugUqvui7bKuTErSD6cE/contract-domain-name-registry-for-ledger-policy-3-.pdf", + "/ipfs/QmeTBY7jZe2ut5WjifNASADo3E4zBxkMd62WwBpXtwP9pg" + ] + }, + "arbitrableChainID": { + "type": "string", + "default": "", + "title": "The arbitrableChainID Schema", + "examples": [ + "1", + "100" + ] + }, + "arbitrableAddress": { + "type": "string", + "default": "", + "title": "The arbitrableAddress Schema", + "examples": [ + "0x2e39b8f43d0870ba896f516f78f57cde773cf805" + ] + }, + "arbitratorChainID": { + "type": "string", + "default": "", + "title": "The arbitratorChainID Schema", + "examples": [ + "421613" + ] + }, + "arbitratorAddress": { + "type": "string", + "default": "", + "title": "The arbitratorAddress Schema", + "examples": [ + "0xD08Ab99480d02bf9C092828043f611BcDFEA917b" + ] + }, + "specification": { + "type": "string", + "default": "", + "title": "The specification Schema", + "examples": [ + "KIP00", + "KIP99" + ] + } + } +} diff --git a/kleros-sdk/config/v2-disputetemplate/README.md b/kleros-sdk/config/v2-disputetemplate/README.md new file mode 100644 index 000000000..1122f0315 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/README.md @@ -0,0 +1,51 @@ +# V2 BREAKING CHANGES + +## Onchain changes + +### IArbitrator + +#### The appeal events and functions have been removed + +The appeal concerns are deemed implementation-specific so they have been removed from the Arbitrator interface. + +The following have been removed from the Arbitrator interface but are available directly on KlerosCore: + +```solidity +function appealCost(uint256 _disputeID) external view returns (uint256 cost); + +function appealPeriod(uint256 _disputeID) external view returns (uint256 start, uint256 end); +``` + +The following have been removed entirely: + +```solidity +event AppealPossible(uint256 indexed _disputeID, IArbitrableV1 indexed _arbitrable); +event AppealDecision(uint256 indexed _disputeID, IArbitrableV1 indexed _arbitrable); +function appeal(uint256 _disputeID, bytes calldata _extraData) external payable; +``` + +The appeal requests are now the responsibility of the DisputeKit implementation. For example in the DisputeKitClassic there is now: + +```solidity +// DisputeKitClassic.sol +function fundAppeal(uint256 _coreDisputeID, uint256 _choice) payable; + +function getFundedChoices(uint256 _coreDisputeID) view returns (uint256[] memory fundedChoices); +``` + +#### `DisputeStatus` has been removed + +It was deemed redundant. An equivalent behavior can be emulated as follow: + +```solidity +// for a particular disputeID +(,,IArbitrator.Period period,,) = arbitrator.disputes(disputeID); + +if (period < IArbitratorV2.Period.appeal) + // Do DisputeStatus.Waiting stuffs +else if (_period < IArbitratorV2.Period.execution) + // Do DisputeStatus.Appealable stuffs +else + // Do DisputeStatus.Solved stuffs +} +``` diff --git a/kleros-sdk/config/v2-disputetemplate/curate/NewDisputeTemplate.curate.jsonc b/kleros-sdk/config/v2-disputetemplate/curate/NewDisputeTemplate.curate.jsonc new file mode 100644 index 000000000..bb99c033a --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/curate/NewDisputeTemplate.curate.jsonc @@ -0,0 +1,24 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "Add an entry to Ledger Contract Domain Name registry v2", + "description": "Someone requested to add an entry to Ledger Contract Domain Name registry v2", + "question": "Does the entry comply with the required criteria?", + "answers": [ + { + "title": "Yes, Add It", + "description": "Select this if you think the entry complies with the required criteria and should be added." + }, + { + "title": "No, Don't Add It", + "description": "Select this if you think the entry does not comply with the required criteria and should not be added." + } + ], + "policyURI": "/ipfs/QmdvkC5Djgk8MfX5ijJR3NJzmvGugUqvui7bKuTErSD6cE/contract-domain-name-registry-for-ledger-policy-3-.pdf", + "frontendUrl": "https://curate.kleros.io/tcr/%s/%s/%s", + "arbitrableChainID": "100", + "arbitrableAddress": "0x957A53A994860BE4750810131d9c876b2f52d6E1", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Curated Lists", + "specification": "KIP88" +} diff --git a/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeDetails.curate.jsonc b/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeDetails.curate.jsonc new file mode 100644 index 000000000..e00b87af4 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeDetails.curate.jsonc @@ -0,0 +1,70 @@ +{ + "$schema": "./DisputeDetails.curate.schema.json", + "title": "Add an entry to Ledger Contract Domain Name registry v2", + "description": "Someone requested to add an entry to Ledger Contract Domain Name registry v2", + "question": "Does the entry comply with the required criteria?", + "type": "single-select", + "answers": [ + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Yes, Add It", + "description": "Select this if you think the entry complies with the required criteria and should be added.", + "reserved": false + }, + { + "id": "0x02", + "title": "No, Don't Add It", + "description": "Select this if you think the entry does not comply with the required criteria and should not be added.", + "reserved": false + } + ], + "policyURI": "/ipfs/QmdvkC5Djgk8MfX5ijJR3NJzmvGugUqvui7bKuTErSD6cE/contract-domain-name-registry-for-ledger-policy-3-.pdf", + "frontendUrl": "https://curate.kleros.io/tcr/100/0x957A53A994860BE4750810131d9c876b2f52d6E1/0xc2c1aa705632f53051f22a9f65967c0944370020a7489aba608bd0d755ca1234", + "arbitrableChainID": "100", + "arbitrableAddress": "0x957A53A994860BE4750810131d9c876b2f52d6E1", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Curated Lists", + "lang": "en_US", + "specification": "KIP88", + "metadata": { + "tcrTitle": "Ledger Contract Domain Name registry v2", + "tcrDescription": "A list of contract addresses and the domain names they are meant to be used from .", + "columns": [ + { + "label": "Contract address", + "description": "The address of the contract in question. Case-sensitive only if required by the blockchain that the address pertains to (e.g. Solana). ", + "type": "rich address", + "isIdentifier": true + }, + { + "label": "Domain name", + "description": "The specific (sub)domain name of the dApp where this contract is meant to be accessed from. Wildcards (*) are acceptable as part of this field if proof can be shown that the contract is intended to be used across multiple domains.", + "type": "text", + "isIdentifier": true + }, + { + "label": "Visual proof", + "description": "If the domain is a specific root or subdomain, this must be a screenshot of the exact page and setup where this particular address can be interacted from.", + "type": "image", + "isIdentifier": false + } + ], + "itemName": "entry", + "itemNamePlural": "entries", + "logoURI": "/ipfs/QmNNSDkpyDX1wB4NNFdAzaHsJihpvgNVV89zCH8FH9CVAz/ledger-white.png", + "requireRemovalEvidence": true, + "isTCRofTCRs": false, + "relTcrDisabled": true + }, + "externalDisputeID": "0x32554266108048001186322211785477470843107987690258181975452540727388224860514", // hash(itemID, requestID) + "arbitrableDisputeID": "91", + "arbitratorDisputeID": "4565", + "disputeTemplateID": "44", + "disputeTemplateHash": "0xD1u9...2254" +} diff --git a/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeTemplateInputs.curate.txt b/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeTemplateInputs.curate.txt new file mode 100644 index 000000000..186ef2be9 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/curate/example/DisputeTemplateInputs.curate.txt @@ -0,0 +1,3 @@ +100 +0x957A53A994860BE4750810131d9c876b2f52d6E1 +0xc2c1aa705632f53051f22a9f65967c0944370020a7489aba608bd0d755ca1234 \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/curate/example/NewDispute.curate.jsonc b/kleros-sdk/config/v2-disputetemplate/curate/example/NewDispute.curate.jsonc new file mode 100644 index 000000000..f1535733b --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/curate/example/NewDispute.curate.jsonc @@ -0,0 +1,11 @@ +{ + "externalDisputeID": "32554266108048001186322211785477470843107987690258181975452540727388224860514", // hash(itemID, requestID) + "arbitrableDisputeID": "91", + "templateID": "44" +} + +/** + Contribution._itemID = 0xC2C1AA705632F53051F22A9F65967C0944370020A7489ABA608BD0D755CA1234 + Contribution._requestID = 0 + Dispute._evidenceGroupID = hash(itemID, requestID) = 0x32554266108048001186322211785477470843107987690258181975452540727388224860514 +**/ \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/kip-template.md b/kleros-sdk/config/v2-disputetemplate/kip-template.md new file mode 100644 index 000000000..bb1f58f77 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/kip-template.md @@ -0,0 +1,40 @@ +--- +kip: <#> +title: +author: <a comma separated list of the author's or authors' name + GitHub username (in parenthesis), or name and email (in angle brackets). Example, FirstName LastName (@GitHubUsername), FirstName LastName <foo@bar.com>, FirstName (@GitHubUsername) and GitHubUsername (@GitHubUsername)> +discussions-to: https://forum.kleros.io/c/proposal/<#> +status: <Draft, Last Call, Approved, Final, Abandoned, Rejected> +type: <Core, Parameter, Arbitrable> +created: <yyyy-mm-dd> +requires: <KIP number(s)> # Only required when you reference an KIP in the `Specification` section. Otherwise, remove this field. +--- + +## Summary + +2-5 sentences providing a simplified and layman-accessible explanation of the issue. + +## Motivation + +The motivation is critical to change the KIP protocol. +It should clearly explain why the existing protocol specification is inadequate with respect to the issue raised. + +## Technical Specification + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174. + +The technical specification should describe the syntax and semantics of the proposed solution for the issue raised. +If a suggestion is proposed, provide sufficient details so that an implementation would be possible (Proof of Concepts are acceptable). + +## Rationale + +The rationale should flesh out the specification by describing what motivated the design and why particular design decisions were made, as well as any alternative designs that were considered. + +## Implementation + +An implementation must be completed before any KIP proceeds to “Last Call” status. + +## Backwards Compatibility + +## Security considerations + +All KIPs must include a discussion of the security implications/considerations relevant to the proposed change as well as proposed mitigations. A KIP cannot proceed to “Final” status without a sufficient security review from the core team. diff --git a/kleros-sdk/config/v2-disputetemplate/linguo/NewDisputeTemplate.linguo.jsonc b/kleros-sdk/config/v2-disputetemplate/linguo/NewDisputeTemplate.linguo.jsonc new file mode 100644 index 000000000..e97ee3b0b --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/linguo/NewDisputeTemplate.linguo.jsonc @@ -0,0 +1,24 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "Review a translation from Linguo", + "description": "Someone challenged a translation", + "question": "Does the translation comply with the required criteria?", + "answers": [ + { + "title": "Yes, the translation should be accepted", + "description": "Select this if you think the translation complies with the required criteria." + }, + { + "title": "No, the translation should not be accepted", + "description": "Select this if you think the translation does not comply with the required criteria." + } + ], + "policyURI": "/ipfs/QmVabp1VjJNYzXDxbcWFdeK17RvvA9eQy6eJVf1T1AzS1a/linguo-translation-quality-policy.pdf", + "frontendUrl": "https://linguo.kleros.io/translation/%s/%s", + "arbitrableChainID": "100", + "arbitrableAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Translation", + "specification": "KIP999" +} diff --git a/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeDetails.linguo.jsonc b/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeDetails.linguo.jsonc new file mode 100644 index 000000000..e8119f2d8 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeDetails.linguo.jsonc @@ -0,0 +1,61 @@ +{ + "$schema": "./DisputeDetails.linguo.schema.json", + "title": "Review a translation from Linguo", + "description": "Someone challenged a translation", + "question": "Does the translation comply with the required criteria?", + "type": "single-select", + "answers": [ + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Yes, the translation should be accepted", + "description": "Select this if you think the translation complies with the required criteria.", + "reserved": false + }, + { + "id": "0x02", + "title": "No, the translation should not be accepted", + "description": "Select this if you think the translation does not comply with the required criteria.", + "reserved": false + } + ], + "policyURI": "/ipfs/QmVabp1VjJNYzXDxbcWFdeK17RvvA9eQy6eJVf1T1AzS1a/linguo-translation-quality-policy.pdf", + "frontendUrl": "https://linguo.kleros.io/translation/0xe78996a233895be74a66f451f1019ca9734205cc/13", + "arbitrableChainID": "100", + "arbitrableAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Translation", + "lang": "en_US", + "specification": "KIP999", + "metadata": { + "linguoAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", + "linguoTranslationID": "76", + "linguoDeadline": "1680307199", + "linguoSourceLanguage": "en-us", + "linguoTargetLanguage": "es", + "linguoExpectedQuality": "professional", + "linguoTitle": "What do I think about network states?", + "linguoWordCount": "7900", + "linguoOriginalTextUrl": "https://vitalik.ca/general/2022/07/13/networkstates.html", + "linguoOriginalTextFile": "/ipfs/QmY16SsM1uk7i2TLxGhUZR8iW74w4Luphry3SJeN6XyCTf/What do I think about network states.docx", + "linguoAssignedPrice": "81670000000000000000", + "linguoMinimumPrice": "0", + "linguoMaximumPrice": "500000000000000000000", + + // https://github.com/kleros/linguo-script/blob/master/src/index.js#L31-L44 + "linguoRequester": "0xabc996a233895be74a66f451f1019ca97342aaaa", + "linguoTranslator": "0xbcd996a233895be74a66f451f1019ca97342bbbb", + "linguoChallenger": "0xcde996a233895be74a66f451f1019ca97342cccc", + "linguoFrontendUrl": "https://linguo.kleros.io/translation/0x0B928165A67df8254412483ae8C3b8cc7F2b4D36/35" + }, + "externalDisputeID": "13", // taskID + "arbitrableDisputeID": "7", + "arbitratorDisputeID": "4564", + "disputeTemplateID": "43", + "disputeTemplateHash": "0xD1u9...2254" +} diff --git a/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeTemplateInputs.linguo.txt b/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeTemplateInputs.linguo.txt new file mode 100644 index 000000000..a4f8f13ce --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/linguo/example/DisputeTemplateInputs.linguo.txt @@ -0,0 +1,2 @@ +0xe78996a233895be74a66f451f1019ca9734205cc +13 \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/linguo/example/NewDispute.linguo.jsonc b/kleros-sdk/config/v2-disputetemplate/linguo/example/NewDispute.linguo.jsonc new file mode 100644 index 000000000..d113123a1 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/linguo/example/NewDispute.linguo.jsonc @@ -0,0 +1,5 @@ +{ + "externalDisputeID": "13", // taskID + "arbitrableDisputeID": "7", + "templateID": "43" +} diff --git a/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh1.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh1.jsonc new file mode 100644 index 000000000..aa644fb1e --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh1.jsonc @@ -0,0 +1,24 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "Proof of Humanity Registration Request", + "description": "A request to register the specified entry to a list of provable humans.", + "question": "Should the request to register be accepted?", + "answers": [ + { + "title": "Yes", + "description": "Accept the request to register the entry." + }, + { + "title": "No", + "description": "Deny the request." + } + ], + "policyURI": "/ipfs/QmXDiiBAizCPoLqHvcfTzuMT7uvFEe1j3s4TgoWWd4k5np/proof-of-humanity-registry-policy-v1.3.pdf", + "frontendUrl": "https://app.proofofhumanity.id/profile/%s", + "arbitrableChainID": "1", + "arbitrableAddress": "0xc5e9ddebb09cd64dfacab4011a0d5cedaf7c9bdb", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Curated Lists", + "specification": "KIP88" +} diff --git a/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh2.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh2.jsonc new file mode 100644 index 000000000..f9225b917 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/NewDisputeTemplate.poh2.jsonc @@ -0,0 +1,24 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "Proof of Humanity Clearing Request", + "description": "A request to remove the specified entry from a list of provable humans.", + "question": "Should the request to remove be accepted?", + "answers": [ + { + "title": "Yes", + "description": "Accept the request to register the entry." + }, + { + "title": "No", + "description": "Deny the request." + } + ], + "policyURI": "/ipfs/QmXDiiBAizCPoLqHvcfTzuMT7uvFEe1j3s4TgoWWd4k5np/proof-of-humanity-registry-policy-v1.3.pdf", + "frontendUrl": "https://app.proofofhumanity.id/profile/%s", + "arbitrableChainID": "1", + "arbitrableAddress": "0xc5e9ddebb09cd64dfacab4011a0d5cedaf7c9bdb", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Curated Lists", + "specification": "KIP88" +} diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeDetails.poh1.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeDetails.poh1.jsonc new file mode 100644 index 000000000..373f72556 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeDetails.poh1.jsonc @@ -0,0 +1,42 @@ +{ + "$schema": "./DisputeDetails.poh.schema.json", + "title": "Proof of Humanity Registration Request", + "description": "A request to register the specified entry to a list of provable humans.", + "question": "Should the request to register be accepted?", + "type": "single-select", + "answers": [ + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Yes", + "description": "Accept the request to register the entry.", + "reserved": false + }, + { + "id": "0x02", + "title": "No", + "description": "Deny the request.", + "reserved": false + } + ], + "policyURI": "/ipfs/QmXDiiBAizCPoLqHvcfTzuMT7uvFEe1j3s4TgoWWd4k5np/proof-of-humanity-registry-policy-v1.3.pdf", + "frontendUrl": "https://app.proofofhumanity.id/profile/0x35998E80B3fa93cFD957D616e6f09cd830e9787c", + "arbitrableChainID": "1", + "arbitrableAddress": "0xc5e9ddebb09cd64dfacab4011a0d5cedaf7c9bdb", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Curated Lists", + "lang": "en_US", + "specification": "KIP77", + "metadata": { + }, + "externalDisputeID": "0x306000938609016839401998194416306598562578921596", // hash(itemID, requestID) + "arbitrableDisputeID": "1556", + "arbitratorDisputeID": "4568", + "disputeTemplateID": "46", + "disputeTemplateHash": "0x51u9...2226" +} diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeTemplateInputs.poh1.txt b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeTemplateInputs.poh1.txt new file mode 100644 index 000000000..ac0129395 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/DisputeTemplateInputs.poh1.txt @@ -0,0 +1 @@ +0x35998E80B3fa93cFD957D616e6f09cd830e9787c \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/NewDispute.poh1.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/NewDispute.poh1.jsonc new file mode 100644 index 000000000..7733da305 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/example1-registration/NewDispute.poh1.jsonc @@ -0,0 +1,11 @@ +{ + "externalDisputeID": "0x306000938609016839401998194416306598562578921596", // hash(itemID, requestID) + "arbitrableDisputeID": "1556", + "templateID": "46" +} + +/** + SubmissionChallenged._submissionID = 0x35998E80B3fa93cFD957D616e6f09cd830e9787c + SubmissionChallenged._requestID = 0 + Dispute._evidenceGroupID = hash(_submissionID, _requestID) = 0x306000938609016839401998194416306598562578921596 +**/ \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeDetails.poh2.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeDetails.poh2.jsonc new file mode 100644 index 000000000..d60c90757 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeDetails.poh2.jsonc @@ -0,0 +1,42 @@ +{ + "$schema": "./DisputeDetails.poh.schema.json", + "title": "Proof of Humanity Clearing Request", + "description": "A request to remove the specified entry from a list of provable humans.", + "question": "Should the request to remove be accepted?", + "type": "single-select", + "answers": [ + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Yes", + "description": "Accept the request to remove the entry.", + "reserved": false + }, + { + "id": "0x02", + "title": "No", + "description": "Deny the request.", + "reserved": false + } + ], + "policyURI": "/ipfs/QmXDiiBAizCPoLqHvcfTzuMT7uvFEe1j3s4TgoWWd4k5np/proof-of-humanity-registry-policy-v1.3.pdf", + "frontendUrl": "https://app.proofofhumanity.id/profile/0x35998E80B3fa93cFD957D616e6f09cd830e9787c", + "arbitrableChainID": "1", + "arbitrableAddress": "0xc5e9ddebb09cd64dfacab4011a0d5cedaf7c9bdb", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Curated Lists", + "lang": "en_US", + "specification": "KIP77", + "metadata": { + }, + "externalDisputeID": "0x2f0c53ed326eb88ef6a01ff83df458c1cebe5b9ee5e8509525189d9422e28983", // hash(itemID, requestID) + "arbitrableDisputeID": "1557", + "arbitratorDisputeID": "4569", + "disputeTemplateID": "47", + "disputeTemplateHash": "0x31u9...5550" +} diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeTemplateInputs.poh2.txt b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeTemplateInputs.poh2.txt new file mode 100644 index 000000000..ac0129395 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/DisputeTemplateInputs.poh2.txt @@ -0,0 +1 @@ +0x35998E80B3fa93cFD957D616e6f09cd830e9787c \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/NewDispute.poh2.jsonc b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/NewDispute.poh2.jsonc new file mode 100644 index 000000000..f313a7bbb --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/poh/example2-removal/NewDispute.poh2.jsonc @@ -0,0 +1,11 @@ +{ + "externalDisputeID": "0x2f0c53ed326eb88ef6a01ff83df458c1cebe5b9ee5e8509525189d9422e28983", // hash(itemID, requestID) + "arbitrableDisputeID": "1557", + "templateID": "47" +} + +/** + SubmissionChallenged._submissionID = 0x35998E80B3fa93cFD957D616e6f09cd830e9787c + SubmissionChallenged._requestID = 1 + Dispute._evidenceGroupID = hash(_submissionID, _requestID) = 0x2f0c53ed326eb88ef6a01ff83df458c1cebe5b9ee5e8509525189d9422e28983 +**/ \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/reality/DisputeDetails.reality.schema.json b/kleros-sdk/config/v2-disputetemplate/reality/DisputeDetails.reality.schema.json new file mode 100644 index 000000000..9eff1c055 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/DisputeDetails.reality.schema.json @@ -0,0 +1,247 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "DisputeDetails.reality.schema.json", + "title": "Root Schema", + "description": "The root schema is the schema that comprises the entire JSON document.", + "type": "object", + "required": [ + "title", + "description", + "question", + "type", + "answers", + "frontendUrl", + "policyURI", + "arbitrableChainID", + "arbitrableAddress", + "arbitratorChainID", + "arbitratorAddress", + "category", + "lang", + "specification", + "metadata", + "externalDisputeID", + "arbitrableDisputeID", + "arbitratorDisputeID", + "disputeTemplateID", + "disputeTemplateHash" + ], + "additionalProperties": false, + "properties": { + "title": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/title" + }, + "description": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/description" + }, + "question": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/question" + }, + "type": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/type" + }, + "answers": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/answers" + }, + "frontendUrl": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/frontendUrl" + }, + "policyURI": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/policyURI" + }, + "arbitrableChainID": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/arbitrableChainID" + }, + "arbitrableAddress": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/arbitrableAddress" + }, + "arbitratorChainID": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/arbitratorChainID" + }, + "arbitratorAddress": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/arbitratorAddress" + }, + "category": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/category" + }, + "lang": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/lang" + }, + "specification": { + "$ref": "../NewDisputeTemplate.schema.json#/properties/specification" + }, + "metadata": { + "type": "object", + "default": {}, + "title": "The metadata Schema", + "required": [ + "realityAddress", + "realityTemplateID", + "realityQuestionID", + "realityUser", + "realityType", + "realityCategory", + "realityLang", + "realityFormat", + "realityTimeout", + "realityOpeningTime", + "realityCreationTime", + "realityNonce" + ], + "properties": { + "realityAddress": { + "type": "string", + "default": "", + "title": "The realityAddress Schema", + "examples": [ + "0xe78996a233895be74a66f451f1019ca9734205cc" + ] + }, + "realityTemplateID": { + "type": "string", + "default": "", + "title": "The realityTemplateID Schema", + "examples": [ + "76" + ] + }, + "realityQuestionID": { + "type": "string", + "default": "", + "title": "The realityQuestionID Schema", + "examples": [ + "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39" + ] + }, + "realityUser": { + "type": "string", + "default": "", + "title": "The realityUser Schema", + "examples": [ + "0xe0441ecf50205d3548456b29fde2a3010f9a61f3" + ] + }, + "realityType": { + "type": "string", + "default": "", + "title": "The realityType Schema", + "examples": [ + "bool" + ] + }, + "realityCategory": { + "type": "string", + "default": "", + "title": "The realityCategory Schema", + "examples": [ + "content moderation" + ] + }, + "realityLang": { + "type": "string", + "default": "", + "title": "The realityLang Schema", + "examples": [ + "en_US" + ] + }, + "realityFormat": { + "type": "string", + "default": "", + "title": "The realityFormat Schema", + "examples": [ + "text/markdown" + ] + }, + "realityTimeout": { + "type": "string", + "default": "", + "title": "The realityTimeout Schema", + "examples": [ + "86400" + ] + }, + "realityOpeningTime": { + "type": "string", + "default": "", + "title": "The realityOpeningTime Schema", + "examples": [ + "1681263978" + ] + }, + "realityCreationTime": { + "type": "string", + "default": "", + "title": "The realityCreationTime Schema", + "examples": [ + "1681263995" + ] + }, + "realityNonce": { + "type": "string", + "default": "", + "title": "The realityNonce Schema", + "examples": [ + "3" + ] + } + }, + "examples": [ + { + "realityAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", + "realityTemplateID": "76", + "realityQuestionID": "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", + "realityUser": "0xe0441ecf50205d3548456b29fde2a3010f9a61f3", + "realityType": "bool", + "realityCategory": "content moderation", + "realityLang": "en_US", + "realityFormat": "text/markdown", + "realityTimeout": "86400", + "realityOpeningTime": "1681263978", + "realityCreationTime": "1681263995", + "realityNonce": "3" + } + ] + }, + "externalDisputeID": { + "type": "string", + "default": "", + "title": "The externalDisputeID Schema", + "examples": [ + "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39" + ] + }, + "arbitrableDisputeID": { + "type": "string", + "default": "", + "title": "The arbitrableDisputeID Schema", + "examples": [ + "245" + ] + }, + "arbitratorDisputeID": { + "type": "string", + "default": "", + "title": "The arbitratorDisputeID Schema", + "examples": [ + "4563" + ] + }, + "disputeTemplateID": { + "type": "string", + "default": "", + "title": "The disputeTemplateID Schema", + "examples": [ + "42" + ] + }, + "disputeTemplateHash": { + "type": "string", + "default": "", + "title": "The disputeTemplateHash Schema", + "examples": [ + "0xffbbbd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b82" + ] + } + } +} diff --git a/kleros-sdk/config/v2-disputetemplate/reality/NewDisputeTemplate.reality.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/NewDisputeTemplate.reality.jsonc new file mode 100644 index 000000000..ac9495234 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/NewDisputeTemplate.reality.jsonc @@ -0,0 +1,23 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "%s", + "type": "%s", + "answers": [ + { + "id": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "title": "Answered Too Soon", + "reserved": true + } + %s // for custom answers + ], + "policyURI": "/ipfs/QmW4zDA8X95cyfAsW9Nq1t7XNTyP3sMQAWNRFoQhMpgAv7/Kleros%2520Moderate%2520x%2520Reality.eth%2520Oracle%2520-%2520Telegram%2520Content%2520Moderation%2520Question%2520Resolution%2520Policy.pdf", + "frontendUrl": "https://reality.eth.link/app/#!/question/%s-%s", + "arbitrableChainID": "100", + "arbitrableAddress": "0x2e39b8f43d0870ba896f516f78f57cde773cf805", // Realitio_v2_1_ArbitratorWithAppeals + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Oracle", + "specification": "KIP99" +} diff --git a/kleros-sdk/config/v2-disputetemplate/reality/README.md b/kleros-sdk/config/v2-disputetemplate/reality/README.md new file mode 100644 index 000000000..b06de559c --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/README.md @@ -0,0 +1,18 @@ +# Dispute Standard for Reality.eth + +[Specs](./kip-99.md) +[New dispute template](./NewDisputeTemplate.reality.jsonc) +[Dispute details schema](./DisputeDetails.reality.schema.json) (optional) +SDK implementation (TODO) + +## Example 1: Kleros Moderate Question + +[New dispute parameters](./example1/NewDispute.reality1.jsonc) +[Inputs for the dispute template](./example1/DisputeTemplateInputs.reality1.txt) +[Dispute details output](./example1/DisputeDetails.reality1.jsonc) + +## Example 2: Formula1 Question + +[New dispute parameters](./example2/NewDispute.reality2.jsonc) +[Inputs for the dispute template](./example2/DisputeTemplateInputs.reality2.txt) +[Dispute details output](./example2/DisputeDetails.reality2.jsonc) diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeDetails.reality1.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeDetails.reality1.jsonc new file mode 100644 index 000000000..a70e1e928 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeDetails.reality1.jsonc @@ -0,0 +1,56 @@ +{ + "$schema": "./DisputeDetails.reality.schema.json", + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "# [Kleros Moderate](https://kleros.io/moderate)\n---\nDid the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)?", + "answers": [ + { + "id": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "title": "Answered Too Soon", + "reserved": true + }, + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Yes", + "reserved": false + }, + { + "id": "0x02", + "title": "No", + "reserved": false + } + ], + "policyURI": "/ipfs/QmW4zDA8X95cyfAsW9Nq1t7XNTyP3sMQAWNRFoQhMpgAv7/Kleros%2520Moderate%2520x%2520Reality.eth%2520Oracle%2520-%2520Telegram%2520Content%2520Moderation%2520Question%2520Resolution%2520Policy.pdf", + "frontendUrl": "https://reality.eth.link/app/#!/question/0xe78996a233895be74a66f451f1019ca9734205cc-0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", + "arbitrableChainID": "100", + "arbitrableAddress": "0x2e39b8f43d0870ba896f516f78f57cde773cf805", // Realitio_v2_1_ArbitratorWithAppeals + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Oracle", + "lang": "en_US", + "specification": "KIP99", + "metadata": { + "realityAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", + "realityTemplateID": "76", + "realityQuestionID": "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", + "realityUser": "0xe0441ecf50205d3548456b29fde2a3010f9a61f3", + "realityType": "bool", + "realityCategory": "content moderation", + "realityLang": "en_US", + "realityFormat": "text/markdown", + "realityTimeout": "86400", + "realityOpeningTime": "1681263978", + "realityCreationTime": "1681263995", + "realityNonce": "3" + }, + "externalDisputeID": "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", + "arbitrableDisputeID": "245", + "arbitratorDisputeID": "4563", + "disputeTemplateID": "42", + "disputeTemplateHash": "0xB5u9...2240" +} diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeTemplateInputs.reality1.txt b/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeTemplateInputs.reality1.txt new file mode 100644 index 000000000..eda71b8f2 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example1/DisputeTemplateInputs.reality1.txt @@ -0,0 +1,5 @@ +# [Kleros Moderate](https://kleros.io/moderate)\n---\nDid the user, **degenape6** (ID: 1554345080), break the Telegram group, ***[Kleros Trading Group]()*** (ID: -1001151472172), ***[rules](https://ipfs.kleros.io/ipfs/Qme3Qbj9rKUNHUe9vj9rqCLnTVUCWKy2YfveQF8HiuWQSu/Kleros%20Moderate%20Community%20Rules.pdf)*** due to conduct related to the ***[message](https://t.me/c/1151472172/116662)*** (***[backup](https://ipfs.kleros.io/ipfs/QmVbFrZR1bcyQzZjvLyXwL9ekDxrqHERykdreRxXrw4nqg/animations_file_23.mp4)***)? +single-select +,{"id":"0x00","title":"Invalid/Refuse to Arbitrate","reserved":true},{"id":"0x01","title":"Yes","reserved":false},{"id":"0x02","title":"No","reserved":false} +0xe78996a233895be74a66f451f1019ca9734205cc +0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39 \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example1/NewDispute.reality1.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/example1/NewDispute.reality1.jsonc new file mode 100644 index 000000000..95fb762f2 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example1/NewDispute.reality1.jsonc @@ -0,0 +1,5 @@ +{ + "externalDisputeID": "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", // questionID + "arbitrableDisputeID": "245", + "templateID": "42" +} diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeDetails.reality2.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeDetails.reality2.jsonc new file mode 100644 index 000000000..669c28d1e --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeDetails.reality2.jsonc @@ -0,0 +1,59 @@ +{ + "$schema": "./DisputeDetails.reality.schema.json", + "title": "A reality.eth question", + "description": "A reality.eth question has been raised to arbitration.", + "question": "Who will win the FORMULA 1 AWS GRAN PREMIO DE ESPAÑA 2023 ?", + "type": "single-select", + "answers": [ + { + "id": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "title": "Answered Too Soon", + "reserved": true + }, + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Max VERSTAPPEN", + "reserved": false + }, + { + "id": "0x02", + "title": "Sergio PEREZ", + "reserved": false + }, + { + "id": "0x03", + "title": "Fernando ALONSO", + "reserved": false + } + ], + "policyURI": "/ipfs/QmW4zDA8X95cyfAsW9Nq1t7XNTyP3sMQAWNRFoQhMpgAv7/Kleros%2520Moderate%2520x%2520Reality.eth%2520Oracle%2520-%2520Telegram%2520Content%2520Moderation%2520Question%2520Resolution%2520Policy.pdf", + "frontendUrl": "https://reality.eth.link/app/#!/question/", // SDK should not change it + "arbitrableChainID": "100", + "arbitrableAddress": "0x2e39b8f43d0870ba896f516f78f57cde773cf805", // Realitio_v2_1_ArbitratorWithAppeals + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Oracle", + "lang": "en_US", + "specification": "KIP99", + "metadata": { + "realityAddress": "0xe78996a233895be74a66f451f1019ca9734205cc", + "realityTemplateID": "2", + "realityQuestionID": "0xc2a52d38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b42", + "realityUser": "0xe0441ecf50205d3548456b29fde2a3010f9a61f3", + "realityCategory": "sport", + "realityLang": "en_US", + "realityTimeout": "86400", + "realityOpeningTime": "1681263978", + "realityCreationTime": "1681263995" + }, + "externalDisputeID": "0xe2a3bd38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b39", + "arbitrableDisputeID": "246", + "arbitratorDisputeID": "4564", + "disputeTemplateID": "2", + "disputeTemplateHash": "0xC5u9...2283" +} diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeTemplateInputs.reality2.txt b/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeTemplateInputs.reality2.txt new file mode 100644 index 000000000..330b28da3 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example2/DisputeTemplateInputs.reality2.txt @@ -0,0 +1,5 @@ +Who will win the FORMULA 1 AWS GRAN PREMIO DE ESPAÑA 2023 ? +single-select +,{"id":"0x00","title":"Invalid/Refuse to Arbitrate","reserved":true},{"id":"0x01","title":"Max VERSTAPPEN","reserved":false},{"id":"0x02","title":"Sergio PEREZ","reserved":false},{"id":"0x03","title":"Fernando ALONSO","reserved":false} +0xe78996a233895be74a66f451f1019ca9734205cc +0xc2a52d38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b42 \ No newline at end of file diff --git a/kleros-sdk/config/v2-disputetemplate/reality/example2/NewDispute.reality2.jsonc b/kleros-sdk/config/v2-disputetemplate/reality/example2/NewDispute.reality2.jsonc new file mode 100644 index 000000000..21c23d34e --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/example2/NewDispute.reality2.jsonc @@ -0,0 +1,5 @@ +{ + "externalDisputeID": "0xc2a52d38e3ad4e22336ac35b221bbbdd808d716209f84014c7bc3bf62f8e3b42", // questionID + "arbitrableDisputeID": "246", + "templateID": "2" +} diff --git a/kleros-sdk/config/v2-disputetemplate/reality/kip-99.md b/kleros-sdk/config/v2-disputetemplate/reality/kip-99.md new file mode 100644 index 000000000..be6903267 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/reality/kip-99.md @@ -0,0 +1,121 @@ +--- +kip: KIP-99 +title: Reality.eth v2.1 as an arbitrable +author: Jaybuidl (@jaybuidl) +discussions-to: https://forum.kleros.io/c/proposal/<#> +status: Draft +type: Arbitrable +created: 2023-04-08 +--- + +## Summary + +This proposal intends to provide an explicit specification describing how the Kleros protocol handles arbitration requests originating from the Reality.eth v2.1 protocol. + +## Motivation + +The Reality protocol is the most complex integration of the Kleros protocol so far. Prior to this proposal, there has been a lack of a comprehensive specification. + +Contributing to the complexity of this integration are: the dynamic nature of the questions and possible answers, an extra reserved answer ("answered too soon"), and a different encoding of the "invalid/refused to arbitrate" answer. + +## Technical Specification + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174. + +### Supported functionalities + +#### Question types + +| Reality | Kleros | +| --------------- | -------------------------- | +| bool | ✅ maps to `single-select` | +| uint | TBC | +| single-select | ✅ | +| multiple-select | TBC | +| datetime | TBC | + +### Dispute details document + +#### New reserved answer + +The answers must include: + +```json +{ + "id": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "title": "Answered Too Soon", + "reserved": true +} +``` + +#### External dispute identifier + +``` +externalDisputeID = realityQuestionID +``` + +#### Metadata + +##### Population of the Reality template + +1. Retrieve the Reality contract address: it is the address calling into `arbitrable.requestArbitration()` +1. Querying the event `LogNewQuestion` for the requested `realityQuestionID` on the Reality contract. +1. Retrieve the reality template by querying the event `LogNewTemplate` for `template_id` on the Reality contract. +1. Execute the template: + +```typescript +rc_question = require("@reality.eth/reality-eth-lib/formatters/question.js"); +rc_question.populatedJSONForTemplate(LogNewTemplate.question_text, LogNewQuestion.question); +``` + +##### Metadata object + +```typescript +{ + realityAddress = callerOf(arbitrable.requestArbitration()); + realityTemplateID = LogNewQuestion.template_id; + realityQuestionID = LogNewQuestion.question_id; + realityUser = LogNewQuestion.user; + realityType = populatedJSONForTemplate.type; + realityCategory = populatedJSONForTemplate.category; + realityLang = populatedJSONForTemplate.lang; + realityFormat = populatedJSONForTemplate.format; + realityTimeout = LogNewQuestion.timeout; + realityOpeningTime = LogNewQuestion.opening_ts; + realityCreationTime = LogNewQuestion.created; + realityNonce = LogNewQuestion.nonce; + realityFrontendUrl = frontendUrl + metadata.realityAddress + "-" + metadata.realityQuestionID; +} +``` + +### Arbitrable contract requirements + +#### Answer encoding + +```typescript +realityRuling = bytes32(klerosRuling - 1); +``` + +#### Interaction sequence + +[TODO](https://github.com/RealityETH/reality-eth-monorepo/blob/5565f55d19f627179f04d79a577ed6906ba78462/packages/docs/arbitrators.rst#creating-and-using-an-arbitration-contract) + +#### Views + +[TODO](https://github.com/RealityETH/reality-eth-monorepo/blob/5565f55d19f627179f04d79a577ed6906ba78462/packages/docs/arbitrators.rst#getting-information-about-the-arbitrator): `realitio()` pointing to Reality, metadata indicating template restrictions, terms of services, cross-chain arbitration. + +## Rationale + +TODO: the rationale should flesh out the specification by describing what motivated the design and why particular design decisions were made, as well as any alternative designs that were considered. + +## Implementation + +TODO: an implementation must be completed before any KIP proceeds to “Last Call” status. + +## Backwards Compatibility + +TODO + +## Security considerations + +All KIPs must include a discussion of the security implications/considerations relevant to the proposed change as well as proposed mitigations. A KIP cannot proceed to “Final” status without a sufficient security review from the core team. diff --git a/kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json b/kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json new file mode 100644 index 000000000..50b3760dc --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json @@ -0,0 +1,23 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "Let's do this", + "description": "We want to do this: %s", + "question": "Does it comply with the policy?", + "answers": [ + { + "title": "Yes", + "description": "Select this if you agree that it must be done." + }, + { + "title": "No", + "description": "Select this if you do not agree that it must be done." + } + ], + "policyURI": "/ipfs/Qmdvk...rSD6cE/policy.pdf", + "frontendUrl": "https://kleros-v2.netlify.app/#/cases/%s/overview", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", + "category": "Others", + "specification": "KIP001", + "lang": "en_US" +} diff --git a/kleros-sdk/config/v2-disputetemplate/simple/example/DisputeDetails.simple.jsonc b/kleros-sdk/config/v2-disputetemplate/simple/example/DisputeDetails.simple.jsonc new file mode 100644 index 000000000..8429d6255 --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/simple/example/DisputeDetails.simple.jsonc @@ -0,0 +1,44 @@ +{ + "title": "Let's do this", + "description": "We want to do this: airdrop magic money", + "question": "Does it comply with the policy?", + "type": "single-select", + "answers": [ + { + "id": "0x00", + "title": "Invalid/Refuse to Arbitrate", + "reserved": true + }, + { + "id": "0x01", + "title": "Yes", + "description": "Select this if you agree that it must be done.", + "reserved": false + }, + { + "id": "0x02", + "title": "No", + "description": "Select this if you do not agree that it must be done.", + "reserved": false + } + ], + "policyURI": "/ipfs/Qmdvk...rSD6cE/policy.pdf", + "frontendUrl": "https://kleros-v2.netlify.app/#/cases/%s/overview", + "arbitrableChainID": "10200", // Chiado + "arbitrableAddress": "0x22f40371b1d1bd7e6229e33b832cbe00d0b991b2", + "arbitratorChainID": "421613", // ArbitrumGoerli + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", // KlerosCore + "category": "Others", + "specification": "KIP001", + "lang": "en_US", + "metadata": { + "aliases": { + "submitter": "0x5B0EdFcD1038746Cc1C1eE3aCdb31feD910B13f4" + } + }, + "externalDisputeID": "13", // hash(action) + "arbitrableDisputeID": "3", + "arbitratorDisputeID": "4564", + "disputeTemplateID": "1", + "disputeTemplateHash": "0xD1u9...2254" +} diff --git a/kleros-sdk/config/v2-disputetemplate/simple/example/DisputeTemplateInputs.curate.txt b/kleros-sdk/config/v2-disputetemplate/simple/example/DisputeTemplateInputs.curate.txt new file mode 100644 index 000000000..7f62d34be --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/simple/example/DisputeTemplateInputs.curate.txt @@ -0,0 +1,2 @@ +airdrop magic money +3 diff --git a/kleros-sdk/config/v2-disputetemplate/simple/example/NewDispute.simple.jsonc b/kleros-sdk/config/v2-disputetemplate/simple/example/NewDispute.simple.jsonc new file mode 100644 index 000000000..97c28de7e --- /dev/null +++ b/kleros-sdk/config/v2-disputetemplate/simple/example/NewDispute.simple.jsonc @@ -0,0 +1,8 @@ +{ + "externalDisputeID": "ea6ed15a0867e22f40371b1d1bd7e6229e33b832cbe00d0b991b2da19d4f951a", + "arbitrableDisputeID": "3", + "templateID": "1" +} + +// action = "airdrop magic money" +// externalDisputeID = hash(action) = 0xea6ed15a0867e22f40371b1d1bd7e6229e33b832cbe00d0b991b2da19d4f951a \ No newline at end of file diff --git a/package.json b/package.json index ac0761513..e17977efb 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "contracts", "dynamic-script", "evidence-display", - "kleros-ts", + "kleros-sdk", "subgraph", "web", "eslint-config",