Skip to content

Commit 9f97125

Browse files
authored
Merge pull request #319 from kleros/test/integration-arbitrum-to-gnosis
Test/integration arbitrum to gnosis
2 parents e22031e + 46247de commit 9f97125

File tree

9 files changed

+1247
-48
lines changed

9 files changed

+1247
-48
lines changed

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

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ const paramsByChainId = {
3636
sequencerLimit: 86400, // 24 hours
3737
},
3838
HARDHAT: {
39-
deposit: parseEther("5"), // 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
42-
challengePeriod: 600, // 10 min (assume no sequencer backdating)
43-
numEpochTimeout: 24, // 6 hours
42+
minChallengePeriod: 600, // 10 min (assume no sequencer backdating)
43+
numEpochTimeout: 21600, // 6 hours
4444
claimDelay: 2,
4545
amb: ethers.constants.AddressZero,
4646
routerAddress: ethers.constants.AddressZero,
4747
maxMissingBlocks: 10000000000000,
4848
routerChainId: 31337,
49-
sequencerLimit: 86400, // 24 hours
49+
sequencerLimit: 864,
5050
},
5151
};
5252

@@ -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 = {
@@ -84,27 +91,50 @@ const deployOutbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
8491
// ----------------------------------------------------------------------------------------------
8592
const hardhatDeployer = async () => {
8693
let nonce = await ethers.provider.getTransactionCount(deployer);
87-
nonce += 4; // SenderGatewayToEthereum deploy tx will be the 5th after this, same network for both sender/receiver.
8894

89-
const routerAddress = getContractAddress(deployer, nonce);
90-
console.log("calculated future router for nonce %d: %s", nonce, routerAddress);
95+
const routerAddress = getContractAddress(deployer, nonce + 10);
96+
console.log("calculated future router for nonce %d: %s", nonce + 10, routerAddress);
97+
98+
const senderGatewayAddress = getContractAddress(deployer, nonce + 6); // with the current order of transaction ,nonce for sender gateway would be 14.
99+
console.log("calculated future SenderGatewayToGnosis address for nonce %d: %s", nonce + 6, senderGatewayAddress);
91100

92-
await deploy("VeaOutboxGnosisMock", {
101+
const ambMock = await deploy("MockAMB", {
93102
from: deployer,
103+
args: [],
104+
log: true,
105+
});
106+
107+
const wethMock = await deploy("MockWETH", {
108+
from: deployer,
109+
args: [],
110+
log: true,
111+
});
112+
113+
const veaOutbox = await deploy("VeaOutboxArbToGnosis", {
114+
from: deployer,
115+
contract: "VeaOutboxArbToGnosis",
94116
args: [
95117
deposit,
96118
epochPeriod,
97119
minChallengePeriod,
98120
numEpochTimeout,
99-
amb,
100-
ethers.constants.AddressZero,
121+
ambMock.address,
122+
routerAddress,
101123
sequencerLimit,
102124
maxMissingBlocks,
103125
routerChainId,
104-
WETH,
126+
wethMock.address,
105127
],
106128
log: true,
107129
});
130+
131+
await deploy("ArbToGnosisReceiverGateway", {
132+
from: deployer,
133+
contract: "ReceiverGatewayMock",
134+
args: [veaOutbox.address, senderGatewayAddress],
135+
gasLimit: 4000000,
136+
log: true,
137+
});
108138
};
109139

110140
// ----------------------------------------------------------------------------------------------

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

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { HardhatRuntimeEnvironment } from "hardhat/types";
22
import { DeployFunction } from "hardhat-deploy/types";
33
import getContractAddress from "../../deploy-helpers/getContractAddress";
4+
import { ethers } from "hardhat";
45

56
enum SenderChains {
67
ARBITRUM = 42161,
78
ARBITRUM_SEPOLIA = 421614,
89
HARDHAT = 31337,
910
}
11+
1012
const paramsByChainId = {
1113
ARBITRUM: {
1214
epochPeriod: 3600, // 1 hours
@@ -19,38 +21,69 @@ const paramsByChainId = {
1921
},
2022
};
2123

22-
// TODO: use deterministic deployments
2324
const deployInbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
2425
const { ethers, deployments, getNamedAccounts, getChainId, config } = hre;
2526
const { deploy } = deployments;
26-
const chainId = Number(await getChainId());
27-
const { providers } = ethers;
2827

29-
const deployer = (await getNamedAccounts()).deployer;
30-
console.log("deployer: %s", deployer);
28+
// fallback to hardhat node signers on local network
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);
3139

3240
const { epochPeriod } = paramsByChainId[SenderChains[chainId]];
3341

34-
const routerNetworks = {
35-
ARBITRUM: config.networks.mainnet,
36-
ARBITRUM_SEPOLIA: config.networks.sepolia,
37-
HARDHAT: config.networks.localhost,
38-
};
42+
// Hack to predict the deployment address on the sender chain.
43+
// TODO: use deterministic deployments
3944

4045
// ----------------------------------------------------------------------------------------------
46+
const hardhatDeployer = async () => {
47+
let nonce = await ethers.provider.getTransactionCount(deployer);
48+
49+
const arbitrumBridgeAddress = getContractAddress(deployer, nonce + 5);
4150

42-
const routerChainProvider = new providers.JsonRpcProvider(routerNetworks[SenderChains[chainId]].url);
43-
let nonceRouter = await routerChainProvider.getTransactionCount(deployer);
51+
const arbSysMock = await deploy("ArbSysMock", {
52+
from: deployer,
53+
contract: "ArbSysMockWithBridge",
54+
args: [arbitrumBridgeAddress],
55+
log: true,
56+
});
4457

45-
const routerAddress = getContractAddress(deployer, nonceRouter);
46-
console.log("calculated future router for nonce %d: %s", nonceRouter, routerAddress);
58+
const routerAddress = getContractAddress(deployer, nonce + 6);
59+
console.log("calculated future router for nonce %d: %s", nonce + 6, routerAddress);
4760

48-
await deploy("VeaInboxArbToGnosis" + (chainId === 42161 ? "" : "Testnet"), {
49-
contract: "VeaInboxArbToGnosis",
50-
from: deployer,
51-
args: [epochPeriod, routerAddress],
52-
log: true,
53-
});
61+
const receiverGateway = await deployments.get("ArbToGnosisReceiverGateway");
62+
const veaInbox = await deploy("VeaInboxArbToGnosis", {
63+
from: deployer,
64+
contract: "VeaInboxArbToGnosisMock",
65+
args: [epochPeriod, routerAddress, arbSysMock.address],
66+
log: true,
67+
});
68+
69+
await deploy("ArbToGnosisSenderGateway", {
70+
from: deployer,
71+
contract: "SenderGatewayMock",
72+
args: [veaInbox.address, receiverGateway.address],
73+
gasLimit: 4000000,
74+
log: true,
75+
});
76+
};
77+
78+
// ----------------------------------------------------------------------------------------------
79+
const liveDeployer = async () => {};
80+
81+
// ----------------------------------------------------------------------------------------------
82+
if (chainId === 31337) {
83+
await hardhatDeployer();
84+
} else {
85+
await liveDeployer();
86+
}
5487
};
5588

5689
deployInbox.tags = ["ArbToGnosisInbox"];

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,50 @@ 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");
47+
const [veaOutbox, veaInbox, amb] = await Promise.all([
48+
deployments.get("VeaOutboxArbToGnosis"),
49+
deployments.get("VeaInboxArbToGnosis"),
50+
deployments.get("MockAMB"),
51+
]);
52+
53+
const sequencerInbox = await deploy("SequencerInboxMock", {
54+
from: deployer,
55+
contract: "SequencerInboxMock",
56+
args: ["10"],
57+
});
58+
const outbox = await deploy("OutboxMock", {
59+
from: deployer,
60+
args: [veaInbox.address],
61+
log: true,
62+
});
63+
64+
const arbitrumBridge = await deploy("BridgeMock", {
65+
from: deployer,
66+
contract: "BridgeMock",
67+
args: [outbox.address, sequencerInbox.address],
68+
});
4269

4370
const router = await deploy("RouterArbToGnosis", {
4471
from: deployer,
4572
contract: "RouterArbToGnosis",
46-
args: [arbitrumBridge, amb, veaInbox.address, veaOutbox.address],
73+
args: [arbitrumBridge.address, amb.address, veaInbox.address, veaOutbox.address],
4774
});
4875
};
4976

@@ -73,7 +100,6 @@ const deployRouter: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
73100
deployRouter.tags = ["ArbToGnosisRouter"];
74101
deployRouter.skip = async ({ getChainId }) => {
75102
const chainId = Number(await getChainId());
76-
console.log(chainId);
77103
return !RouterChains[chainId];
78104
};
79105
deployRouter.runAtTheEnd = true;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
/// @custom:authors: [@madhurMongia]
4+
/// @custom:reviewers: []
5+
/// @custom:auditors: []
6+
/// @custom:bounties: []
7+
/// @custom:deployments: []
8+
9+
pragma solidity 0.8.24;
10+
11+
import "../../arbitrumToGnosis/VeaInboxArbToGnosis.sol";
12+
import "../../canonical/arbitrum/IArbSys.sol";
13+
import "../../interfaces/routers/IRouterToGnosis.sol";
14+
15+
contract VeaInboxArbToGnosisMock is VeaInboxArbToGnosis {
16+
IArbSys public immutable mockArbSys;
17+
18+
constructor(
19+
uint256 _epochPeriod,
20+
address _routerArbToGnosis,
21+
IArbSys _mockArbSys
22+
) VeaInboxArbToGnosis(_epochPeriod, _routerArbToGnosis) {
23+
mockArbSys = _mockArbSys;
24+
}
25+
26+
// Override sendSnapshot to use the mock ArbSys
27+
function sendSnapshot(uint256 _epoch, uint256 _gasLimit, Claim memory _claim) external override {
28+
unchecked {
29+
require(_epoch < block.timestamp / epochPeriod, "Can only send past epoch snapshot.");
30+
}
31+
32+
bytes memory data = abi.encodeCall(IRouterToGnosis.route, (_epoch, snapshots[_epoch], _gasLimit, _claim));
33+
34+
// Use the mock ArbSys instead of the constant ARB_SYS
35+
bytes32 ticketID = bytes32(mockArbSys.sendTxToL1(routerArbToGnosis, data));
36+
37+
emit SnapshotSent(_epoch, ticketID);
38+
}
39+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
/// @custom:authors: [@madhurMongia]
4+
/// @custom:reviewers: []
5+
/// @custom:auditors: []
6+
/// @custom:bounties: []
7+
/// @custom:deployments: []
8+
9+
pragma solidity 0.8.24;
10+
11+
import "../../../canonical/arbitrum/IArbSys.sol";
12+
import "./BridgeMock.sol";
13+
14+
contract ArbSysMockWithBridge is IArbSys {
15+
BridgeMock public immutable bridge;
16+
17+
constructor(BridgeMock _bridge) {
18+
bridge = _bridge;
19+
}
20+
21+
function sendTxToL1(
22+
address destination,
23+
bytes calldata calldataForL1
24+
) external payable returns (uint256 _withdrawal_ID) {
25+
return bridge.executeL1Message(destination, calldataForL1);
26+
}
27+
}

contracts/src/test/bridge-mocks/arbitrum/BridgeMock.sol

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: MIT
22

3-
/// @custom:authors: [@hrishibhat]
3+
/// @custom:authors: [@hrishibhat,@madhurMongia]
44
/// @custom:reviewers: []
55
/// @custom:auditors: []
66
/// @custom:bounties: []
@@ -27,4 +27,17 @@ contract BridgeMock is IBridge {
2727
if (index == 0) return sequencerInbox;
2828
return address(0);
2929
}
30+
31+
function executeL1Message(address destination, bytes calldata data) external returns (uint256) {
32+
// Simulate the bridge calling the destination contract
33+
(bool success, bytes memory returnData) = destination.call(data);
34+
35+
if (!success) {
36+
assembly {
37+
revert(add(returnData, 32), mload(returnData))
38+
}
39+
}
40+
41+
return 0;
42+
}
3043
}

0 commit comments

Comments
 (0)