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
186 changes: 121 additions & 65 deletions .github/workflows/contracts-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,73 +15,129 @@ on:
pull_request:
branches:
- "*"
permissions: # added using https://github.com/step-security/secure-workflows

permissions: # added using https://github.com/step-security/secure-workflows
contents: read

jobs:
contracts-testing:
# *********************************************************************************** #
# ******************************* Hardhat Tests ************************************* #
# *********************************************************************************** #
hardhat-tests:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: false
egress-policy: block
allowed-endpoints: >
binaries.soliditylang.org:443
classic.yarnpkg.com:443
github.com:443
nightly.yarnpkg.com:443
nodejs.org:443
objects.githubusercontent.com:443
registry.yarnpkg.com:443
registry.npmjs.org:443
54.185.253.63:443

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive

- name: Set up corepack (for yarn)
run: |
corepack enable
corepack prepare yarn@4.9.2 --activate
yarn set version 4.9.2

- name: Setup Node.js environment
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 20.x
cache: yarn

- name: Cache node modules
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
env:
cache-name: cache-node-modules
with:
path: |
~/.npm
**/node_modules
key: ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-

- name: Install contracts dependencies
run: yarn workspace @kleros/kleros-v2-contracts install

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@de808b1eea699e761c404bda44ba8f21aba30b2c # v1.3.1

- name: Install lcov
run: sudo apt-get install -y lcov

- name: Run Hardhat and Foundry tests with coverage
run: yarn coverage
working-directory: contracts

- name: Upload a build artifact
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
with:
name: code-coverage-report
path: contracts/coverage
- name: Harden Runner
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: false
egress-policy: block
allowed-endpoints: >
binaries.soliditylang.org:443
classic.yarnpkg.com:443
github.com:443
nightly.yarnpkg.com:443
nodejs.org:443
objects.githubusercontent.com:443
registry.yarnpkg.com:443
registry.npmjs.org:443
54.185.253.63:443

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive

- name: Set up corepack (for yarn)
run: |
corepack enable
corepack prepare yarn@4.9.2 --activate
yarn set version 4.9.2

- name: Setup Node.js environment
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 20.x
cache: yarn

- name: Cache node modules
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
env:
cache-name: cache-node-modules
with:
path: |
~/.npm
**/node_modules
key: ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-

- name: Install contracts dependencies
run: yarn workspace @kleros/kleros-v2-contracts install

- name: Run Hardhat tests
run: yarn test
working-directory: contracts

# *********************************************************************************** #
# ******************************* Foundry Tests ************************************* #
# *********************************************************************************** #
# COMPILATION FAILS 🤬
# foundry-tests:
# runs-on: ubuntu-latest
# steps:
# - name: Harden Runner
# uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
# with:
# disable-sudo: false
# egress-policy: block
# allowed-endpoints: >
# binaries.soliditylang.org:443
# classic.yarnpkg.com:443
# github.com:443
# nightly.yarnpkg.com:443
# nodejs.org:443
# objects.githubusercontent.com:443
# registry.yarnpkg.com:443
# registry.npmjs.org:443
# 54.185.253.63:443

# - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# with:
# submodules: recursive

# - name: Set up corepack (for yarn)
# run: |
# corepack enable
# corepack prepare yarn@4.9.2 --activate
# yarn set version 4.9.2

# - name: Setup Node.js environment
# uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
# with:
# node-version: 20.x
# cache: yarn

# - name: Cache node modules
# uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
# env:
# cache-name: cache-node-modules
# with:
# path: |
# ~/.npm
# **/node_modules
# key: ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
# restore-keys: |
# ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-

# # - name: Install contracts dependencies
# # run: yarn workspace @kleros/kleros-v2-contracts install

# - name: Install Foundry
# uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0

# - name: Run Foundry tests
# run: forge test --config-path ./foundry.toml
# working-directory: contracts

