Skip to content

Commit 5c43453

Browse files
Merge branch 'dev' into feat/restriction-roles
2 parents b454a3c + f9cb5a6 commit 5c43453

File tree

134 files changed

+12652
-959
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

134 files changed

+12652
-959
lines changed

.github/workflows/contracts-testing.yml

+18-22
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,16 @@ jobs:
4040
54.185.253.63:443
4141
4242
- name: Setup Node.js environment
43-
uses: actions/setup-node@v4
43+
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
4444
with:
4545
node-version: 18.x
4646

47-
- uses: actions/checkout@v4
47+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
48+
with:
49+
submodules: recursive
4850

4951
- name: Cache node modules
50-
uses: actions/cache@v4
52+
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
5153
env:
5254
cache-name: cache-node-modules
5355
with:
@@ -57,28 +59,22 @@ jobs:
5759
key: ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
5860
restore-keys: |
5961
${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-
60-
61-
#- name: Install parent dependencies
62-
# run: |
63-
# echo "current dir: $PWD"
64-
# yarn install
65-
62+
6663
- name: Install contracts dependencies
67-
run: |
68-
yarn workspace @kleros/kleros-v2-contracts install
69-
70-
- name: Compile
71-
run: |
72-
yarn hardhat compile
73-
working-directory: contracts
74-
75-
- name: Test with coverage
76-
run: |
77-
yarn hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles './test/**/*.ts' --show-stack-traces
78-
working-directory: contracts
64+
run: yarn workspace @kleros/kleros-v2-contracts install
65+
66+
- name: Install Foundry
67+
uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0
7968

69+
- name: Install lcov
70+
run: sudo apt-get install -y lcov
71+
72+
- name: Run Hardhat and Foundry tests with coverage
73+
run: yarn coverage
74+
working-directory: contracts
75+
8076
- name: Upload a build artifact
81-
uses: actions/upload-artifact@v4
77+
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
8278
with:
8379
name: code-coverage-report
8480
path: contracts/coverage

contracts/.solcover.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const shell = require("shelljs");
55
// The environment variables are loaded in hardhat.config.ts
66

77
module.exports = {
8-
istanbulReporter: ["html"],
8+
istanbulReporter: ["lcov"],
99
onCompileComplete: async function (_config) {
1010
await run("typechain");
1111
},
@@ -14,7 +14,7 @@ module.exports = {
1414
shell.rm("-rf", "./artifacts");
1515
shell.rm("-rf", "./typechain");
1616
},
17-
skipFiles: ["mocks", "test"],
17+
skipFiles: ["test", "token", "kleros-v1", "proxy/mock", "gateway/mock", "rng/mock"],
1818
mocha: {
1919
timeout: 20000,
2020
grep: "@skip-on-coverage", // Find everything with this tag

contracts/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments
1010

1111
#### Arbitrum One
1212

13+
- [BlockHashRNG](https://arbiscan.io/address/0x39D123fc4cFD24EA5bB76195f9ecFE1f0DF35b0B)
14+
- [ChainlinkRNG](https://arbiscan.io/address/0x897d83a7d5F23555eFA15e1BE297d5503522cbA3)
1315
- [DisputeKitClassicNeo: proxy](https://arbiscan.io/address/0x70B464be85A547144C72485eBa2577E5D3A45421), [implementation](https://arbiscan.io/address/0xAF0325dbBFa812a574743Bb5A085266D31e3e03a)
1416
- [DisputeResolverNeo](https://arbiscan.io/address/0xb5526D022962A1fFf6eD32C93e8b714c901F4323)
1517
- [DisputeTemplateRegistry: proxy](https://arbiscan.io/address/0x0cFBaCA5C72e7Ca5fFABE768E135654fB3F2a5A2), [implementation](https://arbiscan.io/address/0x57EfD43DAfCeb6C58Df57932b2B299f46fef5c87)
@@ -27,6 +29,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments
2729
#### Arbitrum Sepolia
2830

2931
- [BlockHashRNG](https://sepolia.arbiscan.io/address/0x0298a3EFa6Faf90865725E2b48Cf0F66e5d52754)
32+
- [ChainlinkRNG](https://sepolia.arbiscan.io/address/0xAd5cCc93429e3A977c273cEeD106Ef16A69EAf79)
3033
- [DAI](https://sepolia.arbiscan.io/address/0xc34aeFEa232956542C5b2f2EE55fD5c378B35c03)
3134
- [DAIFaucet](https://sepolia.arbiscan.io/address/0x1Fa58B52326488D62A406E71DBaD839560e810fF)
3235
- [DisputeKitClassic: proxy](https://sepolia.arbiscan.io/address/0x0c38f115D001d3b5bBec5e8D44f78C7B61A27D94), [implementation](https://sepolia.arbiscan.io/address/0xDb0B7908C46E2Bb08459bf9b3155b9bb8F8713E1)
@@ -67,6 +70,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments
6770

6871
- [ArbitrableExample](https://sepolia.arbiscan.io/address/0x3Eae72F076c68F5c354C73abC33EAA291ef1b2Fa)
6972
- [BlockHashRNG](https://sepolia.arbiscan.io/address/0x56d6d65Fe202232714794B5D5e4ed9894466Ee01)
73+
- [ChainlinkRNG](https://sepolia.arbiscan.io/address/0x6c40D7F5d5bE3492fe9EF70e4eCb2BD773c12AF8)
7074
- [DAI](https://sepolia.arbiscan.io/address/0x593e89704D285B0c3fbF157c7CF2537456CE64b5)
7175
- [DAIFaucet](https://sepolia.arbiscan.io/address/0xB5b39A1bcD2D7097A8824B3cC18Ebd2dFb0D9B5E)
7276
- [DisputeKitClassic: proxy](https://sepolia.arbiscan.io/address/0x9426F127116C3652A262AE1eA48391AC8F44D35b), [implementation](https://sepolia.arbiscan.io/address/0x692CC78F2570181FFB99297965FeAA8352ab12E8)

contracts/deploy/00-chainlink-rng.ts

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { HardhatRuntimeEnvironment } from "hardhat/types";
2+
import { DeployFunction } from "hardhat-deploy/types";
3+
import { HomeChains, isSkipped } from "./utils";
4+
import { getContractOrDeploy } from "./utils/getContractOrDeploy";
5+
6+
const deployRng: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
7+
const { deployments, getNamedAccounts, getChainId } = hre;
8+
const { deploy } = deployments;
9+
10+
// fallback to hardhat node signers on local network
11+
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
12+
const chainId = Number(await getChainId()) as unknown as HomeChains; // Checked at runtime by skip()
13+
console.log("deploying to %s with deployer %s", HomeChains[chainId], deployer);
14+
15+
const KEY_HASHES = {
16+
// https://docs.chain.link/vrf/v2-5/supported-networks#arbitrum-mainnet
17+
[HomeChains.ARBITRUM_ONE]: {
18+
2: "0x9e9e46732b32662b9adc6f3abdf6c5e926a666d174a4d6b8e39c4cca76a38897",
19+
30: "0x8472ba59cf7134dfe321f4d61a430c4857e8b19cdd5230b09952a92671c24409",
20+
150: "0xe9f223d7d83ec85c4f78042a4845af3a1c8df7757b4997b815ce4b8d07aca68c",
21+
},
22+
// https://docs.chain.link/vrf/v2-5/supported-networks#arbitrum-sepolia-testnet
23+
[HomeChains.ARBITRUM_SEPOLIA]: {
24+
150: "0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be",
25+
},
26+
[HomeChains.HARDHAT]: {
27+
0: "0x0000000000000000000000000000000000000000000000000000000000000000",
28+
},
29+
};
30+
31+
const SUBSCRIPTION_ID = {
32+
[HomeChains.ARBITRUM_ONE]: "66240499937595191069677958665918759554657443303079118766000192000140992834352",
33+
[HomeChains.ARBITRUM_SEPOLIA]: "38502597312983100069991953687934627561654236680431968938019951490339399569548",
34+
[HomeChains.HARDHAT]: "0x0000000000000000000000000000000000000000000000000000000000000001",
35+
};
36+
37+
function getKeyHash({ gasPrice }: { gasPrice: keyof (typeof KEY_HASHES)[HomeChains.ARBITRUM_ONE] }): string {
38+
const validGasPrices = Object.keys(KEY_HASHES[HomeChains.ARBITRUM_ONE]).map(Number);
39+
if (!validGasPrices.includes(gasPrice)) {
40+
throw new Error(`Invalid gas price ${gasPrice}. Valid values are: ${validGasPrices.join(", ")}`);
41+
}
42+
if (chainId == HomeChains.HARDHAT) return KEY_HASHES[chainId][0];
43+
if (chainId == HomeChains.ARBITRUM_ONE) return KEY_HASHES[chainId][gasPrice];
44+
if (chainId == HomeChains.ARBITRUM_SEPOLIA) return KEY_HASHES[chainId][150];
45+
throw new Error(`Unknown chainId ${chainId}`);
46+
}
47+
48+
const ChainlinkVRFCoordinator = await getContractOrDeploy(hre, "ChainlinkVRFCoordinator", {
49+
from: deployer,
50+
contract: "ChainlinkVRFCoordinatorV2Mock",
51+
args: [],
52+
log: true,
53+
});
54+
55+
const keyHash = getKeyHash({ gasPrice: 30 });
56+
const subscriptionId = SUBSCRIPTION_ID[chainId];
57+
const requestConfirmations = 200; // between 1 and 200 L2 blocks
58+
const callbackGasLimit = 100000;
59+
60+
await deploy("ChainlinkRNG", {
61+
from: deployer,
62+
args: [
63+
deployer,
64+
deployer, // The consumer is configured as the SortitionModule later
65+
ChainlinkVRFCoordinator.target,
66+
keyHash,
67+
subscriptionId,
68+
requestConfirmations,
69+
callbackGasLimit,
70+
],
71+
log: true,
72+
});
73+
};
74+
75+
deployRng.tags = ["ChainlinkRNG"];
76+
deployRng.skip = async ({ network }) => {
77+
return isSkipped(network, !HomeChains[network.config.chainId ?? 0]);
78+
};
79+
80+
export default deployRng;

contracts/deploy/00-home-chain-arbitrable.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { HardhatRuntimeEnvironment } from "hardhat/types";
22
import { DeployFunction } from "hardhat-deploy/types";
3-
import disputeTemplate from "../test/fixtures/DisputeTemplate.simple.json";
43
import { HomeChains, isSkipped } from "./utils";
54
import { deployUpgradable } from "./utils/deployUpgradable";
65

contracts/deploy/00-home-chain-arbitration-neo.ts

+13-17
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { changeCurrencyRate } from "./utils/klerosCoreHelper";
66
import { HomeChains, isSkipped, isDevnet, PNK, ETH } from "./utils";
77
import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy";
88
import { deployERC20AndFaucet, deployERC721 } from "./utils/deployTokens";
9-
import { DisputeKitClassic, KlerosCoreNeo } from "../typechain-types";
9+
import { ChainlinkRNG, DisputeKitClassic, KlerosCoreNeo, RandomizerRNG } from "../typechain-types";
1010

1111
const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
1212
const { ethers, deployments, getNamedAccounts, getChainId } = hre;
@@ -29,19 +29,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
2929

3030
await deployUpgradable(deployments, "EvidenceModule", { from: deployer, args: [deployer], log: true });
3131

32-
const randomizerOracle = await getContractOrDeploy(hre, "RandomizerOracle", {
33-
from: deployer,
34-
contract: "RandomizerMock",
35-
args: [],
36-
log: true,
37-
});
38-
39-
const rng = await deployUpgradable(deployments, "RandomizerRNG", {
40-
from: deployer,
41-
args: [randomizerOracle.target, deployer],
42-
log: true,
43-
});
44-
4532
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassicNeo", {
4633
from: deployer,
4734
contract: "DisputeKitClassic",
@@ -58,6 +45,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
5845
const devnet = isDevnet(hre.network);
5946
const minStakingTime = devnet ? 180 : 1800;
6047
const maxFreezingTime = devnet ? 600 : 1800;
48+
const rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG;
6149
const maxStakePerJuror = PNK(2_000);
6250
const maxTotalStaked = PNK(2_000_000);
6351
const sortitionModule = await deployUpgradable(deployments, "SortitionModuleNeo", {
@@ -67,7 +55,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
6755
klerosCoreAddress,
6856
minStakingTime,
6957
maxFreezingTime,
70-
rng.address,
58+
rng.target,
7159
RNG_LOOKAHEAD,
7260
maxStakePerJuror,
7361
maxTotalStaked,
@@ -85,7 +73,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
8573
deployer,
8674
deployer,
8775
pnk.target,
88-
ZeroAddress,
76+
ZeroAddress, // KlerosCore is configured later
8977
disputeKit.address,
9078
false,
9179
[minStake, alpha, feeForJuror, jurorsForCourtJump],
@@ -97,14 +85,21 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
9785
log: true,
9886
}); // nonce+2 (implementation), nonce+3 (proxy)
9987

100-
// execute DisputeKitClassic.changeCore() only if necessary
88+
// disputeKit.changeCore() only if necessary
10189
const disputeKitContract = (await hre.ethers.getContract("DisputeKitClassicNeo")) as DisputeKitClassic;
10290
const currentCore = await disputeKitContract.core();
10391
if (currentCore !== klerosCore.address) {
10492
console.log(`disputeKit.changeCore(${klerosCore.address})`);
10593
await disputeKitContract.changeCore(klerosCore.address);
10694
}
10795

96+
// rng.changeSortitionModule() only if necessary
97+
const rngSortitionModule = await rng.sortitionModule();
98+
if (rngSortitionModule !== sortitionModule.address) {
99+
console.log(`rng.changeSortitionModule(${sortitionModule.address})`);
100+
await rng.changeSortitionModule(sortitionModule.address);
101+
}
102+
108103
const core = (await hre.ethers.getContract("KlerosCoreNeo")) as KlerosCoreNeo;
109104
try {
110105
await changeCurrencyRate(core, await weth.getAddress(), true, 1, 1);
@@ -130,6 +125,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
130125
};
131126

132127
deployArbitration.tags = ["ArbitrationNeo"];
128+
deployArbitration.dependencies = ["ChainlinkRNG"];
133129
deployArbitration.skip = async ({ network }) => {
134130
return isSkipped(network, !HomeChains[network.config.chainId ?? 0]);
135131
};

contracts/deploy/00-home-chain-arbitration-university.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { deployUpgradable } from "./utils/deployUpgradable";
55
import { changeCurrencyRate } from "./utils/klerosCoreHelper";
66
import { ETH, HomeChains, PNK, isSkipped } from "./utils";
77
import { deployERC20AndFaucet } from "./utils/deployTokens";
8-
import { DisputeKitClassic, KlerosCore, KlerosCoreUniversity } from "../typechain-types";
8+
import { DisputeKitClassic, KlerosCoreUniversity } from "../typechain-types";
99
import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy";
1010

1111
const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
@@ -53,7 +53,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
5353
deployer, // governor
5454
deployer, // instructor
5555
pnk.target,
56-
ZeroAddress,
56+
ZeroAddress, // KlerosCore is configured later
5757
disputeKit.address,
5858
false,
5959
[minStake, alpha, feeForJuror, jurorsForCourtJump],
@@ -63,7 +63,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
6363
log: true,
6464
}); // nonce+2 (implementation), nonce+3 (proxy)
6565

66-
// changeCore() only if necessary
66+
// disputeKit.changeCore() only if necessary
6767
const disputeKitContract = (await ethers.getContract("DisputeKitClassicUniversity")) as DisputeKitClassic;
6868
const currentCore = await disputeKitContract.core();
6969
if (currentCore !== klerosCore.address) {

contracts/deploy/00-home-chain-arbitration.ts

+13-28
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { DeployFunction } from "hardhat-deploy/types";
33
import { getContractAddress } from "./utils/getContractAddress";
44
import { deployUpgradable } from "./utils/deployUpgradable";
55
import { changeCurrencyRate } from "./utils/klerosCoreHelper";
6-
import { HomeChains, isSkipped, isDevnet, isMainnet, PNK, ETH } from "./utils";
6+
import { HomeChains, isSkipped, isDevnet, PNK, ETH } from "./utils";
77
import { getContractOrDeploy, getContractOrDeployUpgradable } from "./utils/getContractOrDeploy";
88
import { deployERC20AndFaucet } from "./utils/deployTokens";
9-
import { DisputeKitClassic, KlerosCore } from "../typechain-types";
9+
import { ChainlinkRNG, DisputeKitClassic, KlerosCore } from "../typechain-types";
1010

1111
const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
1212
const { ethers, deployments, getNamedAccounts, getChainId } = hre;
@@ -28,30 +28,6 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
2828

2929
await getContractOrDeployUpgradable(hre, "EvidenceModule", { from: deployer, args: [deployer], log: true });
3030

31-
// Randomizer.ai: https://randomizer.ai/docs#addresses
32-
const randomizerOracle = await getContractOrDeploy(hre, "RandomizerOracle", {
33-
from: deployer,
34-
contract: "RandomizerMock", // The mock is deployed only on the Hardhat network
35-
args: [],
36-
log: true,
37-
});
38-
39-
const randomizerRng = await getContractOrDeployUpgradable(hre, "RandomizerRNG", {
40-
from: deployer,
41-
args: [randomizerOracle.target, deployer],
42-
log: true,
43-
});
44-
45-
const blockhashRng = await getContractOrDeploy(hre, "BlockHashRNG", {
46-
from: deployer,
47-
args: [],
48-
log: true,
49-
});
50-
51-
// RNG fallback on Arbitrum Sepolia because the Randomizer.ai oracle contract is unverified and not officially supported.
52-
const rng = isMainnet(hre.network) ? randomizerRng : blockhashRng;
53-
console.log(isMainnet(hre.network) ? "using RandomizerRNG on mainnet" : "using BlockHashRNG on testnet/devnet");
54-
5531
const disputeKit = await deployUpgradable(deployments, "DisputeKitClassic", {
5632
from: deployer,
5733
args: [deployer, ZeroAddress],
@@ -67,6 +43,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
6743
const devnet = isDevnet(hre.network);
6844
const minStakingTime = devnet ? 180 : 1800;
6945
const maxFreezingTime = devnet ? 600 : 1800;
46+
const rng = (await ethers.getContract("ChainlinkRNG")) as ChainlinkRNG;
7047
const sortitionModule = await deployUpgradable(deployments, "SortitionModule", {
7148
from: deployer,
7249
args: [deployer, klerosCoreAddress, minStakingTime, maxFreezingTime, rng.target, RNG_LOOKAHEAD],
@@ -83,7 +60,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
8360
deployer,
8461
deployer,
8562
pnk.target,
86-
ZeroAddress,
63+
ZeroAddress, // KlerosCore is configured later
8764
disputeKit.address,
8865
false,
8966
[minStake, alpha, feeForJuror, jurorsForCourtJump],
@@ -94,14 +71,21 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
9471
log: true,
9572
}); // nonce+2 (implementation), nonce+3 (proxy)
9673

97-
// changeCore() only if necessary
74+
// disputeKit.changeCore() only if necessary
9875
const disputeKitContract = (await ethers.getContract("DisputeKitClassic")) as DisputeKitClassic;
9976
const currentCore = await disputeKitContract.core();
10077
if (currentCore !== klerosCore.address) {
10178
console.log(`disputeKit.changeCore(${klerosCore.address})`);
10279
await disputeKitContract.changeCore(klerosCore.address);
10380
}
10481

82+
// rng.changeSortitionModule() only if necessary
83+
const rngSortitionModule = await rng.sortitionModule();
84+
if (rngSortitionModule !== sortitionModule.address) {
85+
console.log(`rng.changeSortitionModule(${sortitionModule.address})`);
86+
await rng.changeSortitionModule(sortitionModule.address);
87+
}
88+
10589
const core = (await hre.ethers.getContract("KlerosCore")) as KlerosCore;
10690
try {
10791
await changeCurrencyRate(core, await pnk.getAddress(), true, 12225583, 12);
@@ -113,6 +97,7 @@ const deployArbitration: DeployFunction = async (hre: HardhatRuntimeEnvironment)
11397
};
11498

11599
deployArbitration.tags = ["Arbitration"];
100+
deployArbitration.dependencies = ["ChainlinkRNG"];
116101
deployArbitration.skip = async ({ network }) => {
117102
return isSkipped(network, !HomeChains[network.config.chainId ?? 0]);
118103
};

0 commit comments

Comments
 (0)