Skip to content
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "orbit-setup-script",
"dependencies": {
"@arbitrum/nitro-contracts": "^1.1.1",
"@arbitrum/orbit-sdk": "^0.8.0",
"@arbitrum/orbit-sdk": "^0.9.0",
"@arbitrum/token-bridge-contracts": "^1.2.1",
"viem": "^1.20.0"
},
Expand Down
30 changes: 16 additions & 14 deletions scripts/createTokenBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,30 +91,32 @@ async function getNativeToken({
* @returns
*/
export const createNewTokenBridge = async (
baseChainRpc: string,
baseChainDeployerKey: string,
childChainRpc: string,
parentChainRpc: string,
parentChainDeployerKey: string,
orbitChainRpc: string,
rollupAddress: string
) => {
const l1Provider = new JsonRpcProvider(baseChainRpc)
const l1Provider = new JsonRpcProvider(parentChainRpc)
const l1NetworkInfo = await l1Provider.getNetwork()

const l2Provider = new JsonRpcProvider(childChainRpc)
const l2Provider = new JsonRpcProvider(orbitChainRpc)
const l2NetworkInfo = await l2Provider.getNetwork()

const deployer = privateKeyToAccount(sanitizePrivateKey(baseChainDeployerKey))
const deployer = privateKeyToAccount(
sanitizePrivateKey(parentChainDeployerKey)
)
const rollup = RollupAdminLogic__factory.connect(rollupAddress, l1Provider)

const parentChainPublicClient = createPublicClientFromChainInfo({
id: l1NetworkInfo.chainId,
name: l1NetworkInfo.name,
rpcUrl: baseChainRpc,
rpcUrl: parentChainRpc,
})

const orbitChainPublicClient = createPublicClientFromChainInfo({
id: l2NetworkInfo.chainId,
name: l2NetworkInfo.name,
rpcUrl: childChainRpc,
rpcUrl: orbitChainRpc,
})

const nativeToken = await getNativeToken({
Expand Down Expand Up @@ -323,17 +325,17 @@ export const createNewTokenBridge = async (
}

export const createERC20Bridge = async (
baseChainRpc: string,
baseChainDeployerKey: string,
childChainRpc: string,
parentChainRpc: string,
parentChainDeployerKey: string,
orbitChainRpc: string,
rollupAddress: string
) => {
console.log('Creating token bridge for rollup', rollupAddress)

const { l1Network, l2Network } = await createNewTokenBridge(
baseChainRpc,
baseChainDeployerKey,
childChainRpc,
parentChainRpc,
parentChainDeployerKey,
orbitChainRpc,
rollupAddress
)
const NETWORK_FILE = 'network.json'
Expand Down
273 changes: 180 additions & 93 deletions scripts/l3Configuration.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,67 @@
import { abi as ArbOwner__abi } from '@arbitrum/nitro-contracts/build/contracts/src/precompiles/ArbOwner.sol/ArbOwner.json'
import { abi as ArbGasInfo__abi } from '@arbitrum/nitro-contracts/build/contracts/src/precompiles/ArbGasInfo.sol/ArbGasInfo.json'
import { ethers } from 'ethers'
import { L3Config } from './l3ConfigType'
import fs from 'fs'
import { JsonRpcProvider } from '@ethersproject/providers'

import { createPublicClient, defineChain, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

import { arbOwnerPublicActions } from '@arbitrum/orbit-sdk'
import { arbGasInfoPublicActions } from '@arbitrum/orbit-sdk'

import { sanitizePrivateKey } from '@arbitrum/orbit-sdk/utils'

function createPublicClientFromChainInfo({
id,
name,
rpcUrl,
}: {
id: number
name: string
rpcUrl: string
}) {
const chain = defineChain({
id: id,
network: name,
name: name,
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: {
default: {
http: [rpcUrl],
},
public: {
http: [rpcUrl],
},
},
testnet: true,
})
return createPublicClient({ chain, transport: http() })
}

export async function l3Configuration(
privateKey: string,
L2_RPC_URL: string,
L3_RPC_URL: string
parentChainDeployerKey: string,
orbitChainRpc: string
) {
if (!privateKey || !L2_RPC_URL || !L3_RPC_URL) {
if (!parentChainDeployerKey || !orbitChainRpc) {
throw new Error('Required environment variable not found')
}

// Generating providers from RPCs
const L2Provider = new ethers.providers.JsonRpcProvider(L2_RPC_URL)
const L3Provider = new ethers.providers.JsonRpcProvider(L3_RPC_URL)
// Generation parent chain provider and network
const l2Provider = new JsonRpcProvider(orbitChainRpc)
const l2NetworkInfo = await l2Provider.getNetwork()

//Generating deployer signer
const deployer = privateKeyToAccount(
sanitizePrivateKey(parentChainDeployerKey)
)

// Creating the wallet and signer
const l2signer = new ethers.Wallet(privateKey).connect(L2Provider)
const l3signer = new ethers.Wallet(privateKey).connect(L3Provider)
// Creating Orbit chain client with arb owner and arb gas info extension
const orbitChainPublicClient = createPublicClientFromChainInfo({
id: l2NetworkInfo.chainId,
name: l2NetworkInfo.name,
rpcUrl: orbitChainRpc,
})
.extend(arbOwnerPublicActions)
.extend(arbGasInfoPublicActions)

// Read the JSON configuration
const configRaw = fs.readFileSync(
Expand All @@ -28,108 +70,153 @@ export async function l3Configuration(
)
const config: L3Config = JSON.parse(configRaw)

// Reading params for L3 Configuration
const minL2BaseFee = config.minL2BaseFee
const networkFeeReceiver = config.networkFeeReceiver
const infrastructureFeeCollector = config.infrastructureFeeCollector
// Reading params for Configuration
const minOrbitChainBaseFee = config.minL2BaseFee
const networkFeeReceiver = config.networkFeeReceiver as `0x${string}`
const infrastructureFeeCollector =
config.infrastructureFeeCollector as `0x${string}`
const chainOwner = config.chainOwner

// Check if the Private Key provided is the chain owner:
if (l3signer.address !== chainOwner) {
if (deployer.address !== chainOwner) {
throw new Error('The Private Key you have provided is not the chain owner')
}

// ArbOwner precompile setup
const arbOwnerABI = ArbOwner__abi

// Arb Owner precompile address
const arbOwnerAddress = '0x0000000000000000000000000000000000000070'
const ArbOwner = new ethers.Contract(arbOwnerAddress, arbOwnerABI, l3signer)

// Call the isChainOwner function and check the response
const isSignerChainOwner = await ArbOwner.isChainOwner(l3signer.address)
if (!isSignerChainOwner) {
const isOwnerInitially = await orbitChainPublicClient.arbOwnerReadContract({
functionName: 'isChainOwner',
args: [deployer.address],
})

// assert account is not already an owner
if (!isOwnerInitially) {
throw new Error('The address you have provided is not the chain owner')
}

// Set the network base fee
// Set the orbit chain base fee
console.log('Setting the Minimum Base Fee for the Orbit chain')
const tx = await ArbOwner.setMinimumL2BaseFee(minL2BaseFee)

// Wait for the transaction to be mined
const receipt = await tx.wait()
console.log(
`Minimum Base Fee is set on the block number ${await receipt.blockNumber} on the Orbit chain`
)

// Check the status of the transaction: 1 is successful, 0 is failure
if (receipt.status === 0) {
throw new Error('Transaction failed, could not set the Minimum base fee')
const setMinimumBaseFeeTransactionRequest =
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setMinimumL2BaseFee',
args: [BigInt(minOrbitChainBaseFee)],
upgradeExecutor: false,
account: deployer.address,
})
// submit tx to update minimum child chain base fee
const setMinimumBaseFeeTransactionHash =
await orbitChainPublicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(
setMinimumBaseFeeTransactionRequest
),
})
await orbitChainPublicClient.waitForTransactionReceipt({
hash: setMinimumBaseFeeTransactionHash,
})
// Get the updated minimum basefee on orbit chain from arbGasInfo precompile on child chain
const minOrbitChainBaseFeeRead =
await orbitChainPublicClient.arbGasInfoReadContract({
functionName: 'getMinimumGasPrice',
})
// Check if minimum basefee param is set correctly on orbit chain
if (Number(minOrbitChainBaseFeeRead) === minOrbitChainBaseFee) {
console.log('Minimum L3 base fee is set')
} else {
throw new Error('Failed to set Minimum L3 base fee')
}

// Set the network fee receiver
console.log('Setting the network fee receiver for the Orbit chain')
const tx2 = await ArbOwner.setNetworkFeeAccount(networkFeeReceiver)

// Wait for the transaction to be mined
const receipt2 = await tx2.wait()
console.log(
`network fee receiver is set on the block number ${await receipt2.blockNumber} on the Orbit chain`
)

// Check the status of the transaction: 1 is successful, 0 is failure
if (receipt2.status === 0) {
// Set the network fee account
const setNetworkFeeAccountTransactionRequest =
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setNetworkFeeAccount',
args: [networkFeeReceiver],
upgradeExecutor: false,
account: deployer.address,
})

// submit tx to update infra fee receiver
const setNetworkFeeAccountTransactionHash =
await orbitChainPublicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(
setNetworkFeeAccountTransactionRequest
),
})
await orbitChainPublicClient.waitForTransactionReceipt({
hash: setNetworkFeeAccountTransactionHash,
})

// check if network fee account is updated correctly
const networkFeeRecieverAccount =
await orbitChainPublicClient.arbOwnerReadContract({
functionName: 'getNetworkFeeAccount',
})

if (networkFeeRecieverAccount === networkFeeReceiver) {
console.log('network fee receiver is set')
} else {
throw new Error(
'network fee receiver Setting network fee receiver transaction failed'
)
}

// Set the infrastructure fee collector
console.log(
'Setting the infrastructure fee collector address for the Orbit chain'
)
const tx3 = await ArbOwner.setInfraFeeAccount(infrastructureFeeCollector)

// Wait for the transaction to be mined
const receipt3 = await tx3.wait()
console.log(
`infrastructure fee collector address is set on the block number ${await receipt3.blockNumber} on the Orbit chain`
)

// Check the status of the transaction: 1 is successful, 0 is failure
if (receipt3.status === 0) {
throw new Error(
'Setting Set the infrastructure fee collector transaction failed'
)
// Set the infra fee account
const setInfraFeeAccountTransactionRequest =
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setInfraFeeAccount',
args: [infrastructureFeeCollector],
upgradeExecutor: false,
account: deployer.address,
})

// submit tx to update infra fee receiver
const setInfraFeeAccountTransactionHash =
await orbitChainPublicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(
setInfraFeeAccountTransactionRequest
),
})
await orbitChainPublicClient.waitForTransactionReceipt({
hash: setInfraFeeAccountTransactionHash,
})
const infraFeeReceiver = await orbitChainPublicClient.arbOwnerReadContract({
functionName: 'getInfraFeeAccount',
})

// check if infra fee account is updated correctly
if (infraFeeReceiver === infrastructureFeeCollector) {
console.log('Infra Fee Collector changed successfully')
} else {
throw new Error('Infra Fee Collector Setting transaction failed')
}

// Setting L1 basefee on L3
const arbGasInfoAbi = ArbGasInfo__abi
const arbGasInfoAddress = '0x000000000000000000000000000000000000006c'
const ArbOGasInfo = new ethers.Contract(
arbGasInfoAddress,
arbGasInfoAbi,
l2signer
)

// Setting L1 basefee estimate on L3
console.log('Getting L1 base fee estimate')
const l1BaseFeeEstimate = await ArbOGasInfo.getL1BaseFeeEstimate()
console.log(`L1 Base Fee estimate on L2 is ${l1BaseFeeEstimate.toNumber()}`)
const l2Basefee = await L2Provider.getGasPrice()
const totalGasPrice = await l1BaseFeeEstimate.add(l2Basefee)
console.log(`Setting L1 base fee estimate on L3 to ${totalGasPrice}`)
const tx4 = await ArbOwner.setL1PricePerUnit(totalGasPrice)

// Wait for the transaction to be mined
const receipt4 = await tx4.wait()
console.log(
`L1 base fee estimate is set on the block number ${await receipt4.blockNumber} on the Orbit chain`
const l1BaseFeeEstimate = await orbitChainPublicClient.arbGasInfoReadContract(
{
functionName: 'getL1BaseFeeEstimate',
}
)
console.log(`L1 Base Fee estimate on L2 is ${Number(l1BaseFeeEstimate)}`)
const l2Basefee = await l2Provider.getGasPrice()
const totalGasPrice = l2Basefee.add(l1BaseFeeEstimate)
console.log(`Setting L1 base fee estimate on L3 to ${totalGasPrice}`)

// Check the status of the transaction: 1 is successful, 0 is failure
if (receipt4.status === 0) {
throw new Error('Base Fee Setting failed')
}

console.log('All things done! Enjoy your Orbit chain. LFG 🚀🚀🚀🚀')
const setL1PricePerUnitTransactionRequest =
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setL1PricePerUnit',
args: [BigInt(totalGasPrice.toString())],
upgradeExecutor: false,
account: deployer.address,
})

// setting setL1PricePerUnit
const setL1PricePerUnitTransactionHash =
await orbitChainPublicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(
setL1PricePerUnitTransactionRequest
),
})
await orbitChainPublicClient.waitForTransactionReceipt({
hash: setL1PricePerUnitTransactionHash,
})
}
Loading