Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
254 changes: 163 additions & 91 deletions scripts/l3Configuration.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,65 @@
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({
Comment thread
GreatSoshiant marked this conversation as resolved.
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
baseChainDeployerKey: string,
childChainRpc: string
Comment thread
GreatSoshiant marked this conversation as resolved.
Outdated
) {
if (!privateKey || !L2_RPC_URL || !L3_RPC_URL) {
if (!baseChainDeployerKey || !childChainRpc) {
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(childChainRpc)
const l2NetworkInfo = await l2Provider.getNetwork()

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

// 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: childChainRpc,
})
.extend(arbOwnerPublicActions)
.extend(arbGasInfoPublicActions)

// Read the JSON configuration
const configRaw = fs.readFileSync(
Expand All @@ -30,106 +70,138 @@ export async function l3Configuration(

// Reading params for L3 Configuration
const minL2BaseFee = config.minL2BaseFee
Comment thread
GreatSoshiant marked this conversation as resolved.
Outdated
const networkFeeReceiver = config.networkFeeReceiver
const infrastructureFeeCollector = config.infrastructureFeeCollector
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 child 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 transactionRequest1 =
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setMinimumL2BaseFee',
args: [BigInt(minL2BaseFee)],
upgradeExecutor: false,
account: deployer.address,
})
// submit tx to update minimum child chain base fee
const txHash1 = await orbitChainPublicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(transactionRequest1),
})
await orbitChainPublicClient.waitForTransactionReceipt({
hash: txHash1,
})
// Get the updated minL2Basefee from arbGasInfo precompile on child chain
const minL3BaseFee = await orbitChainPublicClient.arbGasInfoReadContract({
functionName: 'getMinimumGasPrice',
})
// Check if minL2BaseFee param is set correctly
if (Number(minL3BaseFee) === minL2BaseFee) {
Comment thread
GreatSoshiant marked this conversation as resolved.
Outdated
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 transactionRequest2 =
Comment thread
GreatSoshiant marked this conversation as resolved.
Outdated
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setNetworkFeeAccount',
args: [networkFeeReceiver],
upgradeExecutor: false,
account: deployer.address,
})

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

// 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 transactionRequest3 =
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setInfraFeeAccount',
args: [infrastructureFeeCollector],
upgradeExecutor: false,
account: deployer.address,
})

// submit tx to update infra fee receiver
const txHash3 = await orbitChainPublicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(transactionRequest3),
})
await orbitChainPublicClient.waitForTransactionReceipt({
hash: txHash3,
})
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 transactionRequest4 =
await orbitChainPublicClient.arbOwnerPrepareTransactionRequest({
functionName: 'setL1PricePerUnit',
args: [BigInt(totalGasPrice.toString())],
upgradeExecutor: false,
account: deployer.address,
})

// setting setL1PricePerUnit
const txHash4 = await orbitChainPublicClient.sendRawTransaction({
serializedTransaction: await deployer.signTransaction(transactionRequest4),
})
await orbitChainPublicClient.waitForTransactionReceipt({
hash: txHash4,
})
}
6 changes: 3 additions & 3 deletions scripts/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ async function main() {
console.log(
'Running l3Configuration script to configure your Orbit chain 📝📝📝📝📝'
)
await l3Configuration(privateKey, L2_RPC_URL, L3_RPC_URL)
await l3Configuration(privateKey, L3_RPC_URL)
rs.l3config = true
}
////////////////////////////////
Expand All @@ -177,8 +177,9 @@ async function main() {
console.log(
'Transferring ownership on L3, from rollup owner to upgrade executor 🔃🔃🔃'
)
await transferOwner(privateKey, L2Provider, L3Provider)
await transferOwner(privateKey, L2Provider, L3Provider, L3_RPC_URL)
rs.transferOwnership = true
console.log('All things done! Enjoy your Orbit chain. LFG 🚀🚀🚀🚀')
}
} catch (error) {
console.error('Error occurred:', error)
Expand All @@ -189,7 +190,6 @@ async function main() {
)
}
}

// Run the script
main().catch(error => {
console.error(error)
Expand Down
Loading