Skip to content

Commit 41df4f4

Browse files
authored
Merge pull request #53 from OffchainLabs/deploy-instructions
Deployment instructions
2 parents 8aa70ea + a91d7fd commit 41df4f4

File tree

8 files changed

+198
-41
lines changed

8 files changed

+198
-41
lines changed

.env-sample

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1+
## RPC endpoint
2+
BASECHAIN_RPC=""
3+
4+
## Deployer key used for deploying creator or creating token bridge
5+
BASECHAIN_DEPLOYER_KEY=""
6+
7+
## WETH address on the basechain. It will be set and used in the TokenBridgeCreator
8+
BASECHAIN_WETH=""
9+
10+
## Gas limit for deploying child chain factory needs to be provided to the TokenBridgeCreator when templates are set.
11+
## If this param is not provided then gas limit will be estimated using SDK from child chain (specified by ORBIT_RPC and ROLLUP_ADDRESS)
12+
GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT=6000000
13+
14+
## Contract verification
15+
ARBISCAN_API_KEY=""
16+
17+
### Vars for creating token bridge from existing TokenBridgeCreator
118
## Rollup on top of which token bridge will be created
219
ROLLUP_ADDRESS=""
20+
ORBIT_RPC=""
321
ROLLUP_OWNER=""
422
L1_TOKEN_BRIDGE_CREATOR=""
523
# needed for verification
6-
L1_RETRYABLE_SENDER=""
7-
8-
## RPC endpoints
9-
BASECHAIN_RPC=""
10-
ORBIT_RPC=""
11-
12-
## Deployer key used for deploying creator and creating token bridge
13-
BASECHAIN_DEPLOYER_KEY=""
24+
L1_RETRYABLE_SENDER=""

.env.arb1.sample

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## RPC endpoint
2+
BASECHAIN_RPC="https://arb1.arbitrum.io/rpc"
3+
4+
## Deployer key used for deploying creator or creating token bridge
5+
BASECHAIN_DEPLOYER_KEY=""
6+
7+
## WETH address on the basechain. It will be set and used in the TokenBridgeCreator
8+
BASECHAIN_WETH="0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
9+
10+
## Gas limit for deploying child chain factory needs to be provided to the TokenBridgeCreator when templates are set.
11+
## If this param is not provided then gas limit will be estimated using SDK from child chain (specified by ORBIT_RPC and ROLLUP_ADDRESS)
12+
GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT=6000000
13+
14+
## Contract verification
15+
ARBISCAN_API_KEY=""
16+
17+
18+
### Vars for creating token bridge from existing TokenBridgeCreator
19+
## Rollup on top of which token bridge will be created
20+
# ROLLUP_ADDRESS=""
21+
# ORBIT_RPC=""
22+
# ROLLUP_OWNER=""
23+
# L1_TOKEN_BRIDGE_CREATOR=""
24+
# # needed for verification
25+
# L1_RETRYABLE_SENDER=""

