@@ -146,7 +146,7 @@ contract KlerosCore_AppealsTest is KlerosCore_TestBase {
146146 disputeKit.fundAppeal {value: 0.1 ether }(disputeID, 2 );
147147 }
148148
149- function test_appeal_fullFundingNoSwitch () public {
149+ function test_appeal_fullFundingNoJump () public {
150150 uint256 disputeID = 0 ;
151151
152152 vm.prank (staker1);
@@ -208,10 +208,12 @@ contract KlerosCore_AppealsTest is KlerosCore_TestBase {
208208 core.passPeriod (disputeID);
209209 }
210210
211- function test_appeal_fullFundingDKCourtSwitch () public {
211+ function test_appeal_fullFundingCourtJumpAndDKJumpToClassic () public {
212+ // Setup: dk2 supported by court2 with dk2._jumpDisputeKitID == DISPUTE_KIT_CLASSIC
213+ // Ensure that court2 jumps to GENERAL_COURT and dk2 jumps to DISPUTE_KIT_CLASSIC
212214 uint256 disputeID = 0 ;
213215 DisputeKitClassic dkLogic = new DisputeKitClassic ();
214- // Create a new DK and court to check the switch
216+ // Create a new DK and court to check the jump
215217 bytes memory initDataDk = abi.encodeWithSignature (
216218 "initialize(address,address,address,uint256) " ,
217219 owner,
@@ -250,6 +252,7 @@ contract KlerosCore_AppealsTest is KlerosCore_TestBase {
250252 supportedDK = new uint256 [](1 );
251253 supportedDK[0 ] = newDkID;
252254 core.enableDisputeKits (newCourtID, supportedDK, true );
255+ assertEq (core.isSupported (newCourtID, newDkID), true , "New DK should be supported by new court " );
253256
254257 vm.prank (staker1);
255258 core.setStake (newCourtID, 20000 );
@@ -279,7 +282,6 @@ contract KlerosCore_AppealsTest is KlerosCore_TestBase {
279282
280283 vm.prank (crowdfunder1);
281284 newDisputeKit.fundAppeal {value: 0.63 ether }(disputeID, 1 );
282- vm.prank (crowdfunder2);
283285
284286 assertEq (core.isDisputeKitJumping (disputeID), true , "Should be jumping " );
285287
@@ -293,6 +295,7 @@ contract KlerosCore_AppealsTest is KlerosCore_TestBase {
293295 emit KlerosCoreBase.AppealDecision (disputeID, arbitrable);
294296 vm.expectEmit (true , true , true , true );
295297 emit KlerosCoreBase.NewPeriod (disputeID, KlerosCoreBase.Period.evidence);
298+ vm.prank (crowdfunder2);
296299 newDisputeKit.fundAppeal {value: 0.42 ether }(disputeID, 2 );
297300
298301 (, bool jumped , ) = newDisputeKit.disputes (disputeID);
@@ -326,6 +329,144 @@ contract KlerosCore_AppealsTest is KlerosCore_TestBase {
326329 assertEq (account, staker1, "Wrong drawn account in the classic DK " );
327330 }
328331
332+ function test_appeal_fullFundingCourtJumpAndDKJumpToNonClassic () public {
333+ // Setup:
334+ // dk2 supported by GENERAL_COURT, which is a non-DISPUTE_KIT_CLASSIC
335+ // dk3 supported by court2, with dk3._jumpDisputeKitID == dk2
336+ // Ensure that court2 jumps to GENERAL_COURT and dk3 jumps to dk2
337+ uint256 disputeID = 0 ;
338+ uint96 newCourtID = 2 ;
339+ uint256 dkID2 = 2 ;
340+ uint256 dkID3 = 3 ;
341+
342+ DisputeKitClassic dkLogic = new DisputeKitClassic ();
343+
344+ bytes memory initDataDk2 = abi.encodeWithSignature (
345+ "initialize(address,address,address,uint256) " ,
346+ owner,
347+ address (core),
348+ address (wNative),
349+ DISPUTE_KIT_CLASSIC
350+ );
351+ UUPSProxy proxyDk2 = new UUPSProxy (address (dkLogic), initDataDk2);
352+ DisputeKitClassic disputeKit2 = DisputeKitClassic (address (proxyDk2));
353+
354+ bytes memory initDataDk3 = abi.encodeWithSignature (
355+ "initialize(address,address,address,uint256) " ,
356+ owner,
357+ address (core),
358+ address (wNative),
359+ dkID2
360+ );
361+ UUPSProxy proxyDk3 = new UUPSProxy (address (dkLogic), initDataDk3);
362+ DisputeKitClassic disputeKit3 = DisputeKitClassic (address (proxyDk3));
363+
364+ vm.prank (owner);
365+ core.addNewDisputeKit (disputeKit2);
366+ vm.prank (owner);
367+ core.addNewDisputeKit (disputeKit3);
368+
369+ uint256 [] memory supportedDK = new uint256 [](2 );
370+ supportedDK[0 ] = DISPUTE_KIT_CLASSIC;
371+ supportedDK[1 ] = dkID3;
372+ vm.prank (owner);
373+ core.createCourt (
374+ GENERAL_COURT,
375+ hiddenVotes,
376+ minStake,
377+ alpha,
378+ feeForJuror,
379+ 3 , // jurors for jump. Low number to ensure jump after the first appeal
380+ [uint256 (60 ), uint256 (120 ), uint256 (180 ), uint256 (240 )], // Times per period
381+ sortitionExtraData,
382+ supportedDK
383+ );
384+ assertEq (core.isSupported (newCourtID, dkID3), true , "dkID3 should be supported by new court " );
385+
386+ vm.prank (owner);
387+ supportedDK[0 ] = DISPUTE_KIT_CLASSIC;
388+ supportedDK[1 ] = dkID2;
389+ core.enableDisputeKits (GENERAL_COURT, supportedDK, true );
390+ assertEq (core.isSupported (GENERAL_COURT, dkID2), true , "dkID2 should be supported by GENERAL_COURT " );
391+
392+ bytes memory newExtraData = abi.encodePacked (uint256 (newCourtID), DEFAULT_NB_OF_JURORS, dkID3);
393+ arbitrable.changeArbitratorExtraData (newExtraData);
394+
395+ vm.prank (staker1);
396+ core.setStake (newCourtID, 20000 );
397+ vm.prank (disputer);
398+ arbitrable.createDispute {value: feeForJuror * DEFAULT_NB_OF_JURORS}("Action " );
399+ vm.warp (block .timestamp + minStakingTime);
400+ sortitionModule.passPhase (); // Generating
401+ vm.warp (block .timestamp + rngLookahead);
402+ sortitionModule.passPhase (); // Drawing phase
403+
404+ KlerosCoreBase.Round memory round = core.getRoundInfo (disputeID, 0 );
405+ assertEq (round.disputeKitID, dkID3, "Wrong DK ID " );
406+
407+ core.draw (disputeID, DEFAULT_NB_OF_JURORS);
408+ vm.warp (block .timestamp + timesPerPeriod[0 ]);
409+ core.passPeriod (disputeID); // Vote
410+
411+ uint256 [] memory voteIDs = new uint256 [](3 );
412+ voteIDs[0 ] = 0 ;
413+ voteIDs[1 ] = 1 ;
414+ voteIDs[2 ] = 2 ;
415+
416+ vm.prank (staker1);
417+ disputeKit3.castVote (disputeID, voteIDs, 2 , 0 , "XYZ " );
418+
419+ core.passPeriod (disputeID); // Appeal
420+
421+ vm.prank (crowdfunder1);
422+ disputeKit3.fundAppeal {value: 0.63 ether }(disputeID, 1 );
423+
424+ assertEq (core.isDisputeKitJumping (disputeID), true , "Should be jumping " );
425+
426+ vm.expectEmit (true , true , true , true );
427+ emit KlerosCoreBase.CourtJump (disputeID, 1 , newCourtID, GENERAL_COURT);
428+ vm.expectEmit (true , true , true , true );
429+ emit KlerosCoreBase.DisputeKitJump (disputeID, 1 , dkID3, dkID2);
430+ vm.expectEmit (true , true , true , true );
431+ emit DisputeKitClassicBase.DisputeCreation (disputeID, 2 , newExtraData);
432+ vm.expectEmit (true , true , true , true );
433+ emit KlerosCoreBase.AppealDecision (disputeID, arbitrable);
434+ vm.expectEmit (true , true , true , true );
435+ emit KlerosCoreBase.NewPeriod (disputeID, KlerosCoreBase.Period.evidence);
436+ vm.prank (crowdfunder2);
437+ disputeKit3.fundAppeal {value: 0.42 ether }(disputeID, 2 );
438+
439+ (, bool jumped , ) = disputeKit3.disputes (disputeID);
440+ assertEq (jumped, true , "jumped should be true " );
441+ assertEq (
442+ (disputeKit3.getFundedChoices (disputeID)).length ,
443+ 2 ,
444+ "No fresh round created so the number of funded choices should be 2 "
445+ );
446+
447+ round = core.getRoundInfo (disputeID, 1 );
448+ assertEq (round.disputeKitID, dkID2, "Wrong DK ID " );
449+ assertEq (sortitionModule.disputesWithoutJurors (), 1 , "Wrong disputesWithoutJurors count " );
450+ (uint96 courtID , , , , ) = core.disputes (disputeID);
451+ assertEq (courtID, GENERAL_COURT, "Wrong court ID " );
452+
453+ (, jumped, ) = disputeKit2.disputes (disputeID);
454+ assertEq (jumped, false , "jumped should be false in the DK that dispute jumped to " );
455+
456+ // Check jump modifier
457+ vm.prank (address (core));
458+ vm.expectRevert (DisputeKitClassicBase.DisputeJumpedToParentDK.selector );
459+ disputeKit3.draw (disputeID, 1 );
460+
461+ // And check that draw in the new round works
462+ vm.expectEmit (true , true , true , true );
463+ emit KlerosCoreBase.Draw (staker1, disputeID, 1 , 0 ); // roundID = 1 VoteID = 0
464+ core.draw (disputeID, 1 );
465+
466+ (address account , , , ) = disputeKit2.getVoteInfo (disputeID, 1 , 0 );
467+ assertEq (account, staker1, "Wrong drawn account in the classic DK " );
468+ }
469+
329470 function test_appeal_quickPassPeriod () public {
330471 uint256 disputeID = 0 ;
331472
0 commit comments