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

Deployment instructions #53

Merged
merged 12 commits into from
Nov 14, 2023
27 changes: 19 additions & 8 deletions .env-sample
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
## RPC endpoint
BASECHAIN_RPC=""

## Deployer key used for deploying creator or creating token bridge
BASECHAIN_DEPLOYER_KEY=""

## WETH address on the basechain. It will be set and used in the TokenBridgeCreator
BASECHAIN_WETH=""

## Gas limit for deploying child chain factory needs to be provided to the TokenBridgeCreator when templates are set.
## If this param is not provided then gas limit will be estimated using SDK from child chain (specified by ORBIT_RPC and ROLLUP_ADDRESS)
GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT=6000000

## Contract verification
ARBISCAN_API_KEY=""

### Vars for creating token bridge from existing TokenBridgeCreator
## Rollup on top of which token bridge will be created
ROLLUP_ADDRESS=""
ORBIT_RPC=""
ROLLUP_OWNER=""
L1_TOKEN_BRIDGE_CREATOR=""
# needed for verification
L1_RETRYABLE_SENDER=""

## RPC endpoints
BASECHAIN_RPC=""
ORBIT_RPC=""

## Deployer key used for deploying creator and creating token bridge
BASECHAIN_DEPLOYER_KEY=""
L1_RETRYABLE_SENDER=""
25 changes: 25 additions & 0 deletions .env.arb1.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## RPC endpoint
BASECHAIN_RPC="https://arb1.arbitrum.io/rpc"

## Deployer key used for deploying creator or creating token bridge
BASECHAIN_DEPLOYER_KEY=""

## WETH address on the basechain. It will be set and used in the TokenBridgeCreator
BASECHAIN_WETH="0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"

## Gas limit for deploying child chain factory needs to be provided to the TokenBridgeCreator when templates are set.
## If this param is not provided then gas limit will be estimated using SDK from child chain (specified by ORBIT_RPC and ROLLUP_ADDRESS)
GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT=6000000

## Contract verification
ARBISCAN_API_KEY=""


### Vars for creating token bridge from existing TokenBridgeCreator
## Rollup on top of which token bridge will be created
# ROLLUP_ADDRESS=""
# ORBIT_RPC=""
# ROLLUP_OWNER=""
# L1_TOKEN_BRIDGE_CREATOR=""
# # needed for verification
# L1_RETRYABLE_SENDER=""
74 changes: 74 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# How to deploy RollupCreator and TokenBridgeCreator?

## RollupCreator
RollupCreator is in nitro-contracts repo
```
cd nitro-contracts
```

Checkout target code, ie.
```
git checkout v1.1.0
```

Install dependencies and build
```
yarn install
yarn build
```

Populate .env
```
DEVNET_PRIVKEY or MAINNET_PRIVKEY
ARBISCAN_API_KEY
```

Finally deploy it, using `--network` flag to specify network.

Ie. to deploy to Arbitrum Sepolia
```
yarn run deploy-factory --network arbSepolia
```

To deploy to Arbitrum One
```
yarn run deploy-factory --network arb1
```

Script output will contain all deployed addresses.


## TokenBridgeCreator
Checkout target code, install dependencies and build
```
cd token-bridge-contracts
yarn install
yarn build
```


