Skip to content

Commit e23307e

Browse files
committed
feat(gateway): add deploy scripts
1 parent 62ba1d9 commit e23307e

File tree

15 files changed

+1854
-56
lines changed

15 files changed

+1854
-56
lines changed

contracts/README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,5 @@ This must be done for each network separately.
8888
For `Mainnet` you can use the `etherscan-verify` command from `hardhat`:
8989

9090
```bash
91-
yarn hardhat --network mainnet etherscan-verify
91+
yarn hardhat --network <arbitrumRinkeby|arbitrum|rinkeby|mainnet> etherscan-verify
9292
```
93-
94-
For `Arbitrum` the process currently must be done manually through [Arbiscan](https://arbiscan.io/verifyContract).
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const { BN, Address, toChecksumAddress } = require("ethereumjs-util");
2+
3+
/**
4+
* Gets the address of a soon to be deployed contract.
5+
* @param {string} deployer The address of the deployer account.
6+
* @param {number|BN} nonce The current nonce for the deployer account.
7+
* @return {string} The address of a contract if it is deployed in the next transaction sent by the deployer account.
8+
*/
9+
function getContractAddress(deployer, nonce) {
10+
const deployAddress = Address.generate(Address.fromString(deployer), new BN(String(nonce)));
11+
return toChecksumAddress(deployAddress.toString());
12+
}
13+
14+
module.exports = getContractAddress;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import {parseEther} from 'ethers/lib/utils';
2+
3+
import {HardhatRuntimeEnvironment} from 'hardhat/types';
4+
import {DeployFunction} from 'hardhat-deploy/types';
5+
6+
import getContractAddress from "../deploy-helpers/getContractAddress";
7+
8+
const FOREIGN_CHAIN_IDS = [1, 4];
9+
const paramsByChainId = {
10+
1: {
11+
claimDeposit: parseEther('0.1'),
12+
challengeDuration: 86400, // 1 day
13+
homeChainId: 42161,
14+
},
15+
4: {
16+
claimDeposit: parseEther('0.1'),
17+
challengeDuration: 3600, // 1 hour
18+
homeChainId: 421611,
19+
},
20+
};
21+
22+
const deployForeignGateway: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
23+
const {ethers, deployments, getNamedAccounts, getChainId, config} = hre;
24+
const {deploy} = deployments;
25+
const { providers, constants } = ethers;
26+
const { hexZeroPad } = hre.ethers.utils;
27+
28+
const {deployer } = await getNamedAccounts();
29+
const chainId = await getChainId();
30+
31+
const homeNetworks = {
32+
1: config.networks.arbitrum,
33+
4: config.networks.arbitrumRinkeby,
34+
};
35+
const { url } = homeNetworks[chainId];
36+
const homeChainProvider = new providers.JsonRpcProvider(url);
37+
const nonce = await homeChainProvider.getTransactionCount(deployer);
38+
39+
const { claimDeposit, challengeDuration, homeChainId} = paramsByChainId[chainId];
40+
41+
// home Gateway deploy tx will the third tx after this on it's network,
42+
// so we add two to the current nonce.
43+
const homeGatewayAddress = getContractAddress(deployer, nonce + 2);
44+
45+
const homeChainIdAsBytes32 = hexZeroPad(homeChainId, 32);
46+
console.log(nonce + 2);
47+
console.log(homeGatewayAddress);
48+
49+
let fastBridgeReceiver = await deploy('FastBridgeReceiver', {
50+
from: deployer,
51+
args: [deployer, claimDeposit, challengeDuration],
52+
log: true,
53+
});
54+
55+
let foreignGateway = await deploy('ForeignGateway', {
56+
from: deployer,
57+
args: [deployer, fastBridgeReceiver.address, ["1000", "10000"], homeGatewayAddress, homeChainIdAsBytes32],
58+
log: true,
59+
});
60+
};
61+
62+
deployForeignGateway.tags = ["ForeignChain"];
63+
deployForeignGateway.skip = async ({ getChainId }) => !FOREIGN_CHAIN_IDS.includes(Number(await getChainId()));
64+
65+
export default deployForeignGateway;

