Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test/integration arbitrum to gnosis #319

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions contracts/deploy/01-outbox/01-arb-to-gnosis-outbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ const paramsByChainId = {
sequencerLimit: 86400, // 24 hours
},
HARDHAT: {
deposit: parseEther("5"), // 120 xDAI budget for timeout
deposit: parseEther("10"),
// Average happy path wait time is 22.5 mins, assume no censorship
epochPeriod: 600, // 10 min
challengePeriod: 600, // 10 min (assume no sequencer backdating)
numEpochTimeout: 24, // 6 hours
minChallengePeriod: 600, // 10 min (assume no sequencer backdating)
numEpochTimeout: 21600, // 6 hours
fcanela marked this conversation as resolved.
Show resolved Hide resolved
claimDelay: 2,
amb: ethers.constants.AddressZero,
routerAddress: ethers.constants.AddressZero,
maxMissingBlocks: 10000000000000,
routerChainId: 31337,
sequencerLimit: 86400, // 24 hours
sequencerLimit: 864,
},
};

Expand All @@ -56,8 +56,15 @@ const deployOutbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { providers } = ethers;

// fallback to hardhat node signers on local network
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
const chainId = Number(await getChainId());
const [namedAccounts, signers, rawChainId] = await Promise.all([
getNamedAccounts(),
hre.ethers.getSigners(),
getChainId(),
]);

const deployer = namedAccounts.deployer ?? signers[0].address;
const chainId = Number(rawChainId);

console.log("deploying to chainId %s with deployer %s", chainId, deployer);