docs/deployment.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# How to deploy RollupCreator and TokenBridgeCreator?
2+
3+
## RollupCreator
4+
RollupCreator is in nitro-contracts repo
5+
```
6+
cd nitro-contracts
7+
```
8+
9+
Checkout target code, ie.
10+
```
11+
git checkout v1.1.0
12+
```
13+
14+
Install dependencies and build
15+
```
16+
yarn install
17+
yarn build
18+
```
19+
20+
Populate .env
21+
```
22+
DEVNET_PRIVKEY or MAINNET_PRIVKEY
23+
ARBISCAN_API_KEY
24+
```
25+
26+
Finally deploy it, using `--network` flag to specify network.
27+
28+
Ie. to deploy to Arbitrum Sepolia
29+
```
30+
yarn run deploy-factory --network arbSepolia
31+
```
32+
33+
To deploy to Arbitrum One
34+
```
35+
yarn run deploy-factory --network arb1
36+
```
37+
38+
Script output will contain all deployed addresses.
39+
40+
41+
## TokenBridgeCreator
42+
Checkout target code, install dependencies and build
43+
```
44+
cd token-bridge-contracts
45+
yarn install
46+
yarn build
47+
```
48+
49+
50+
Populate .env
51+
```
52+
BASECHAIN_RPC
53+
BASECHAIN_DEPLOYER_KEY
54+
BASECHAIN_WETH
55+
GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT
56+
ARBISCAN_API_KEY
57+
```
58+
59+
Note: Gas limit for deploying child chain factory via retryable needs to be provided to the TokenBridgeCreator when templates are set. This value can be obtained in 2 ways - 1st is to provide `ORBIT_RPC` and `ROLLUP_ADDRESS` env vars, and script will then use Arbitrum SDK to estimate gas needed for deploying L2 factory. Other way to do it is much simpler - provide hardcoded value by setting the `GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT`. Previous deployments showed that gas needed is ~5140000. Adding a bit of buffer on top, we can set this value to `GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT=6000000`.
60+
61+
62+
Finally, deploy token bridge creator. Target chain is defined by `BASECHAIN_RPC` env var (no need to provide `--network` flag).
63+
```
64+
yarn run deploy:token-bridge-creator
65+
```
66+
67+
Script outputs `L1TokenBridgeCreator` and `L1TokenBridgeRetryableSender` addresses. All deployed addresses can be obtained through `L1TokenBridgeCreator` contract.
68+
69+
70+
## Ownership
71+
These contracts will be owned by deployer:
72+
- RollupCreator (owner can set templates)
73+
- L1AtomicTokenBridgeCreator (owner can set templates)
74+
- ProxyAdmin of L1AtomicTokenBridgeCreator and L1TokenBridgeRetryableSender (owner can do upgrades)

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
"test:e2e:local-env": "yarn hardhat test test-e2e/*",
2222
"test:storage": "./scripts/storage_layout_test.bash",
2323
"deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts",
24-
"deploy:goerli:token-bridge-creator": "ts-node ./scripts/goerli-deployment/deployTokenBridgeCreator.ts",
25-
"create:goerli:token-bridge": "ts-node ./scripts/goerli-deployment/createTokenBridge.ts",
24+
"deploy:token-bridge-creator": "ts-node ./scripts/deployment/deployTokenBridgeCreator.ts",
25+
"create:token-bridge": "ts-node ./scripts/deployment/createTokenBridge.ts",
2626
"test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts",
2727
"typechain": "hardhat typechain",
2828
"deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet",

