diff --git a/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol b/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol index 5c2485a8c..d0e7ddb95 100644 --- a/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol +++ b/contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol @@ -229,6 +229,10 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi bytes32 key = bytes32(uint256(courtID)); // Get the ID of the tree. drawnAddress = sortitionModule.draw(key, _coreDisputeID, _nonce); + if (drawnAddress == address(0)) { + // Sortition can return 0 address if no one has staked yet. + return drawnAddress; + } if (_postDrawCheck(round, _coreDisputeID, drawnAddress)) { round.votes.push(Vote({account: drawnAddress, commit: bytes32(0), choice: 0, voted: false})); diff --git a/contracts/test/foundry/KlerosCore.t.sol b/contracts/test/foundry/KlerosCore.t.sol index e1f452da4..e91da1dad 100644 --- a/contracts/test/foundry/KlerosCore.t.sol +++ b/contracts/test/foundry/KlerosCore.t.sol @@ -1447,6 +1447,26 @@ contract KlerosCoreTest is Test { } } + function test_draw_noEmptyAddresses() public { + uint256 disputeID = 0; + uint256 roundID = 0; + + vm.prank(disputer); + arbitrable.createDispute{value: feeForJuror * DEFAULT_NB_OF_JURORS}("Action"); + vm.warp(block.timestamp + minStakingTime); + sortitionModule.passPhase(); // Generating + vm.roll(block.number + rngLookahead + 1); + sortitionModule.passPhase(); // Drawing phase + + core.draw(disputeID, DEFAULT_NB_OF_JURORS); // No one is staked so check that the empty addresses are not drawn. + + KlerosCoreBase.Round memory round = core.getRoundInfo(disputeID, roundID); + assertEq(round.drawIterations, 3, "Wrong drawIterations number"); + + (, , , , uint256 nbVoters, ) = disputeKit.getRoundInfo(disputeID, roundID, 0); + assertEq(nbVoters, 0, "nbVoters should be 0"); + } + function test_draw_parentCourts() public { uint96 newCourtID = 2; uint256 disputeID = 0;