const routerNetworks = {
Expand All @@ -84,27 +91,50 @@ const deployOutbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
// ----------------------------------------------------------------------------------------------
const hardhatDeployer = async () => {
let nonce = await ethers.provider.getTransactionCount(deployer);
nonce += 4; // SenderGatewayToEthereum deploy tx will be the 5th after this, same network for both sender/receiver.

const routerAddress = getContractAddress(deployer, nonce);
console.log("calculated future router for nonce %d: %s", nonce, routerAddress);
const routerAddress = getContractAddress(deployer, nonce + 10);
console.log("calculated future router for nonce %d: %s", nonce + 10, routerAddress);

const senderGatewayAddress = getContractAddress(deployer, nonce + 6); // with the current order of transaction ,nonce for sender gateway would be 14.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Inconsistency between nonce calculation and comment for senderGatewayAddress

There's a discrepancy between the nonce increment used in the code and the nonce value mentioned in the comment. The code calculates senderGatewayAddress using nonce + 6, but the comment states that the nonce for senderGateway would be 14. Please verify and update the comment or adjust the nonce calculation to ensure consistency.

console.log("calculated future SenderGatewayToGnosis address for nonce %d: %s", nonce + 6, senderGatewayAddress);

await deploy("VeaOutboxGnosisMock", {
const ambMock = await deploy("MockAMB", {
from: deployer,
args: [],
log: true,
});

const wethMock = await deploy("MockWETH", {
from: deployer,
args: [],
log: true,
});

const veaOutbox = await deploy("VeaOutboxArbToGnosis", {
from: deployer,
contract: "VeaOutboxArbToGnosis",
args: [
deposit,
epochPeriod,
minChallengePeriod,
numEpochTimeout,
amb,
ethers.constants.AddressZero,
ambMock.address,
routerAddress,
sequencerLimit,
maxMissingBlocks,
routerChainId,
WETH,
wethMock.address,
],
log: true,
});

await deploy("ArbToGnosisReceiverGateway", {
from: deployer,
contract: "ReceiverGatewayMock",
args: [veaOutbox.address, senderGatewayAddress],
gasLimit: 4000000,
log: true,
});
};

// ----------------------------------------------------------------------------------------------
Expand Down
73 changes: 53 additions & 20 deletions contracts/deploy/02-inbox/02-arb-to-gnosis-inbox.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import getContractAddress from "../../deploy-helpers/getContractAddress";
import { ethers } from "hardhat";

enum SenderChains {
ARBITRUM = 42161,
ARBITRUM_SEPOLIA = 421614,
HARDHAT = 31337,
}

const paramsByChainId = {
ARBITRUM: {
epochPeriod: 3600, // 1 hours
Expand All @@ -19,38 +21,69 @@ const paramsByChainId = {
},
};

// TODO: use deterministic deployments
const deployInbox: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { ethers, deployments, getNamedAccounts, getChainId, config } = hre;
const { deploy } = deployments;
const chainId = Number(await getChainId());
const { providers } = ethers;

const deployer = (await getNamedAccounts()).deployer;
console.log("deployer: %s", deployer);
// fallback to hardhat node signers on local network
const [namedAccounts, signers, rawChainId] = await Promise.all([
getNamedAccounts(),
hre.ethers.getSigners(),
getChainId(),
]);

const deployer = namedAccounts.deployer ?? signers[0].address;
const chainId = Number(rawChainId);

console.log("deploying to chainId %s with deployer %s", chainId, deployer);

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

const routerNetworks = {
ARBITRUM: config.networks.mainnet,
ARBITRUM_SEPOLIA: config.networks.sepolia,
HARDHAT: config.networks.localhost,
};
// Hack to predict the deployment address on the sender chain.
// TODO: use deterministic deployments
madhurMongia marked this conversation as resolved.
Show resolved Hide resolved

// ----------------------------------------------------------------------------------------------
const hardhatDeployer = async () => {
let nonce = await ethers.provider.getTransactionCount(deployer);

const arbitrumBridgeAddress = getContractAddress(deployer, nonce + 5);

const routerChainProvider = new providers.JsonRpcProvider(routerNetworks[SenderChains[chainId]].url);
let nonceRouter = await routerChainProvider.getTransactionCount(deployer);
const arbSysMock = await deploy("ArbSysMock", {
fcanela marked this conversation as resolved.
Show resolved Hide resolved
from: deployer,
contract: "ArbSysMockWithBridge",
args: [arbitrumBridgeAddress],
log: true,
});

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

await deploy("VeaInboxArbToGnosis" + (chainId === 42161 ? "" : "Testnet"), {
contract: "VeaInboxArbToGnosis",
from: deployer,
args: [epochPeriod, routerAddress],
log: true,
});
const receiverGateway = await deployments.get("ArbToGnosisReceiverGateway");
const veaInbox = await deploy("VeaInboxArbToGnosis", {
from: deployer,
contract: "VeaInboxArbToGnosisMock",
args: [epochPeriod, routerAddress, arbSysMock.address],
log: true,
});

await deploy("ArbToGnosisSenderGateway", {
from: deployer,
contract: "SenderGatewayMock",
args: [veaInbox.address, receiverGateway.address],
gasLimit: 4000000,
log: true,
});
madhurMongia marked this conversation as resolved.
Show resolved Hide resolved
};

// ----------------------------------------------------------------------------------------------
const liveDeployer = async () => {};

// ----------------------------------------------------------------------------------------------
if (chainId === 31337) {
await hardhatDeployer();
} else {
await liveDeployer();
}
madhurMongia marked this conversation as resolved.
Show resolved Hide resolved
};

deployInbox.tags = ["ArbToGnosisInbox"];
Expand Down
40 changes: 33 additions & 7 deletions contracts/deploy/03-routers/03-arb-to-gnosis-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,50 @@ const paramsByChainId = {
const deployRouter: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { deployments, getNamedAccounts, getChainId } = hre;
const { deploy } = deployments;
const chainId = Number(await getChainId());

// fallback to hardhat node signers on local network
const deployer = (await getNamedAccounts()).deployer ?? (await hre.ethers.getSigners())[0].address;
console.log("deployer: %s", deployer);
const [namedAccounts, signers, rawChainId] = await Promise.all([
getNamedAccounts(),
hre.ethers.getSigners(),
getChainId(),
]);

const deployer = namedAccounts.deployer ?? signers[0].address;
const chainId = Number(rawChainId);

console.log("deploying to chainId %s with deployer %s", chainId, deployer);

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

// ----------------------------------------------------------------------------------------------
const hardhatDeployer = async () => {
const veaOutbox = await deployments.get("VeaOutboxArbToGnosis");
const veaInbox = await deployments.get("VeaInboxArbToGnosis");
const [veaOutbox, veaInbox, amb] = await Promise.all([
deployments.get("VeaOutboxArbToGnosis"),
deployments.get("VeaInboxArbToGnosis"),
deployments.get("MockAMB"),
]);

const sequencerInbox = await deploy("SequencerInboxMock", {
madhurMongia marked this conversation as resolved.
Show resolved Hide resolved
from: deployer,
contract: "SequencerInboxMock",
args: ["10"],
});
const outbox = await deploy("OutboxMock", {
from: deployer,
args: [veaInbox.address],
log: true,
});

const arbitrumBridge = await deploy("BridgeMock", {
from: deployer,
contract: "BridgeMock",
args: [outbox.address, sequencerInbox.address],
});

const router = await deploy("RouterArbToGnosis", {
from: deployer,
contract: "RouterArbToGnosis",
args: [arbitrumBridge, amb, veaInbox.address, veaOutbox.address],
args: [arbitrumBridge.address, amb.address, veaInbox.address, veaOutbox.address],
});
};

Expand Down Expand Up @@ -73,7 +100,6 @@ const deployRouter: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
deployRouter.tags = ["ArbToGnosisRouter"];
deployRouter.skip = async ({ getChainId }) => {
const chainId = Number(await getChainId());
console.log(chainId);
return !RouterChains[chainId];
};
deployRouter.runAtTheEnd = true;
Expand Down
39 changes: 39 additions & 0 deletions contracts/src/test/ArbToGnosis/VeaInboxArbToGnosisMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT

/// @custom:authors: [@madhurMongia]
/// @custom:reviewers: []
/// @custom:auditors: []
/// @custom:bounties: []
/// @custom:deployments: []

pragma solidity 0.8.24;

import "../../arbitrumToGnosis/VeaInboxArbToGnosis.sol";
import "../../canonical/arbitrum/IArbSys.sol";
import "../../interfaces/routers/IRouterToGnosis.sol";

contract VeaInboxArbToGnosisMock is VeaInboxArbToGnosis {
IArbSys public immutable mockArbSys;

constructor(
uint256 _epochPeriod,
address _routerArbToGnosis,
IArbSys _mockArbSys
) VeaInboxArbToGnosis(_epochPeriod, _routerArbToGnosis) {
mockArbSys = _mockArbSys;
}

// Override sendSnapshot to use the mock ArbSys
function sendSnapshot(uint256 _epoch, uint256 _gasLimit, Claim memory _claim) external override {
unchecked {
require(_epoch < block.timestamp / epochPeriod, "Can only send past epoch snapshot.");
}

bytes memory data = abi.encodeCall(IRouterToGnosis.route, (_epoch, snapshots[_epoch], _gasLimit, _claim));

// Use the mock ArbSys instead of the constant ARB_SYS
bytes32 ticketID = bytes32(mockArbSys.sendTxToL1(routerArbToGnosis, data));

emit SnapshotSent(_epoch, ticketID);
}
madhurMongia marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT

/// @custom:authors: [@madhurMongia]
/// @custom:reviewers: []
/// @custom:auditors: []
/// @custom:bounties: []
/// @custom:deployments: []

pragma solidity 0.8.24;

import "../../../canonical/arbitrum/IArbSys.sol";
import "./BridgeMock.sol";

contract ArbSysMockWithBridge is IArbSys {
BridgeMock public immutable bridge;

constructor(BridgeMock _bridge) {
bridge = _bridge;
}

function sendTxToL1(
address destination,
bytes calldata calldataForL1
) external payable returns (uint256 _withdrawal_ID) {
return bridge.executeL1Message(destination, calldataForL1);
}
}
15 changes: 14 additions & 1 deletion contracts/src/test/bridge-mocks/arbitrum/BridgeMock.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT

/// @custom:authors: [@hrishibhat]
/// @custom:authors: [@hrishibhat,@madhurMongia]
/// @custom:reviewers: []
/// @custom:auditors: []
/// @custom:bounties: []
Expand All @@ -27,4 +27,17 @@ contract BridgeMock is IBridge {
if (index == 0) return sequencerInbox;
return address(0);
}

function executeL1Message(address destination, bytes calldata data) external returns (uint256) {
// Simulate the bridge calling the destination contract
(bool success, bytes memory returnData) = destination.call(data);

if (!success) {
assembly {
revert(add(returnData, 32), mload(returnData))
}
}

return 0;
}
}
Loading
Loading