Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"solidity.compileUsingRemoteVersion": "v0.8.10+commit.fc410830",
"mochaExplorer.files": "contracts/test/**/*.{j,t}s",
"cSpell.words": [
"arbitrum"
"arbitrum",
"kleros"
]
}
7 changes: 5 additions & 2 deletions contracts/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1
REPORT_GAS=true
INFURA_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1
ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1

# There seems to be a bug with hardhat-deploy's implementation of etherscan-verify
# If ETHERSCAN_API_KEY is set, it overrides any hardhat configuration.
ETHERSCAN_API_KEY_FIX=ABC123ABC123ABC123ABC123ABC123ABC1
ARBISCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1
REPORT_GAS=true
12 changes: 8 additions & 4 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Smart contracts for Kleros v2

## Deployed Addresses

Refresh the list of deployed contracts by running `scripts/generateDeploymentsMarkdown.sh`.
Refresh the list of deployed contracts by running `./scripts/generateDeploymentsMarkdown.sh`.

### Rinkeby

Expand All @@ -13,9 +13,13 @@ Refresh the list of deployed contracts by running `scripts/generateDeploymentsMa

### Arbitrum Rinkeby

- [FastBridgeSender](https://testnet.arbiscan.io/address/0x395014fddc3b12F9a78ED8E57DA162Fd77E12bE3)
- [HomeGateway](https://testnet.arbiscan.io/address/0x300CbF0829762FeDc90287D08aeDf261EE6ED8eB)
- [SafeBridgeArbitrum](https://testnet.arbiscan.io/address/0x014A442480DbAD767b7615E55E271799889FA1a7)
- [ConstantNG](https://testnet.arbiscan.io/address/0x4401A368dea8D5761AEEFfd3c4a674086dea0666)
- [DisputeKitClassic](https://testnet.arbiscan.io/address/0xD78DCddE2C5a2Bd4BB246Bc7dB6994b95f7c442C)
- [FastBridgeSender](https://testnet.arbiscan.io/address/0x34E520dc1d2Db660113b64724e14CEdCD01Ee879)
- [HomeGateway](https://testnet.arbiscan.io/address/0x40a78989317B953e427B3BD87C59eA003fcC2296)
- [KlerosCore](https://testnet.arbiscan.io/address/0xf2a59723c5d625D646668E0B615B5764c3F81540)
- [SafeBridgeArbitrum](https://testnet.arbiscan.io/address/0x68eE49dfD9d76f3386257a3D0e0A85c0A5519bBD)
- [SortitionSumTreeFactory](https://testnet.arbiscan.io/address/0xf02733d9e5CbfE67B54F165b0277E1995106D526)

## Contributing

Expand Down
49 changes: 49 additions & 0 deletions contracts/deploy/00-home-chain-arbitration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

const HOME_CHAIN_IDS = [42161, 421611, 31337]; // ArbOne, ArbRinkeby, Hardhat

const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { deployments, getNamedAccounts } = hre;
const { deploy, execute } = deployments;
const { AddressZero } = hre.ethers.constants;

// fallback to hardhat node signers on local network
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
console.log("deployer: %s", deployer);

const rng = await deploy("ConstantNG", {
from: deployer,
args: [42],
log: true,
});

const disputeKit = await deploy("DisputeKitClassic", {
from: deployer,
args: [deployer, AddressZero, rng.address],
log: true,
});

const sortitionSumTreeLibrary = await deploy("SortitionSumTreeFactory", {
from: deployer,
log: true,
});

// TODO: deploy a PNK token if there isn't one already

const klerosCore = await deploy("KlerosCore", {
from: deployer,
libraries: {
SortitionSumTreeFactory: sortitionSumTreeLibrary.address,
},
args: [deployer, AddressZero, AddressZero, disputeKit.address, false, 200, 10000, 100, 3, [0, 0, 0, 0], 3],
log: true,
});

await execute("DisputeKitClassic", { from: deployer, log: true }, "changeCore", klerosCore.address);
};

deployArbitration.tags = ["HomeChain", "Arbitration"];
deployArbitration.skip = async ({ getChainId }) => !HOME_CHAIN_IDS.includes(Number(await getChainId()));

export default deployArbitration;
2 changes: 1 addition & 1 deletion contracts/deploy/01-foreign-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { DeployFunction } from "hardhat-deploy/types";

import getContractAddress from "../deploy-helpers/getContractAddress";

const FOREIGN_CHAIN_IDS = [1, 4];
const FOREIGN_CHAIN_IDS = [1, 4, 31337]; // Mainnet, Rinkeby, Hardhat
const paramsByChainId = {
1: {
claimDeposit: parseEther("0.1"),
Expand Down
41 changes: 11 additions & 30 deletions contracts/deploy/02-home-chain.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,41 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";

import getContractAddress from "../deploy-helpers/getContractAddress";

const HOME_CHAIN_IDS = [42161, 421611];
const paramsByChainId = {
4: {
arbitrator: "0xab96e690f784b305942752a1fda42680e80f37a0", // SimplePermissionlessArbitrator
foreignChainId: 77,
},
42161: {
arbitrator: "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", // SimplePermissionlessArbitrator
foreignChainId: 1,
},
421611: {
arbitrator: "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", // SimplePermissionlessArbitrator
foreignChainId: 4,
},
};
const HOME_CHAIN_IDS = [42161, 421611, 31337]; // ArbOne, ArbRinkeby, Hardhat

const deployHomeGateway: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { deployments, getNamedAccounts, getChainId } = hre;
const { deployments, getNamedAccounts } = hre;
const { deploy, execute } = deployments;
const { hexZeroPad } = hre.ethers.utils;

const { deployer } = await getNamedAccounts();
const chainId = await getChainId();

const { arbitrator, foreignChainId } = paramsByChainId[chainId];

const foreignGateway = await hre.companionNetworks.foreign.deployments.get("ForeignGateway");
const fastBridgeReceiver = await hre.companionNetworks.foreign.deployments.get("FastBridgeReceiver");

const foreignChainIdAsBytes32 = hexZeroPad(foreignChainId, 32);
// fallback to hardhat node signers on local network
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
console.log("deployer: %s", deployer);

const safeBridge = await deploy("SafeBridgeArbitrum", {
from: deployer,
log: true,
});

const fastBridgeReceiver = await hre.companionNetworks.foreign.deployments.get("FastBridgeReceiver");
const fastBridgeSender = await deploy("FastBridgeSender", {
from: deployer,
args: [safeBridge.address, fastBridgeReceiver.address],
log: true,
});

const klerosCore = await deployments.get("KlerosCore");
const foreignGateway = await hre.companionNetworks.foreign.deployments.get("ForeignGateway");
const foreignChainId = Number(await hre.companionNetworks.foreign.getChainId());
const homeGateway = await deploy("HomeGateway", {
from: deployer,
args: [arbitrator, fastBridgeSender.address, foreignGateway.address, foreignChainIdAsBytes32],
args: [klerosCore.address, fastBridgeSender.address, foreignGateway.address, foreignChainId],
log: true,
});

await execute("FastBridgeSender", { from: deployer, log: true }, "setFastSender", homeGateway.address);
};

deployHomeGateway.tags = ["HomeChain"];
deployHomeGateway.tags = ["HomeChain", "HomeGateway"];
deployHomeGateway.skip = async ({ getChainId }) => !HOME_CHAIN_IDS.includes(Number(await getChainId()));

export default deployHomeGateway;
168 changes: 168 additions & 0 deletions contracts/deployments/arbitrumRinkeby/ConstantNG.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
{
"address": "0x4401A368dea8D5761AEEFfd3c4a674086dea0666",
"abi": [
{
"inputs": [
{
"internalType": "uint256",
"name": "_number",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_block",
"type": "uint256"
}
],
"name": "contribute",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_block",
"type": "uint256"
}
],
"name": "getRN",
"outputs": [
{
"internalType": "uint256",
"name": "RN",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_block",
"type": "uint256"
}
],
"name": "getUncorrelatedRN",
"outputs": [
{
"internalType": "uint256",
"name": "RN",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "number",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_block",
"type": "uint256"
}
],
"name": "requestRN",
"outputs": [],
"stateMutability": "payable",
"type": "function"
}
],
"transactionHash": "0xd895745c58c5c5446c2d0cf1c0361948728603c976a6778fd7a88117c360510d",
"receipt": {
"to": null,
"from": "0xF50E77f2A2B6138D16c6c7511562E5C33c4B15A3",
"contractAddress": "0x4401A368dea8D5761AEEFfd3c4a674086dea0666",
"transactionIndex": 0,
"gasUsed": "1272164",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"blockHash": "0x7a54453a6c172718f25498599fa57f0e6ecd8d7ea906c5a63994731178695146",
"transactionHash": "0xd895745c58c5c5446c2d0cf1c0361948728603c976a6778fd7a88117c360510d",
"logs": [],
"blockNumber": 9361437,
"cumulativeGasUsed": "7164",
"status": 1,
"byzantium": true
},
"args": [
42
],
"numDeployments": 1,
"solcInputHash": "9627b78546d73cee66a2022d221ca6c9",
"metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_number\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"contribute\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"getRN\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"RN\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"getUncorrelatedRN\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"RN\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_block\",\"type\":\"uint256\"}],\"name\":\"requestRN\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor.\",\"params\":{\"_number\":\"The number to always return.\"}},\"contribute(uint256)\":{\"details\":\"Contribute to the reward of a random number. All the ETH will be lost forever.\",\"params\":{\"_block\":\"Block the random number is linked to.\"}},\"getRN(uint256)\":{\"details\":\"Get the \\\"random number\\\" (which is always the same).\",\"params\":{\"_block\":\"Block the random number is linked to.\"},\"returns\":{\"RN\":\"Random Number. If the number is not ready or has not been required 0 instead.\"}},\"getUncorrelatedRN(uint256)\":{\"details\":\"Get a uncorrelated random number. Act like getRN but give a different number for each sender. This is to prevent users from getting correlated numbers.\",\"params\":{\"_block\":\"Block the random number is linked to.\"},\"returns\":{\"RN\":\"Random Number. If the number is not ready or has not been required 0 instead.\"}},\"requestRN(uint256)\":{\"details\":\"Request a random number.\",\"params\":{\"_block\":\"Block linked to the request.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/rng/ConstantNG.sol\":\"ConstantNG\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/rng/ConstantNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/**\\n * @title Constant Number Generator\\n * @author Cl\\u00e9ment Lesaege - <[email protected]>\\n * @dev A Random Number Generator which always return the same number. Usefull in order to make tests.\\n */\\n\\npragma solidity ^0.8;\\nimport \\\"./RNG.sol\\\";\\n\\ncontract ConstantNG is RNG {\\n uint256 public immutable number;\\n\\n /**\\n * @dev Constructor.\\n * @param _number The number to always return.\\n */\\n constructor(uint256 _number) {\\n number = _number;\\n }\\n\\n /**\\n * @dev Contribute to the reward of a random number. All the ETH will be lost forever.\\n * @param _block Block the random number is linked to.\\n */\\n function contribute(uint256 _block) public payable override {}\\n\\n /**\\n * @dev Get the \\\"random number\\\" (which is always the same).\\n * @param _block Block the random number is linked to.\\n * @return RN Random Number. If the number is not ready or has not been required 0 instead.\\n */\\n function getRN(uint256 _block) public view override returns (uint256 RN) {\\n return number;\\n }\\n}\\n\",\"keccak256\":\"0xa36e4dbc69128b01a005e4a9ce79a4c0f555be0963497e7cabdb76028f00e44c\",\"license\":\"MIT\"},\"src/rng/RNG.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/**\\n * @authors: [@clesaege]\\n * @reviewers: [@remedcu]\\n * @auditors: []\\n * @bounties: []\\n * @deployments: []\\n */\\n\\npragma solidity ^0.8;\\n\\n/**\\n * @title Random Number Generator Standard\\n * @author Cl\\u00e9ment Lesaege - <[email protected]>\\n * @dev This is an abstract contract\\n */\\nabstract contract RNG {\\n /**\\n * @dev Contribute to the reward of a random number.\\n * @param _block Block the random number is linked to.\\n */\\n function contribute(uint256 _block) public payable virtual;\\n\\n /**\\n * @dev Request a random number.\\n * @param _block Block linked to the request.\\n */\\n function requestRN(uint256 _block) public payable {\\n contribute(_block);\\n }\\n\\n /**\\n * @dev Get the random number.\\n * @param _block Block the random number is linked to.\\n * @return RN Random Number. If the number is not ready or has not been required 0 instead.\\n */\\n function getRN(uint256 _block) public virtual returns (uint256 RN);\\n\\n /**\\n * @dev Get a uncorrelated random number. Act like getRN but give a different number for each sender.\\n * This is to prevent users from getting correlated numbers.\\n * @param _block Block the random number is linked to.\\n * @return RN Random Number. If the number is not ready or has not been required 0 instead.\\n */\\n function getUncorrelatedRN(uint256 _block) public returns (uint256 RN) {\\n uint256 baseRN = getRN(_block);\\n if (baseRN == 0) return 0;\\n else return uint256(keccak256(abi.encode(msg.sender, baseRN)));\\n }\\n}\\n\",\"keccak256\":\"0x854bcb147fe44383cba7a5fdbcb69b3c0a9a71435c80eb73c172222da472a855\",\"license\":\"MIT\"}},\"version\":1}",
"bytecode": "0x60a060405234801561001057600080fd5b5060405161024438038061024483398101604081905261002f91610037565b608052610050565b60006020828403121561004957600080fd5b5051919050565b6080516101cd6100776000396000818160a80152818160f9015261011f01526101cd6000f3fe60806040526004361061004a5760003560e01c80631c73601e1461004f5780637b9c34e0146100815780638381f58a14610096578063c1cbbca7146100ca578063ca4742f1146100db575b600080fd5b34801561005b57600080fd5b5061006f61006a36600461017e565b61011b565b60405190815260200160405180910390f35b61009461008f36600461017e565b6100d8565b005b3480156100a257600080fd5b5061006f7f000000000000000000000000000000000000000000000000000000000000000081565b6100946100d836600461017e565b50565b3480156100e757600080fd5b5061006f6100f636600461017e565b507f000000000000000000000000000000000000000000000000000000000000000090565b60007f00000000000000000000000000000000000000000000000000000000000000008061014c5750600092915050565b6040805133602082015290810182905260600160408051601f1981840301815291905280516020909101209392505050565b60006020828403121561019057600080fd5b503591905056fea2646970667358221220693d5cc66e09ccd6a6d6637ad435b22e4b44841e2e761be701bf91040945c1fc64736f6c634300080a0033",
"deployedBytecode": "0x60806040526004361061004a5760003560e01c80631c73601e1461004f5780637b9c34e0146100815780638381f58a14610096578063c1cbbca7146100ca578063ca4742f1146100db575b600080fd5b34801561005b57600080fd5b5061006f61006a36600461017e565b61011b565b60405190815260200160405180910390f35b61009461008f36600461017e565b6100d8565b005b3480156100a257600080fd5b5061006f7f000000000000000000000000000000000000000000000000000000000000000081565b6100946100d836600461017e565b50565b3480156100e757600080fd5b5061006f6100f636600461017e565b507f000000000000000000000000000000000000000000000000000000000000000090565b60007f00000000000000000000000000000000000000000000000000000000000000008061014c5750600092915050565b6040805133602082015290810182905260600160408051601f1981840301815291905280516020909101209392505050565b60006020828403121561019057600080fd5b503591905056fea2646970667358221220693d5cc66e09ccd6a6d6637ad435b22e4b44841e2e761be701bf91040945c1fc64736f6c634300080a0033",
"devdoc": {
"kind": "dev",
"methods": {
"constructor": {
"details": "Constructor.",
"params": {
"_number": "The number to always return."
}
},
"contribute(uint256)": {
"details": "Contribute to the reward of a random number. All the ETH will be lost forever.",
"params": {
"_block": "Block the random number is linked to."
}
},
"getRN(uint256)": {
"details": "Get the \"random number\" (which is always the same).",
"params": {
"_block": "Block the random number is linked to."
},
"returns": {
"RN": "Random Number. If the number is not ready or has not been required 0 instead."
}
},
"getUncorrelatedRN(uint256)": {
"details": "Get a uncorrelated random number. Act like getRN but give a different number for each sender. This is to prevent users from getting correlated numbers.",
"params": {
"_block": "Block the random number is linked to."
},
"returns": {
"RN": "Random Number. If the number is not ready or has not been required 0 instead."
}
},
"requestRN(uint256)": {
"details": "Request a random number.",
"params": {
"_block": "Block linked to the request."
}
}
},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
},
"storageLayout": {
"storage": [],
"types": null
}
}
Loading