scripts/atomicTokenBridgeDeployer.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,18 @@ export const createTokenBridge = async (
217217
const l2ProxyAdmin =
218218
await l1TokenBridgeCreator.getCanonicalL2ProxyAdminAddress(chainId)
219219

220+
const l1Multicall = await l1TokenBridgeCreator.l1Multicall()
221+
const l2Multicall = await l1TokenBridgeCreator.getCanonicalL2Multicall(
222+
chainId
223+
)
224+
220225
return {
221226
l1Router,
222227
l1StandardGateway,
223228
l1CustomGateway,
224229
l1WethGateway,
225230
l1ProxyAdmin,
231+
l1Multicall,
226232
l2Router,
227233
l2StandardGateway: l2StandardGateway.address,
228234
l2CustomGateway,
@@ -231,6 +237,7 @@ export const createTokenBridge = async (
231237
l2Weth,
232238
beaconProxyFactory,
233239
l2ProxyAdmin,
240+
l2Multicall
234241
}
235242
}
236243

@@ -243,8 +250,8 @@ export const createTokenBridge = async (
243250
*/
244251
export const deployL1TokenBridgeCreator = async (
245252
l1Deployer: Signer,
246-
l2Provider: ethers.providers.Provider,
247253
l1WethAddress: string,
254+
gasLimitForL2FactoryDeployment: BigNumber,
248255
verifyContracts: boolean = false
249256
) => {
250257
/// deploy creator behind proxy
@@ -383,12 +390,6 @@ export const deployL1TokenBridgeCreator = async (
383390
const l1Multicall = await new Multicall2__factory(l1Deployer).deploy()
384391
await l1Multicall.deployed()
385392

386-
//// run retryable estimate for deploying L2 factory
387-
const deployFactoryGasParams = await getEstimateForDeployingFactory(
388-
l1Deployer,
389-
l2Provider
390-
)
391-
392393
await (
393394
await l1TokenBridgeCreator.setTemplates(
394395
l1Templates,
@@ -400,7 +401,7 @@ export const deployL1TokenBridgeCreator = async (
400401
l2WethAddressOnL1.address,
401402
l1WethAddress,
402403
l1Multicall.address,
403-
deployFactoryGasParams.gasLimit
404+
gasLimitForL2FactoryDeployment
404405
)
405406
).wait()
406407

scripts/goerli-deployment/createTokenBridge.ts renamed to scripts/deployment/createTokenBridge.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const envVars = {
3131
* @param l2Url
3232
* @returns
3333
*/
34-
export const createTokenBridgeOnGoerli = async () => {
34+
export const createTokenBridgeOnTargetChain = async () => {
3535
if (envVars.rollupAddress == undefined)
3636
throw new Error('Missing ROLLUP_ADDRESS in env vars')
3737
if (envVars.rollupOwner == undefined)
@@ -51,7 +51,7 @@ export const createTokenBridgeOnGoerli = async () => {
5151
const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey)
5252
const l2Provider = new JsonRpcProvider(envVars.childChainRpc)
5353

54-
const { l1Network, l2Network: corel2Network } = await registerGoerliNetworks(
54+
const { l1Network, l2Network: corel2Network } = await registerNetworks(
5555
l1Provider,
5656
l2Provider,
5757
envVars.rollupAddress
@@ -77,15 +77,15 @@ export const createTokenBridgeOnGoerli = async () => {
7777
l1CustomGateway: deployedContracts.l1CustomGateway,
7878
l1ERC20Gateway: deployedContracts.l1StandardGateway,
7979
l1GatewayRouter: deployedContracts.l1Router,
80-
l1MultiCall: '',
80+
l1MultiCall: deployedContracts.l1Multicall,
8181
l1ProxyAdmin: deployedContracts.l1ProxyAdmin,
8282
l1Weth: deployedContracts.l1Weth,
8383
l1WethGateway: deployedContracts.l1WethGateway,
8484

8585
l2CustomGateway: deployedContracts.l2CustomGateway,
8686
l2ERC20Gateway: deployedContracts.l2StandardGateway,
8787
l2GatewayRouter: deployedContracts.l2Router,
88-
l2Multicall: '',
88+
l2Multicall: deployedContracts.l2Multicall,
8989
l2ProxyAdmin: deployedContracts.l2ProxyAdmin,
9090
l2Weth: deployedContracts.l2Weth,
9191
l2WethGateway: deployedContracts.l2WethGateway,
@@ -98,7 +98,7 @@ export const createTokenBridgeOnGoerli = async () => {
9898
}
9999
}
100100

101-
const registerGoerliNetworks = async (
101+
const registerNetworks = async (
102102
l1Provider: JsonRpcProvider,
103103
l2Provider: JsonRpcProvider,
104104
rollupAddress: string
@@ -170,7 +170,7 @@ const registerGoerliNetworks = async (
170170
}
171171

172172
async function main() {
173-
const { l1Network, l2Network } = await createTokenBridgeOnGoerli()
173+
const { l1Network, l2Network } = await createTokenBridgeOnTargetChain()
174174
const NETWORK_FILE = 'network.json'
175175
fs.writeFileSync(
176176
NETWORK_FILE,

scripts/goerli-deployment/deployTokenBridgeCreator.ts renamed to scripts/deployment/deployTokenBridgeCreator.ts

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@ import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk'
33
import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory'
44
import {
55
deployL1TokenBridgeCreator,
6+
getEstimateForDeployingFactory,
67
getSigner,
78
} from '../atomicTokenBridgeDeployer'
89
import dotenv from 'dotenv'
10+
import { BigNumber } from 'ethers'
911

1012
dotenv.config()
1113

1214
export const envVars = {
1315
baseChainRpc: process.env['BASECHAIN_RPC'] as string,
1416
baseChainDeployerKey: process.env['BASECHAIN_DEPLOYER_KEY'] as string,
1517
childChainRpc: process.env['ORBIT_RPC'] as string,
18+
baseChainWeth: process.env['BASECHAIN_WETH'] as string,
19+
rollupAddress: process.env['ROLLUP_ADDRESS'] as string,
20+
gasLimitForL2FactoryDeployment:
21+
process.env['GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT'],
1622
}
1723

18-
const ARB_GOERLI_WETH = '0xEe01c0CD76354C383B8c7B4e65EA88D00B06f36f'
19-
2024
/**
2125
* Steps:
2226
* - read network info from local container and register networks
@@ -30,28 +34,58 @@ const ARB_GOERLI_WETH = '0xEe01c0CD76354C383B8c7B4e65EA88D00B06f36f'
3034
* @param l2Url
3135
* @returns
3236
*/
33-
export const deployTokenBridgeCreator = async (rollupAddress: string) => {
34-
if (envVars.baseChainRpc == undefined)
37+
export const deployTokenBridgeCreator = async () => {
38+
if (!envVars.baseChainRpc) {
3539
throw new Error('Missing BASECHAIN_RPC in env vars')
36-
if (envVars.baseChainDeployerKey == undefined)
40+
}
41+
if (!envVars.baseChainDeployerKey) {
3742
throw new Error('Missing BASECHAIN_DEPLOYER_KEY in env vars')
38-
if (envVars.childChainRpc == undefined)
39-
throw new Error('Missing ORBIT_RPC in env vars')
43+
}
44+
if (!envVars.baseChainWeth) {
45+
throw new Error('Missing BASECHAIN_WETH in env vars')
46+
}
47+
if (
48+
!(envVars.rollupAddress && envVars.childChainRpc) &&
49+
!envVars.gasLimitForL2FactoryDeployment
50+
) {
51+
throw new Error(
52+
'Either GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT or (ROLLUP_ADDRESS and ORBIT_RPC) must be set in env vars'
53+
)
54+
}
4055

4156
const l1Provider = new JsonRpcProvider(envVars.baseChainRpc)
4257
const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey)
43-
const l2Provider = new JsonRpcProvider(envVars.childChainRpc)
4458

45-
await registerGoerliNetworks(l1Provider, l2Provider, rollupAddress)
59+
// get gas limit for L2 factory deployment from env var or do retryable estimate
60+
let gasLimitForL2FactoryDeployment: BigNumber
61+
if (envVars.gasLimitForL2FactoryDeployment) {
62+
gasLimitForL2FactoryDeployment = BigNumber.from(
63+
envVars.gasLimitForL2FactoryDeployment
64+
)
65+
} else {
66+
const l2Provider = new JsonRpcProvider(envVars.childChainRpc)
67+
await registerNetworks(l1Provider, l2Provider, envVars.rollupAddress)
68+
//// run retryable estimate for deploying L2 factory
69+
const deployFactoryGasParams = await getEstimateForDeployingFactory(
70+
l1Deployer,
71+
l2Provider
72+
)
73+
gasLimitForL2FactoryDeployment = deployFactoryGasParams.gasLimit
74+
}
4675

4776
// deploy L1 creator and set templates
4877
const { l1TokenBridgeCreator, retryableSender } =
49-
await deployL1TokenBridgeCreator(l1Deployer, l2Provider, ARB_GOERLI_WETH, true)
78+
await deployL1TokenBridgeCreator(
79+
l1Deployer,
80+
envVars.baseChainWeth,
81+
gasLimitForL2FactoryDeployment,
82+
true
83+
)
5084

5185
return { l1TokenBridgeCreator, retryableSender }
5286
}
5387

54-
const registerGoerliNetworks = async (
88+
const registerNetworks = async (
5589
l1Provider: JsonRpcProvider,
5690
l2Provider: JsonRpcProvider,
5791
rollupAddress: string
@@ -123,10 +157,9 @@ const registerGoerliNetworks = async (
123157
}
124158

125159
async function main() {
126-
// this is just random Orbit rollup that will be used to estimate gas needed to deploy L2 token bridge factory via retryable
127-
const rollupAddress = '0x8223bd899C6643483872ed2A7b105b2aC9C8aBEc'
160+
console.log('Deploying token bridge creator...')
128161
const { l1TokenBridgeCreator, retryableSender } =
129-
await deployTokenBridgeCreator(rollupAddress)
162+
await deployTokenBridgeCreator()
130163

131164
console.log('Token bridge creator deployed!')
132165
console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address)

0 commit comments

Comments
 (0)