Skip to content

Commit 46247de

Browse files
committed
test(arbToGno): added more unit test and concurrency in deployment scripts
1 parent 2c3c514 commit 46247de

File tree

4 files changed

+229
-22
lines changed

4 files changed

+229
-22
lines changed

contracts/deploy/01-outbox/01-arb-to-gnosis-outbox.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const paramsByChainId = {
3636
sequencerLimit: 86400, // 24 hours
3737
},
3838
HARDHAT: {
39-
deposit: parseEther("10"), // 120 xDAI budget for timeout
39+
deposit: parseEther("10"),
4040
// Average happy path wait time is 22.5 mins, assume no censorship
4141
epochPeriod: 600, // 10 min
4242
minChallengePeriod: 600, // 10 min (assume no sequencer backdating)
@@ -56,8 +56,15 @@ const deployOutbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
5656
const { providers } = ethers;
5757

5858
// fallback to hardhat node signers on local network
59-
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
60-
const chainId = Number(await getChainId());
59+
const [namedAccounts, signers, rawChainId] = await Promise.all([
60+
getNamedAccounts(),
61+
hre.ethers.getSigners(),
62+
getChainId(),
63+
]);
64+
65+
const deployer = namedAccounts.deployer ?? signers[0].address;
66+
const chainId = Number(rawChainId);
67+
6168
console.log("deploying to chainId %s with deployer %s", chainId, deployer);
6269

6370
const routerNetworks = {
@@ -89,7 +96,7 @@ const deployOutbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
8996
console.log("calculated future router for nonce %d: %s", nonce + 10, routerAddress);
9097

9198
const senderGatewayAddress = getContractAddress(deployer, nonce + 6); // with the current order of transaction ,nonce for sender gateway would be 14.
92-
console.log("calculated future SenderGatewayToGnosis address for nonce %d: %s", nonce, senderGatewayAddress);
99+
console.log("calculated future SenderGatewayToGnosis address for nonce %d: %s", nonce + 6, senderGatewayAddress);
93100

94101
const ambMock = await deploy("MockAMB", {
95102
from: deployer,

contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ const paramsByChainId = {
1818
},
1919
HARDHAT: {
2020
epochPeriod: 600, // 10 minutes
21-
routerAddress: ethers.constants.AddressZero,
2221
},
2322
};
2423

@@ -27,8 +26,16 @@ const deployInbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
2726
const { deploy } = deployments;
2827

2928
// fallback to hardhat node signers on local network
30-
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
31-
const chainId = Number(await getChainId());
29+
const [namedAccounts, signers, rawChainId] = await Promise.all([
30+
getNamedAccounts(),
31+
hre.ethers.getSigners(),
32+
getChainId(),
33+
]);
34+
35+
const deployer = namedAccounts.deployer ?? signers[0].address;
36+
const chainId = Number(rawChainId);
37+
38+
console.log("deploying to chainId %s with deployer %s", chainId, deployer);
3239

3340
const { epochPeriod } = paramsByChainId[SenderChains[chainId]];
3441

contracts/deploy/03-routers/03-arb-to-gnosis-router.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,28 @@ const paramsByChainId = {
2727
const deployRouter: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
2828
const { deployments, getNamedAccounts, getChainId } = hre;
2929
const { deploy } = deployments;
30-
const chainId = Number(await getChainId());
3130

3231
// fallback to hardhat node signers on local network
33-
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
34-
console.log("deployer: %s", deployer);
32+
const [namedAccounts, signers, rawChainId] = await Promise.all([
33+
getNamedAccounts(),
34+
hre.ethers.getSigners(),
35+
getChainId(),
36+
]);
37+
38+
const deployer = namedAccounts.deployer ?? signers[0].address;
39+
const chainId = Number(rawChainId);
40+
41+
console.log("deploying to chainId %s with deployer %s", chainId, deployer);
3542

3643
const { arbitrumBridge, amb } = paramsByChainId[RouterChains[chainId]];
3744

3845
// ----------------------------------------------------------------------------------------------
3946
const hardhatDeployer = async () => {
40-
const veaOutbox = await deployments.get("VeaOutboxArbToGnosis");
41-
const veaInbox = await deployments.get("VeaInboxArbToGnosis");
42-
const amb = await deployments.get("MockAMB");
43-
//const ArbSysMock = await deployments.get('arbSysMock');
47+
const [veaOutbox, veaInbox, amb] = await Promise.all([
48+
deployments.get("VeaOutboxArbToGnosis"),
49+
deployments.get("VeaInboxArbToGnosis"),
50+
deployments.get("MockAMB"),
51+
]);
4452

4553
const sequencerInbox = await deploy("SequencerInboxMock", {
4654
from: deployer,

contracts/test/integration/ArbToGnosis.ts

Lines changed: 193 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)