contracts/deploy/02-home-chain.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {HardhatRuntimeEnvironment} from 'hardhat/types';
2+
import {DeployFunction} from 'hardhat-deploy/types';
3+
4+
import getContractAddress from "../deploy-helpers/getContractAddress";
5+
6+
const HOME_CHAIN_IDS = [42161, 421611];
7+
const paramsByChainId = {
8+
4: {
9+
arbitrator: "0xab96e690f784b305942752a1fda42680e80f37a0", // SimplePermissionlessArbitrator
10+
foreignChainId: 77,
11+
},
12+
42161: {
13+
arbitrator: "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", // SimplePermissionlessArbitrator
14+
foreignChainId: 1,
15+
},
16+
421611: {
17+
arbitrator: "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", // SimplePermissionlessArbitrator
18+
foreignChainId: 4,
19+
},
20+
};
21+
22+
const deployHomeGateway: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
23+
const {ethers, deployments, getNamedAccounts, getChainId, config} = hre;
24+
const {deploy} = deployments;
25+
const { providers, constants } = ethers;
26+
const { hexZeroPad } = hre.ethers.utils;
27+
28+
const {deployer } = await getNamedAccounts();
29+
const chainId = await getChainId();
30+
31+
const foreignNetworks = {
32+
42161: config.networks.mainnet,
33+
421611: config.networks.rinkeby,
34+
};
35+
const { url } = foreignNetworks[chainId];
36+
const foreignChainProvider = new providers.JsonRpcProvider(url);
37+
const nonce = await foreignChainProvider.getTransactionCount(deployer);
38+
39+
const { arbitrator, foreignChainId } = paramsByChainId[chainId];
40+
41+
// Foreign gateway deploy tx is the last transaction on its network
42+
// So we get it's current nonce subtracted by 1.
43+
const foreignGatewayAddress = getContractAddress(deployer, nonce - 1 );
44+
// And FastBridgeReceiver is the second last tx.
45+
const fastBridgeReceiverAddress = getContractAddress(deployer, nonce - 2 );
46+
47+
const foreignChainIdAsBytes32 = hexZeroPad(foreignChainId, 32);
48+
console.log(fastBridgeReceiverAddress);
49+
console.log(foreignGatewayAddress);
50+
51+
let safeBridge = await deploy('SafeArbitrumBridge', {
52+
from: deployer,
53+
log: true,
54+
});
55+
56+
let fastBridgeSender = await deploy('FastBridgeSender', {
57+
from: deployer,
58+
args: [safeBridge.address, fastBridgeReceiverAddress],
59+
log: true,
60+
});
61+
62+
let homeGateway = await deploy('HomeGateway', {
63+
from: deployer,
64+
args: [arbitrator, fastBridgeSender.address, foreignGatewayAddress, foreignChainIdAsBytes32],
65+
log: true,
66+
});
67+
68+
};
69+
70+
deployHomeGateway.tags = ["HomeChain"];
71+
deployHomeGateway.skip = async ({ getChainId }) => !HOME_CHAIN_IDS.includes(Number(await getChainId()));
72+
73+
export default deployHomeGateway;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
421611
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
{
2+
"address": "0xefA86cB132B608a959621A657f50173370791634",
3+
"abi": [
4+
{
5+
"inputs": [
6+
{
7+
"internalType": "contract ISafeBridge",
8+
"name": "_safebridge",
9+
"type": "address"
10+
},
11+
{
12+
"internalType": "contract IFastBridgeReceiver",
13+
"name": "_fastBridgeReceiver",
14+
"type": "address"
15+
}
16+
],
17+
"stateMutability": "nonpayable",
18+
"type": "constructor"
19+
},
20+
{
21+
"anonymous": false,
22+
"inputs": [
23+
{
24+
"indexed": false,
25+
"internalType": "address",
26+
"name": "target",
27+
"type": "address"
28+
},
29+
{
30+
"indexed": false,
31+
"internalType": "bytes32",
32+
"name": "messageHash",
33+
"type": "bytes32"
34+
},
35+
{
36+
"indexed": false,
37+
"internalType": "bytes",
38+
"name": "messagePreImage",
39+
"type": "bytes"
40+
}
41+
],
42+
"name": "OutboxMessage",
43+
"type": "event"
44+
},
45+
{
46+
"inputs": [
47+
{
48+
"internalType": "address",
49+
"name": "_receiver",
50+
"type": "address"
51+
},
52+
{
53+
"internalType": "bytes",
54+
"name": "_calldata",
55+
"type": "bytes"
56+
}
57+
],
58+
"name": "sendFast",
59+
"outputs": [],
60+
"stateMutability": "nonpayable",
61+
"type": "function"
62+
}
63+
],
64+
"transactionHash": "0xba45e898056c0f6c1398ed4c41ebd7cbff83b9a9bd2cff11326980d05a8b2d94",
65+
"receipt": {
66+
"to": null,
67+
"from": "0x3b434e0D2a6C7F53d5C556D7BAeE8942c351Cf1a",
68+
"contractAddress": "0xefA86cB132B608a959621A657f50173370791634",
69+
"transactionIndex": 0,
70+
"gasUsed": "2285803",
71+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
72+
"blockHash": "0xd18059ef07d36d8e57c7dce859c3f4879583b87cb6a39b1576e2b28d8d21258d",
73+
"transactionHash": "0xba45e898056c0f6c1398ed4c41ebd7cbff83b9a9bd2cff11326980d05a8b2d94",
74+
"logs": [],
75+
"blockNumber": 9322964,
76+
"cumulativeGasUsed": "115523",
77+
"status": 1,
78+
"byzantium": true
79+
},
80+
"args": [
81+
"0xa4bdf6D5c291e6c5f3b9b75764cFcaF0EF7e7AB9",
82+
"0xB520c1bA7e27723Cb9b96b5ab759269De243a69B"
83+
],
84+
"numDeployments": 1,
85+
"solcInputHash": "404f378731df3b59bdbdc6b6946fcc1d",
86+
"metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract ISafeBridge\",\"name\":\"_safebridge\",\"type\":\"address\"},{\"internalType\":\"contract IFastBridgeReceiver\",\"name\":\"_fastBridgeReceiver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"messagePreImage\",\"type\":\"bytes\"}],\"name\":\"OutboxMessage\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"sendFast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"sendFast(address,bytes)\":{\"params\":{\"_calldata\":\"The receiving domain encoded message data.\",\"_receiver\":\"The L1 contract address who will receive the calldata\"}}},\"version\":1},\"userdoc\":{\"events\":{\"OutboxMessage(address,bytes32,bytes)\":{\"notice\":\"The bridgers need to watch for these events and relay the messageHash on the FastBridgeReceiver.\"}},\"kind\":\"user\",\"methods\":{\"sendFast(address,bytes)\":{\"notice\":\"Sends an arbitrary message from one domain to another via the fast bridge mechanism TODO: probably needs some access control either on the sender side or the receiver side\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/bridge/FastBridgeSender.sol\":\"FastBridgeSender\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"src/bridge/FastBridgeSender.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\n/**\\n * @authors: [@shalzz]\\n * @reviewers: []\\n * @auditors: []\\n * @bounties: []\\n * @deployments: []\\n */\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./interfaces/ISafeBridge.sol\\\";\\nimport \\\"./interfaces/IFastBridgeSender.sol\\\";\\nimport \\\"./interfaces/IFastBridgeReceiver.sol\\\";\\n\\ncontract FastBridgeSender is IFastBridgeSender {\\n ISafeBridge safebridge;\\n IFastBridgeReceiver fastBridgeReceiver;\\n\\n /**\\n * The bridgers need to watch for these events and\\n * relay the messageHash on the FastBridgeReceiver.\\n */\\n event OutboxMessage(address target, bytes32 messageHash, bytes messagePreImage);\\n\\n constructor(ISafeBridge _safebridge, IFastBridgeReceiver _fastBridgeReceiver) {\\n safebridge = _safebridge;\\n fastBridgeReceiver = _fastBridgeReceiver;\\n }\\n\\n /**\\n * Sends an arbitrary message from one domain to another\\n * via the fast bridge mechanism\\n *\\n * TODO: probably needs some access control either on the sender side\\n * or the receiver side\\n *\\n * @param _receiver The L1 contract address who will receive the calldata\\n * @param _calldata The receiving domain encoded message data.\\n */\\n function sendFast(address _receiver, bytes memory _calldata) external {\\n // Encode the receiver address with the function signature + arguments i.e calldata\\n bytes memory encodedData = abi.encode(_receiver, _calldata);\\n\\n emit OutboxMessage(_receiver, keccak256(encodedData), encodedData);\\n\\n // The safe bridge sends the encoded data to the FastBridgeReceiver\\n // in order for the FastBridgeReceiver to resolve any potential\\n // challenges and then forwards the message to the actual\\n // intended recipient encoded in `data`\\n // TODO: For this encodedData needs to be wrapped into an\\n // IFastBridgeReceiver function.\\n // TODO: add access checks for this on the FastBridgeReceiver.\\n safebridge.sendCrossDomainMessage(address(fastBridgeReceiver), encodedData);\\n }\\n}\\n\",\"keccak256\":\"0x13fede57f3c5a6940cd98a003ed91592e9c5041b9c636a0c6199ee6136e6e0e1\",\"license\":\"MIT\"},\"src/bridge/interfaces/IFastBridgeReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IFastBridgeReceiver {\\n function claim(bytes32 _messageHash) external payable;\\n\\n function verifyAndRelay(bytes32 _messageHash, bytes memory _calldata) external;\\n\\n function withdrawClaimDeposit(bytes32 _messageHash) external;\\n\\n function claimDeposit() external view returns (uint256 amount);\\n}\\n\",\"keccak256\":\"0x1d7f6a6ed2c2b88f51833cba6091c57a43af2915a265395ad11aad08b1f7285d\",\"license\":\"MIT\"},\"src/bridge/interfaces/IFastBridgeSender.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface IFastBridgeSender {\\n /**\\n * Sends an arbitrary message from one domain to another\\n * via the fast bridge mechanism\\n *\\n * TODO: probably needs some access control either on the sender side\\n * or the receiver side\\n *\\n * @param _receiver The L1 contract address who will receive the calldata\\n * @param _calldata The receiving domain encoded message data.\\n */\\n function sendFast(address _receiver, bytes memory _calldata) external;\\n}\\n\",\"keccak256\":\"0xcbf3e9b5e153940b73ab5f09469eaf2fb24a1effac83c3786b27f785c325ff2e\",\"license\":\"MIT\"},\"src/bridge/interfaces/ISafeBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface ISafeBridge {\\n /**\\n * Sends an arbitrary message from one domain to another.\\n *\\n * @param _receiver The L1 contract address who will receive the calldata\\n * @param _calldata The L2 encoded message data.\\n * @return Unique id to track the message request/transaction.\\n */\\n function sendCrossDomainMessage(address _receiver, bytes memory _calldata) external virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x6c9485fb8c7d85a6946f1d4693a44fa4bfc52ce16a504f064b03c9f77a1687c4\",\"license\":\"MIT\"}},\"version\":1}",
87+
"bytecode": "0x608060405234801561001057600080fd5b506040516103cb3803806103cb83398101604081905261002f91610078565b600080546001600160a01b039384166001600160a01b031991821617909155600180549290931691161790556100b2565b6001600160a01b038116811461007557600080fd5b50565b6000806040838503121561008b57600080fd5b825161009681610060565b60208401519092506100a781610060565b809150509250929050565b61030a806100c16000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806398ec20ec14610030575b600080fd5b61004361003e366004610142565b610045565b005b6000828260405160200161005a92919061025f565b60405160208183030381529060405290507f3e699139e0a8115e8de390569fc57ce0b665e5523f19a6d74007da1eb8681e31838280519060200120836040516100a59392919061028b565b60405180910390a160005460015460405163c249b6c160e01b81526001600160a01b039283169263c249b6c1926100e392911690859060040161025f565b6020604051808303816000875af1158015610102573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012691906102bb565b50505050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561015557600080fd5b82356001600160a01b038116811461016c57600080fd5b9150602083013567ffffffffffffffff8082111561018957600080fd5b818501915085601f83011261019d57600080fd5b8135818111156101af576101af61012c565b604051601f8201601f19908116603f011681019083821181831017156101d7576101d761012c565b816040528281528860208487010111156101f057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000815180845260005b818110156102385760208185018101518683018201520161021c565b8181111561024a576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061028390830184610212565b949350505050565b60018060a01b03841681528260208201526060604082015260006102b26060830184610212565b95945050505050565b6000602082840312156102cd57600080fd5b505191905056fea2646970667358221220f36cb7b79fa35133f53c12e670af146d0fe08da199d1101ed29baa56342edace64736f6c634300080a0033",
88+
"deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c806398ec20ec14610030575b600080fd5b61004361003e366004610142565b610045565b005b6000828260405160200161005a92919061025f565b60405160208183030381529060405290507f3e699139e0a8115e8de390569fc57ce0b665e5523f19a6d74007da1eb8681e31838280519060200120836040516100a59392919061028b565b60405180910390a160005460015460405163c249b6c160e01b81526001600160a01b039283169263c249b6c1926100e392911690859060040161025f565b6020604051808303816000875af1158015610102573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012691906102bb565b50505050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561015557600080fd5b82356001600160a01b038116811461016c57600080fd5b9150602083013567ffffffffffffffff8082111561018957600080fd5b818501915085601f83011261019d57600080fd5b8135818111156101af576101af61012c565b604051601f8201601f19908116603f011681019083821181831017156101d7576101d761012c565b816040528281528860208487010111156101f057600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000815180845260005b818110156102385760208185018101518683018201520161021c565b8181111561024a576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061028390830184610212565b949350505050565b60018060a01b03841681528260208201526060604082015260006102b26060830184610212565b95945050505050565b6000602082840312156102cd57600080fd5b505191905056fea2646970667358221220f36cb7b79fa35133f53c12e670af146d0fe08da199d1101ed29baa56342edace64736f6c634300080a0033",
89+
"devdoc": {
90+
"kind": "dev",
91+
"methods": {
92+
"sendFast(address,bytes)": {
93+
"params": {
94+
"_calldata": "The receiving domain encoded message data.",
95+
"_receiver": "The L1 contract address who will receive the calldata"
96+
}
97+
}
98+
},
99+
"version": 1
100+
},
101+
"userdoc": {
102+
"events": {
103+
"OutboxMessage(address,bytes32,bytes)": {
104+
"notice": "The bridgers need to watch for these events and relay the messageHash on the FastBridgeReceiver."
105+
}
106+
},
107+
"kind": "user",
108+
"methods": {
109+
"sendFast(address,bytes)": {
110+
"notice": "Sends an arbitrary message from one domain to another via the fast bridge mechanism TODO: probably needs some access control either on the sender side or the receiver side"
111+
}
112+
},
113+
"version": 1
114+
},
115+
"storageLayout": {
116+
"storage": [
117+
{
118+
"astId": 7557,
119+
"contract": "src/bridge/FastBridgeSender.sol:FastBridgeSender",
120+
"label": "safebridge",
121+
"offset": 0,
122+
"slot": "0",
123+
"type": "t_contract(ISafeBridge)7766"
124+
},
125+
{
126+
"astId": 7560,
127+
"contract": "src/bridge/FastBridgeSender.sol:FastBridgeSender",
128+
"label": "fastBridgeReceiver",
129+
"offset": 0,
130+
"slot": "1",
131+
"type": "t_contract(IFastBridgeReceiver)7742"
132+
}
133+
],
134+
"types": {
135+
"t_contract(IFastBridgeReceiver)7742": {
136+
"encoding": "inplace",
137+
"label": "contract IFastBridgeReceiver",
138+
"numberOfBytes": "20"
139+
},
140+
"t_contract(ISafeBridge)7766": {
141+
"encoding": "inplace",
142+
"label": "contract ISafeBridge",
143+
"numberOfBytes": "20"
144+
}
145+
}
146+
}
147+
}

0 commit comments

Comments
 (0)