Populate .env
```
BASECHAIN_RPC
BASECHAIN_DEPLOYER_KEY
BASECHAIN_WETH
GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT
ARBISCAN_API_KEY
```

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`.


Finally, deploy token bridge creator. Target chain is defined by `BASECHAIN_RPC` env var (no need to provide `--network` flag).
```
yarn run deploy:token-bridge-creator
```

Script outputs `L1TokenBridgeCreator` and `L1TokenBridgeRetryableSender` addresses. All deployed addresses can be obtained through `L1TokenBridgeCreator` contract.


## Ownership
These contracts will be owned by deployer:
- RollupCreator (owner can set templates)
- L1AtomicTokenBridgeCreator (owner can set templates)
- ProxyAdmin of L1AtomicTokenBridgeCreator and L1TokenBridgeRetryableSender (owner can do upgrades)
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
"test:e2e:local-env": "yarn hardhat test test-e2e/*",
"test:storage": "./scripts/storage_layout_test.bash",
"deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts",
"deploy:goerli:token-bridge-creator": "ts-node ./scripts/goerli-deployment/deployTokenBridgeCreator.ts",
"create:goerli:token-bridge": "ts-node ./scripts/goerli-deployment/createTokenBridge.ts",
"deploy:token-bridge-creator": "ts-node ./scripts/deployment/deployTokenBridgeCreator.ts",
"create:token-bridge": "ts-node ./scripts/deployment/createTokenBridge.ts",
"test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts",
"typechain": "hardhat typechain",
"deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet",
Expand Down
17 changes: 9 additions & 8 deletions scripts/atomicTokenBridgeDeployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,18 @@ export const createTokenBridge = async (
const l2ProxyAdmin =
await l1TokenBridgeCreator.getCanonicalL2ProxyAdminAddress(chainId)

const l1Multicall = await l1TokenBridgeCreator.l1Multicall()
const l2Multicall = await l1TokenBridgeCreator.getCanonicalL2Multicall(
chainId
)

return {
l1Router,
l1StandardGateway,
l1CustomGateway,
l1WethGateway,
l1ProxyAdmin,
l1Multicall,
l2Router,
l2StandardGateway: l2StandardGateway.address,
l2CustomGateway,
Expand All @@ -231,6 +237,7 @@ export const createTokenBridge = async (
l2Weth,
beaconProxyFactory,
l2ProxyAdmin,
l2Multicall
}
}

Expand All @@ -243,8 +250,8 @@ export const createTokenBridge = async (
*/
export const deployL1TokenBridgeCreator = async (
l1Deployer: Signer,
l2Provider: ethers.providers.Provider,
l1WethAddress: string,
gasLimitForL2FactoryDeployment: BigNumber,
verifyContracts: boolean = false
) => {
/// deploy creator behind proxy
Expand Down Expand Up @@ -383,12 +390,6 @@ export const deployL1TokenBridgeCreator = async (
const l1Multicall = await new Multicall2__factory(l1Deployer).deploy()
await l1Multicall.deployed()

//// run retryable estimate for deploying L2 factory
const deployFactoryGasParams = await getEstimateForDeployingFactory(
l1Deployer,
l2Provider
)

await (
await l1TokenBridgeCreator.setTemplates(
l1Templates,
Expand All @@ -400,7 +401,7 @@ export const deployL1TokenBridgeCreator = async (
l2WethAddressOnL1.address,
l1WethAddress,
l1Multicall.address,
deployFactoryGasParams.gasLimit
gasLimitForL2FactoryDeployment
)
).wait()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const envVars = {
* @param l2Url
* @returns
*/
export const createTokenBridgeOnGoerli = async () => {
export const createTokenBridgeOnTargetChain = async () => {
if (envVars.rollupAddress == undefined)
throw new Error('Missing ROLLUP_ADDRESS in env vars')
if (envVars.rollupOwner == undefined)
Expand All @@ -51,7 +51,7 @@ export const createTokenBridgeOnGoerli = async () => {
const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey)
const l2Provider = new JsonRpcProvider(envVars.childChainRpc)

const { l1Network, l2Network: corel2Network } = await registerGoerliNetworks(
const { l1Network, l2Network: corel2Network } = await registerNetworks(
l1Provider,
l2Provider,
envVars.rollupAddress
Expand All @@ -77,15 +77,15 @@ export const createTokenBridgeOnGoerli = async () => {
l1CustomGateway: deployedContracts.l1CustomGateway,
l1ERC20Gateway: deployedContracts.l1StandardGateway,
l1GatewayRouter: deployedContracts.l1Router,
l1MultiCall: '',
l1MultiCall: deployedContracts.l1Multicall,
l1ProxyAdmin: deployedContracts.l1ProxyAdmin,
l1Weth: deployedContracts.l1Weth,
l1WethGateway: deployedContracts.l1WethGateway,

l2CustomGateway: deployedContracts.l2CustomGateway,
l2ERC20Gateway: deployedContracts.l2StandardGateway,
l2GatewayRouter: deployedContracts.l2Router,
l2Multicall: '',
l2Multicall: deployedContracts.l2Multicall,
l2ProxyAdmin: deployedContracts.l2ProxyAdmin,
l2Weth: deployedContracts.l2Weth,
l2WethGateway: deployedContracts.l2WethGateway,
Expand All @@ -98,7 +98,7 @@ export const createTokenBridgeOnGoerli = async () => {
}
}

const registerGoerliNetworks = async (
const registerNetworks = async (
l1Provider: JsonRpcProvider,
l2Provider: JsonRpcProvider,
rollupAddress: string
Expand Down Expand Up @@ -170,7 +170,7 @@ const registerGoerliNetworks = async (
}

async function main() {
const { l1Network, l2Network } = await createTokenBridgeOnGoerli()
const { l1Network, l2Network } = await createTokenBridgeOnTargetChain()
const NETWORK_FILE = 'network.json'
fs.writeFileSync(
NETWORK_FILE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk'
import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory'
import {
deployL1TokenBridgeCreator,
getEstimateForDeployingFactory,
getSigner,
} from '../atomicTokenBridgeDeployer'
import dotenv from 'dotenv'
import { BigNumber } from 'ethers'

dotenv.config()

export const envVars = {
baseChainRpc: process.env['BASECHAIN_RPC'] as string,
baseChainDeployerKey: process.env['BASECHAIN_DEPLOYER_KEY'] as string,
childChainRpc: process.env['ORBIT_RPC'] as string,
baseChainWeth: process.env['BASECHAIN_WETH'] as string,
rollupAddress: process.env['ROLLUP_ADDRESS'] as string,
gasLimitForL2FactoryDeployment:
process.env['GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT'],
}

const ARB_GOERLI_WETH = '0xEe01c0CD76354C383B8c7B4e65EA88D00B06f36f'

/**
* Steps:
* - read network info from local container and register networks
Expand All @@ -30,28 +34,58 @@ const ARB_GOERLI_WETH = '0xEe01c0CD76354C383B8c7B4e65EA88D00B06f36f'
* @param l2Url
* @returns
*/
export const deployTokenBridgeCreator = async (rollupAddress: string) => {
if (envVars.baseChainRpc == undefined)
export const deployTokenBridgeCreator = async () => {
if (!envVars.baseChainRpc) {
throw new Error('Missing BASECHAIN_RPC in env vars')
if (envVars.baseChainDeployerKey == undefined)
}
if (!envVars.baseChainDeployerKey) {
throw new Error('Missing BASECHAIN_DEPLOYER_KEY in env vars')
if (envVars.childChainRpc == undefined)
throw new Error('Missing ORBIT_RPC in env vars')
}
if (!envVars.baseChainWeth) {
throw new Error('Missing BASECHAIN_WETH in env vars')
}
if (
!(envVars.rollupAddress && envVars.childChainRpc) &&
!envVars.gasLimitForL2FactoryDeployment
) {
throw new Error(
'Either GAS_LIMIT_FOR_L2_FACTORY_DEPLOYMENT or (ROLLUP_ADDRESS and ORBIT_RPC) must be set in env vars'
gvladika marked this conversation as resolved.
Show resolved Hide resolved
)
}

const l1Provider = new JsonRpcProvider(envVars.baseChainRpc)
const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey)
const l2Provider = new JsonRpcProvider(envVars.childChainRpc)

await registerGoerliNetworks(l1Provider, l2Provider, rollupAddress)
// get gas limit for L2 factory deployment from env var or do retryable estimate
let gasLimitForL2FactoryDeployment: BigNumber
if (envVars.gasLimitForL2FactoryDeployment) {
gasLimitForL2FactoryDeployment = BigNumber.from(
envVars.gasLimitForL2FactoryDeployment
)
} else {
const l2Provider = new JsonRpcProvider(envVars.childChainRpc)
await registerNetworks(l1Provider, l2Provider, envVars.rollupAddress)
//// run retryable estimate for deploying L2 factory
const deployFactoryGasParams = await getEstimateForDeployingFactory(
l1Deployer,
l2Provider
)
gasLimitForL2FactoryDeployment = deployFactoryGasParams.gasLimit
}

// deploy L1 creator and set templates
const { l1TokenBridgeCreator, retryableSender } =
await deployL1TokenBridgeCreator(l1Deployer, l2Provider, ARB_GOERLI_WETH, true)
await deployL1TokenBridgeCreator(
l1Deployer,
envVars.baseChainWeth,
gasLimitForL2FactoryDeployment,
true
)

return { l1TokenBridgeCreator, retryableSender }
}

const registerGoerliNetworks = async (
const registerNetworks = async (
l1Provider: JsonRpcProvider,
l2Provider: JsonRpcProvider,
rollupAddress: string
Expand Down Expand Up @@ -123,10 +157,9 @@ const registerGoerliNetworks = async (
}

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

console.log('Token bridge creator deployed!')
console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address)
Expand Down
Loading