@@ -369,12 +369,12 @@ describe("Arbitrum to Gnosis Bridge Tests", async () => {
369369 await network.provider.send("evm_mine");
370370
371371 // Ensure bridger and challenger have enough WETH
372- await weth.transfer(bridger.address, TEN_ETH.mul(2 ));
373- await weth.transfer(challenger.address, TEN_ETH.mul(2 ));
372+ await weth.transfer(bridger.address, TEN_ETH.mul(10 ));
373+ await weth.transfer(challenger.address, TEN_ETH.mul(10 ));
374374
375375 // Approve WETH spending for both
376- await weth.connect(bridger).approve(veaOutbox.address, TEN_ETH.mul(2 ));
377- await weth.connect(challenger).approve(veaOutbox.address, TEN_ETH.mul(2 ));
376+ await weth.connect(bridger).approve(veaOutbox.address, TEN_ETH.mul(10 ));
377+ await weth.connect(challenger).approve(veaOutbox.address, TEN_ETH.mul(10 ));
378378 await amb.setMaxGasPerTx(100000);
379379 });
380380
@@ -447,10 +447,102 @@ describe("Arbitrum to Gnosis Bridge Tests", async () => {
447447 const verifiedEvent = verifiedEvents[0];
448448 expect(verifiedEvent.args._epoch).to.equal(epoch, "Verified event epoch mismatch");
449449
450+ const expectedClaim = {
451+ stateRoot: batchMerkleRoot,
452+ claimer: bridger.address,
453+ timestampClaimed: claimBlock.timestamp,
454+ timestampVerification: 0,
455+ blocknumberVerification: 0,
456+ honest: 1,
457+ challenger: challenger.address,
458+ };
459+
460+ const expectedClaimHash = await veaOutbox.hashClaim(expectedClaim);
461+ const storedClaimHash = await veaOutbox.claimHashes(epoch);
462+
463+ expect(storedClaimHash).to.equal(expectedClaimHash, "Stored claim hash does not match expected");
450464 expect(await veaOutbox.stateRoot()).to.equal(batchMerkleRoot, "VeaOutbox stateRoot should be updated");
451465 expect(await veaOutbox.latestVerifiedEpoch()).to.equal(epoch, "VeaOutbox latestVerifiedEpoch should be updated");
452466 });
453467
468+ it("should not update latestEpoch and stateRoot when resolving older dispute", async () => {
469+ const { claimBlock } = await setupClaimAndChallenge(epoch, batchMerkleRoot, 0);
470+
471+ // Create and verify newer epochs
472+ const newEpoch1 = epoch + 1;
473+ const newMerkleRoot1 = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("newer1"));
474+
475+ // Advance time to the next epoch
476+ await network.provider.send("evm_increaseTime", [EPOCH_PERIOD]);
477+ await network.provider.send("evm_mine");
478+
479+ const newClaimTxOne = await veaOutbox.connect(bridger).claim(newEpoch1, newMerkleRoot1);
480+ const newClaimTxOneBlock = await ethers.provider.getBlock(newClaimTxOne.blockNumber!);
481+
482+ const sequencerDelayLimit = await veaOutbox.sequencerDelayLimit();
483+ const maxL2StateSyncDelay = sequencerDelayLimit.add(EPOCH_PERIOD);
484+ await network.provider.send("evm_increaseTime", [maxL2StateSyncDelay.toNumber()]);
485+ await network.provider.send("evm_mine");
486+
487+ const newVerifyTxOne = await veaOutbox.startVerification(
488+ newEpoch1,
489+ createClaim(newMerkleRoot1, bridger.address, newClaimTxOneBlock.timestamp)
490+ );
491+ const newVerifyTxOneBlock = await ethers.provider.getBlock(newVerifyTxOne.blockNumber!);
492+
493+ await network.provider.send("evm_increaseTime", [CHALLENGE_PERIOD]);
494+ await network.provider.send("evm_mine");
495+
496+ await veaOutbox.connect(bridger).verifySnapshot(newEpoch1, {
497+ ...createClaim(newMerkleRoot1, bridger.address, newClaimTxOneBlock.timestamp),
498+ blocknumberVerification: newVerifyTxOne.blockNumber!,
499+ timestampVerification: newVerifyTxOneBlock.timestamp,
500+ });
501+
502+ // Advance time to the next epoch
503+ await network.provider.send("evm_increaseTime", [EPOCH_PERIOD]);
504+ await network.provider.send("evm_mine");
505+
506+ const newEpoch2 = (await veaOutbox.epochNow()).toNumber() - 1;
507+ const newMerkleRoot2 = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("newer2"));
508+ const newClaimTxTwo = await veaOutbox.connect(bridger).claim(newEpoch2, newMerkleRoot2);
509+
510+ const newClaimTxTwoBlock = await ethers.provider.getBlock(newClaimTxTwo.blockNumber!);
511+
512+ await network.provider.send("evm_increaseTime", [maxL2StateSyncDelay.toNumber()]);
513+ await network.provider.send("evm_mine");
514+
515+ const newVerifyTxTwo = await veaOutbox.startVerification(
516+ newEpoch2,
517+ createClaim(newMerkleRoot2, bridger.address, newClaimTxTwoBlock.timestamp)
518+ );
519+ const newVerifyTxTwoBlock = await ethers.provider.getBlock(newVerifyTxTwo.blockNumber!);
520+
521+ await network.provider.send("evm_increaseTime", [CHALLENGE_PERIOD]);
522+ await network.provider.send("evm_mine");
523+
524+ await veaOutbox.connect(bridger).verifySnapshot(newEpoch2, {
525+ ...createClaim(newMerkleRoot2, bridger.address, newClaimTxTwoBlock.timestamp),
526+ timestampVerification: newVerifyTxTwoBlock.timestamp!,
527+ blocknumberVerification: newVerifyTxTwo.blockNumber!,
528+ });
529+
530+ // Resolve the dispute for the old epoch
531+ await simulateDisputeResolution(epoch, {
532+ stateRoot: batchMerkleRoot,
533+ claimer: bridger.address,
534+ timestampClaimed: claimBlock.timestamp,
535+ timestampVerification: 0,
536+ blocknumberVerification: 0,
537+ honest: 0,
538+ challenger: challenger.address,
539+ });
540+
541+ // Check that latestEpoch and stateRoot weren't updated to the old epoch's data
542+ expect(await veaOutbox.latestVerifiedEpoch()).to.equal(newEpoch2, "Latest verified epoch should not change");
543+ expect(await veaOutbox.stateRoot()).to.equal(newMerkleRoot2, "State root should not change");
544+ });
545+
454546 it("should allow bridger to withdraw deposit plus reward", async () => {
455547 const { claimBlock } = await setupClaimAndChallenge(epoch, batchMerkleRoot, 0);
456548
@@ -558,12 +650,12 @@ describe("Arbitrum to Gnosis Bridge Tests", async () => {
558650 await network.provider.send("evm_mine");
559651
560652 // Ensure bridger and challenger have enough WETH
561- await weth.transfer(bridger.address, TEN_ETH.mul(2 ));
562- await weth.transfer(challenger.address, TEN_ETH.mul(2 ));
653+ await weth.transfer(bridger.address, TEN_ETH.mul(10 ));
654+ await weth.transfer(challenger.address, TEN_ETH.mul(10 ));
563655
564656 // Approve WETH spending for both
565- await weth.connect(bridger).approve(veaOutbox.address, TEN_ETH.mul(2 ));
566- await weth.connect(challenger).approve(veaOutbox.address, TEN_ETH.mul(2 ));
657+ await weth.connect(bridger).approve(veaOutbox.address, TEN_ETH.mul(10 ));
658+ await weth.connect(challenger).approve(veaOutbox.address, TEN_ETH.mul(10 ));
567659 });
568660
569661 it("should allow challenger to submit a challenge to a dishonest claim", async () => {
@@ -613,6 +705,21 @@ describe("Arbitrum to Gnosis Bridge Tests", async () => {
613705 challenger: challenger.address,
614706 });
615707
708+ const expectedClaim = {
709+ stateRoot: dishonestMerkleRoot,
710+ claimer: bridger.address,
711+ timestampClaimed: claimBlock.timestamp,
712+ timestampVerification: 0,
713+ blocknumberVerification: 0,
714+ honest: 2,
715+ challenger: challenger.address,
716+ };
717+
718+ const expectedClaimHash = await veaOutbox.hashClaim(expectedClaim);
719+ const storedClaimHash = await veaOutbox.claimHashes(epoch);
720+
721+ expect(storedClaimHash).to.equal(expectedClaimHash, "Stored claim hash does not match expected");
722+
616723 expect(await veaOutbox.stateRoot()).to.equal(honestMerkleRoot, "State root should be updated to honest root");
617724 });
618725
@@ -718,6 +825,84 @@ describe("Arbitrum to Gnosis Bridge Tests", async () => {
718825 expect(await veaOutbox.stateRoot()).to.equal(honestMerkleRoot, "State root should be updated to honest root");
719826 });
720827
828+ it("should not update latestEpoch and stateRoot when resolving older dispute", async () => {
829+ const { claimBlock } = await setupClaimAndChallenge(epoch, dishonestMerkleRoot, 0);
830+
831+ // Create and verify newer epochs
832+ const newEpoch1 = epoch + 1;
833+ const newMerkleRoot1 = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("newer1"));
834+
835+ // Advance time to the next epoch
836+ await network.provider.send("evm_increaseTime", [EPOCH_PERIOD]);
837+ await network.provider.send("evm_mine");
838+
839+ const newClaimTxOne = await veaOutbox.connect(bridger).claim(newEpoch1, newMerkleRoot1);
840+ const newClaimTxOneBlock = await ethers.provider.getBlock(newClaimTxOne.blockNumber!);
841+
842+ const sequencerDelayLimit = await veaOutbox.sequencerDelayLimit();
843+ const maxL2StateSyncDelay = sequencerDelayLimit.add(EPOCH_PERIOD);
844+ await network.provider.send("evm_increaseTime", [maxL2StateSyncDelay.toNumber()]);
845+ await network.provider.send("evm_mine");
846+
847+ const newVerifyTxOne = await veaOutbox.startVerification(
848+ newEpoch1,
849+ createClaim(newMerkleRoot1, bridger.address, newClaimTxOneBlock.timestamp)
850+ );
851+ const newVerifyTxOneBlock = await ethers.provider.getBlock(newVerifyTxOne.blockNumber!);
852+
853+ await network.provider.send("evm_increaseTime", [CHALLENGE_PERIOD]);
854+ await network.provider.send("evm_mine");
855+
856+ await veaOutbox.connect(bridger).verifySnapshot(newEpoch1, {
857+ ...createClaim(newMerkleRoot1, bridger.address, newClaimTxOneBlock.timestamp),
858+ blocknumberVerification: newVerifyTxOne.blockNumber!,
859+ timestampVerification: newVerifyTxOneBlock.timestamp,
860+ });
861+
862+ // Advance time to the next epoch
863+ await network.provider.send("evm_increaseTime", [EPOCH_PERIOD]);
864+ await network.provider.send("evm_mine");
865+
866+ const newEpoch2 = (await veaOutbox.epochNow()).toNumber() - 1;
867+ const newMerkleRoot2 = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("newer2"));
868+ const newClaimTxTwo = await veaOutbox.connect(bridger).claim(newEpoch2, newMerkleRoot2);
869+
870+ const newClaimTxTwoBlock = await ethers.provider.getBlock(newClaimTxTwo.blockNumber!);
871+
872+ await network.provider.send("evm_increaseTime", [maxL2StateSyncDelay.toNumber()]);
873+ await network.provider.send("evm_mine");
874+
875+ const newVerifyTxTwo = await veaOutbox.startVerification(
876+ newEpoch2,
877+ createClaim(newMerkleRoot2, bridger.address, newClaimTxTwoBlock.timestamp)
878+ );
879+ const newVerifyTxTwoBlock = await ethers.provider.getBlock(newVerifyTxTwo.blockNumber!);
880+
881+ await network.provider.send("evm_increaseTime", [CHALLENGE_PERIOD]);
882+ await network.provider.send("evm_mine");
883+
884+ await veaOutbox.connect(bridger).verifySnapshot(newEpoch2, {
885+ ...createClaim(newMerkleRoot2, bridger.address, newClaimTxTwoBlock.timestamp),
886+ timestampVerification: newVerifyTxTwoBlock.timestamp!,
887+ blocknumberVerification: newVerifyTxTwo.blockNumber!,
888+ });
889+
890+ // Resolve the dispute for the old epoch
891+ await simulateDisputeResolution(epoch, {
892+ stateRoot: dishonestMerkleRoot,
893+ claimer: bridger.address,
894+ timestampClaimed: claimBlock.timestamp,
895+ timestampVerification: 0,
896+ blocknumberVerification: 0,
897+ honest: 0,
898+ challenger: challenger.address,
899+ });
900+
901+ // Check that latestEpoch and stateRoot weren't updated to the old epoch's data
902+ expect(await veaOutbox.latestVerifiedEpoch()).to.equal(newEpoch2, "Latest verified epoch should not change");
903+ expect(await veaOutbox.stateRoot()).to.equal(newMerkleRoot2, "State root should not change");
904+ });
905+
721906 it("should not allow multiple withdrawals for the same challenge", async () => {
722907 const { claimBlock } = await setupClaimAndChallenge(epoch, dishonestMerkleRoot, 0);
723908
0 commit comments