# - name: Run snapshot
# run: NO_COLOR=1 forge snapshot >> $GITHUB_STEP_SUMMARY
# working-directory: contracts
13 changes: 8 additions & 5 deletions contracts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,31 @@ The format is based on [Common Changelog](https://common-changelog.org/).
- **Breaking:** Rename `governor` to `owner` in order to comply with the lightweight ownership standard [ERC-5313](https://eipsinsight.com/ercs/erc-5313) ([#2112](https://github.com/kleros/kleros-v2/issues/2112))
- **Breaking:** Apply the penalties to the stakes in the Sortition Tree ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
- **Breaking:** Make `SortitionModule.getJurorBalance().stakedInCourt` include the penalties ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
- **Breaking:** Add a new field `drawnJurorFromCourtIDs` to the `Round` struct in `KlerosCoreBase` and `KlerosCoreUniversity` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
- **Breaking:** Add a new state variable `jumpDisputeKitID` to the `DisputeKitClassicBase` contract ([#2114](https://github.com/kleros/kleros-v2/issues/2114))
- Make `IDisputeKit.draw()` and `ISortitionModule.draw()` return the court ID from which the juror was drawn ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
- Rename `SortitionModule.setJurorInactive()` to `SortitionModule.forcedUnstakeAllCourts()` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
- Allow stake changes to by-pass delayed stakes when initiated by the SortitionModule by setting the `_noDelay` parameter to `true` in `SortitionModule.validateStake()` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
- Make the primary VRF-based RNG fall back to `BlockhashRNG` if the VRF request is not fulfilled within a timeout ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- Authenticate the calls to the RNGs to prevent 3rd parties from depleting the Chainlink VRF subscription funds ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- Use `block.timestamp` rather than `block.number` for `BlockhashRNG` for better reliability on Arbitrum as block production is sporadic depending on network conditions. ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
- Replace the `bytes32 _key` parameter in `SortitionTrees.createTree()` and `SortitionTrees.draw()` by `uint96 courtID` ([#2113](https://github.com/kleros/kleros-v2/issues/2113))
- Extract the sortition sum trees logic into a library `SortitionTrees` ([#2113](https://github.com/kleros/kleros-v2/issues/2113))
- Make `IDisputeKit.getDegreeOfCoherenceReward()` multi-dimensional so different calculations may be applied to PNK rewards, fee rewards and PNK penalties (future-proofing) ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
- Consolidate the constant `ALPHA_DIVISOR` with `ONE_BASIS_POINTS` ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
- Set the Hardhat Solidity version to v0.8.30 and enable the IR pipeline ([#2069](https://github.com/kleros/kleros-v2/issues/2069))
- Set the Foundry Solidity version to v0.8.30 and enable the IR pipeline ([#2073](https://github.com/kleros/kleros-v2/issues/2073))
- Widen the allowed solc version to any v0.8.x for the interfaces only ([#2083](https://github.com/kleros/kleros-v2/issues/2083))
- Make `IDisputeKit.getDegreeOfCoherenceReward()` multi-dimensional so different calculations may be applied to PNK rewards, fee rewards and PNK penalties (future-proofing) ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
- Consolidate the constant `ALPHA_DIVISOR` with `ONE_BASIS_POINTS` ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
- Bump `hardhat` to v2.26.2 ([#2069](https://github.com/kleros/kleros-v2/issues/2069))
- Bump `@kleros/vea-contracts` to v0.7.0 ([#2073](https://github.com/kleros/kleros-v2/issues/2073))

### Added

- **Breaking:** Add a new field `drawnJurorFromCourtIDs` to the `Round` struct in `KlerosCoreBase` and `KlerosCoreUniversity` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
- **Breaking:** Add a new state variable `jumpDisputeKitID` to the `DisputeKitClassicBase` contract ([#2114](https://github.com/kleros/kleros-v2/issues/2114))
- **Breaking:** Add a parameter `_recoveryCommit` to the event `DisputeKitShutter.CommitCastShutter` ([#2100](https://github.com/kleros/kleros-v2/issues/2100))
- **Breaking:** Add a storage variable `recoveryCommitments` to `DisputeKitShutter` ([#2100](https://github.com/kleros/kleros-v2/issues/2100))
- Allow the Shutter commitment to be recovered by the juror using only the salt and the choice, without having to provide the justification ([#2100](https://github.com/kleros/kleros-v2/issues/2100))
- Allow the dispute kits to force an early court jump and to override the number of votes after an appeal (future-proofing) ([#2110](https://github.com/kleros/kleros-v2/issues/2110))
- Allow the dispute kits to specify which new dispute kit to use when a court jump occurs ([#2114](https://github.com/kleros/kleros-v2/issues/2114))
- Allow stake changes to by-pass delayed stakes when initiated by the SortitionModule by setting the `_noDelay` parameter to `true` in `SortitionModule.validateStake()` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))

### Fixed

Expand Down
11 changes: 3 additions & 8 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@

[profile.default]
solc = "0.8.30"
evm_version = "cancun"
via_ir = true
optimizer = true
optimizer_runs = 500
optimizer_details = { yulDetails = { stackAllocation = true } }
additional_compiler_profiles = [
{ name = "tests", via_ir = false }
]
compilation_restrictions = [
{ paths = "test/foundry/KlerosCore.t.sol", via_ir = false },
]
optimizer_runs = 10000

src = 'src'
out = 'out'
libs = ['../node_modules', 'lib']
Expand Down
1 change: 1 addition & 0 deletions contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const config: HardhatUserConfig = {
{
version: "0.8.30",
settings: {
evmVersion: "cancun",
viaIR: process.env.VIA_IR !== "false", // Defaults to true
optimizer: {
enabled: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,19 +318,21 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
if (_voteIDs.length == 0) revert EmptyVoteIDs();
if (!coreDisputeIDToActive[_coreDisputeID]) revert NotActiveForCoreDisputeID();

Dispute storage dispute = disputes[coreDisputeIDToLocal[_coreDisputeID]];
uint256 localDisputeID = coreDisputeIDToLocal[_coreDisputeID];
Dispute storage dispute = disputes[localDisputeID];
if (_choice > dispute.numberOfChoices) revert ChoiceOutOfBounds();

Round storage round = dispute.rounds[dispute.rounds.length - 1];
uint256 localRoundID = dispute.rounds.length - 1;
Round storage round = dispute.rounds[localRoundID];
{
(uint96 courtID, , , , ) = core.disputes(_coreDisputeID);
(, bool hiddenVotes, , , , , ) = core.courts(courtID);
bytes32 voteHash = hashVote(_choice, _salt, _justification);
bytes32 actualVoteHash = hashVote(_choice, _salt, _justification);

// Save the votes.
for (uint256 i = 0; i < _voteIDs.length; i++) {
if (round.votes[_voteIDs[i]].account != _juror) revert JurorHasToOwnTheVote();
if (hiddenVotes && round.votes[_voteIDs[i]].commit != voteHash)
if (hiddenVotes && _getExpectedVoteHash(localDisputeID, localRoundID, _voteIDs[i]) != actualVoteHash)
revert HashDoesNotMatchHiddenVoteCommitment();
if (round.votes[_voteIDs[i]].voted) revert VoteAlreadyCast();
round.votes[_voteIDs[i]].choice = _choice;
Expand Down Expand Up @@ -484,15 +486,14 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
* @dev Computes the hash of a vote using ABI encoding
* @dev The unused parameters may be used by overriding contracts.
* @param _choice The choice being voted for
* @param _justification The justification for the vote
* @param _salt A random salt for commitment
* @return bytes32 The hash of the encoded vote parameters
*/
function hashVote(
uint256 _choice,
uint256 _salt,
string memory _justification
) public pure virtual returns (bytes32) {
string memory /*_justification*/
) public view virtual returns (bytes32) {
return keccak256(abi.encodePacked(_choice, _salt));
}

Expand Down Expand Up @@ -738,17 +739,29 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
// * Internal * //
// ************************************* //

/// @dev Returns the expected vote hash for a given vote.
/// @param _localDisputeID The ID of the dispute in the Dispute Kit.
/// @param _localRoundID The ID of the round in the Dispute Kit.
/// @param _voteID The ID of the vote.
/// @return The expected vote hash.
function _getExpectedVoteHash(
uint256 _localDisputeID,
uint256 _localRoundID,
uint256 _voteID
) internal view virtual returns (bytes32) {
return disputes[_localDisputeID].rounds[_localRoundID].votes[_voteID].commit;
}

/// @dev Checks that the chosen address satisfies certain conditions for being drawn.
/// Note that we don't check the minStake requirement here because of the implicit staking in parent courts.
/// minStake is checked directly during staking process however it's possible for the juror to get drawn
/// while having < minStake if it is later increased by governance.
/// This issue is expected and harmless.
/// @param _round The round in which the juror is being drawn.
/// @param _coreDisputeID ID of the dispute in the core contract.
/// @param _juror Chosen address.
/// @return result Whether the address passes the check or not.
function _postDrawCheck(
Round storage _round,
Round storage /*_round*/,
uint256 _coreDisputeID,
address _juror
) internal view virtual returns (bool result) {
Expand Down
Loading
Loading