Skip to content

Commit

Permalink
fix: check contract init bug
Browse files Browse the repository at this point in the history
  • Loading branch information
dghelm committed Aug 21, 2024
1 parent d3bd6a2 commit b1c2a32
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 123 deletions.
59 changes: 13 additions & 46 deletions src/commands/helper/fund-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,13 @@ export default class HelperFundContracts extends Command {
char: 'k',
description: 'Private key for funder wallet',
}),
contracts: Flags.string({
char: 'n',
default: './config-contracts.toml',
description: 'Path to config-contracts.toml file',
}),
'gateway-address': Flags.string({
char: 'g',
description: 'L1 Gateway Router or L1 ETH Gateway contract address',
}),
}

private l1Provider!: ethers.JsonRpcProvider
private l2Provider!: ethers.JsonRpcProvider
private l1Rpc!: string
private l2Rpc!: string
private l1FundingWallet!: ethers.Wallet
private l2FundingWallet!: ethers.Wallet
private fundingWallet!: ethers.Wallet
private l1ETHGateway!: string
private blockExplorers: Record<Layer, { blockExplorerURI: string }> = {
[Layer.L1]: { blockExplorerURI: '' },
Expand Down Expand Up @@ -111,23 +101,9 @@ export default class HelperFundContracts extends Command {
this.l1ETHGateway = config?.contracts?.L1_ETH_GATEWAY_PROXY_ADDR

if (flags['private-key']) {
this.l1FundingWallet = new ethers.Wallet(flags['private-key'], this.l1Provider)
this.l2FundingWallet = new ethers.Wallet(flags['private-key'], this.l2Provider)
this.fundingWallet = new ethers.Wallet(flags['private-key'], this.l1Provider)
} else if (!flags.manual && !flags.dev) {
this.l1FundingWallet = new ethers.Wallet(config.accounts.DEPLOYER_PRIVATE_KEY, this.l1Provider)
this.l2FundingWallet = new ethers.Wallet(config.accounts.DEPLOYER_PRIVATE_KEY, this.l2Provider)
}

if (flags['gateway-address']) {
this.l1ETHGateway = flags['gateway-address']
} else if (flags.contracts) {
const contractsConfigPath = path.resolve(flags.contracts)
try {
const contractsConfig = parseTomlConfig(contractsConfigPath)
this.l1ETHGateway = contractsConfig?.L1_ETH_GATEWAY_PROXY_ADDR
} catch (error) {
this.log("Parsing config-contracts.toml failed. Bridging will be disabled.")
}
this.fundingWallet = new ethers.Wallet(config.accounts.DEPLOYER_PRIVATE_KEY, this.l1Provider)
}

const l1Addresses = [
Expand Down Expand Up @@ -177,20 +153,14 @@ export default class HelperFundContracts extends Command {
continue
}

this.log(this.l1ETHGateway)
const fundingMethod = await this.promptUserForL2Funding()

if (flags.manual) {
await this.promptManualFunding(address, FUNDING_AMOUNT, Layer.L2)
if (fundingMethod === 'bridge') {
await this.bridgeFundsL1ToL2(address, FUNDING_AMOUNT)
} else if (fundingMethod === 'direct') {
await this.fundAddressNetwork(this.l2Provider, address, FUNDING_AMOUNT, Layer.L2)
} else {
const fundingMethod = await this.promptUserForL2Funding()

if (fundingMethod === 'bridge') {
await this.bridgeFundsL1ToL2(address, FUNDING_AMOUNT)
} else if (fundingMethod === 'direct') {
await this.fundAddressNetwork(this.l2Provider, address, FUNDING_AMOUNT, Layer.L2)
} else {
await this.promptManualFunding(address, FUNDING_AMOUNT, Layer.L2)
}
await this.promptManualFunding(address, FUNDING_AMOUNT, Layer.L2)
}
}
}
Expand All @@ -206,9 +176,8 @@ export default class HelperFundContracts extends Command {
}

private async fundAddressNetwork(provider: ethers.JsonRpcProvider, address: string, amount: number, layer: Layer) {
const fundingWallet = layer === Layer.L1 ? this.l1FundingWallet : this.l2FundingWallet
try {
const tx = await fundingWallet.sendTransaction({
const tx = await this.fundingWallet.sendTransaction({
to: address,
value: ethers.parseEther(amount.toString()),
})
Expand Down Expand Up @@ -255,8 +224,8 @@ export default class HelperFundContracts extends Command {
const answer = await select({
message: 'How would you like to fund the L2 address?',
choices: [
{ name: 'Bridge funds from L1', value: 'bridge', disabled: !(this.l1ETHGateway) },
{ name: 'Directly fund L2 wallet using Deployer / private key', value: 'direct' },
{ name: 'Bridge funds from L1', value: 'bridge' },
{ name: 'Directly fund L2 wallet', value: 'direct' },
{ name: 'Manual funding', value: 'manual' },
],
})
Expand All @@ -270,12 +239,10 @@ export default class HelperFundContracts extends Command {
const gasLimit = BigInt(170_000)
const value = ethers.parseEther((amount + 0.001).toString())

this.log(this.l1ETHGateway)

const l1ETHGateway = new ethers.Contract(
this.l1ETHGateway,
['function depositETH(address _to, uint256 _amount, uint256 _gasLimit) payable'],
this.l1FundingWallet
this.fundingWallet
)

await this.logAddress(this.l1ETHGateway, `Depositing ${amount} ETH by sending ${ethers.formatEther(value)} to`, Layer.L1)
Expand Down
72 changes: 48 additions & 24 deletions src/commands/test/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { Command, Flags } from '@oclif/core'
import cliProgress from 'cli-progress'
import { ethers } from 'ethers'
import path from 'node:path'
import chalk from 'chalk'

import { DeployedContract, L1Contracts, L2Contracts } from '../../data/contracts.js'
import { DeployedContract, contracts, Layer } from '../../data/contracts.js'
import { parseTomlConfig } from '../../utils/config-parser.js'
import { addressLink, txLink } from '../../utils/onchain/index.js'

interface ContractsConfig {
[key: string]: string
}


export default class TestContracts extends Command {
static description = 'Test contracts by checking deployment and initialization'

Expand All @@ -31,6 +34,11 @@ export default class TestContracts extends Command {
}),
}

private blockExplorers: Record<Layer, { blockExplorerURI: string }> = {
[Layer.L1]: { blockExplorerURI: '' },
[Layer.L2]: { blockExplorerURI: '' },
}

async run(): Promise<void> {
const { flags } = await this.parse(TestContracts)

Expand All @@ -54,47 +62,50 @@ export default class TestContracts extends Command {

const owner = config?.accounts?.OWNER_ADDR

this.blockExplorers.l1.blockExplorerURI = config?.frontend?.EXTERNAL_EXPLORER_URI_L1
this.blockExplorers.l2.blockExplorerURI = config?.frontend?.EXTERNAL_EXPLORER_URI_L2

// Check if RPC URLs are defined
if (!l1RpcUrl || !l2RpcUrl) {
this.error(
this.error(chalk.red(
`Missing RPC URL(s) in ${configPath}. Please ensure L1_RPC_ENDPOINT and L2_RPC_ENDPOINT (for pod mode) or EXTERNAL_RPC_URI_L1 and EXTERNAL_RPC_URI_L2 (for non-pod mode) are defined.`,
)
))
}

// Check if owner address is defined
if (!owner) {
this.error(`Missing OWNER_ADDR in ${configPath}. Please ensure it is defined in the accounts section.`)
this.error(chalk.red(`Missing OWNER_ADDR in ${configPath}. Please ensure it is defined in the accounts section.`))
}

// Check if contractsConfig is empty
if (Object.keys(contractsConfig).length === 0) {
this.error(
this.error(chalk.red(
`Contract configuration in ${contractsPath} is empty. Please ensure it contains the necessary contract addresses.`,
)
))
}

const l1Provider = new ethers.JsonRpcProvider(l1RpcUrl)
const l2Provider = new ethers.JsonRpcProvider(l2RpcUrl)

// Check that config has a value for each required contract name

const l1Addresses: DeployedContract[] = L1Contracts.map((contract) => {
const l1Addresses: DeployedContract[] = contracts.filter((contract) => contract.layer === Layer.L1).map((contract) => {
const address = contractsConfig[contract.name]
if (!address) {
this.log(`Missing address for contract: ${contract.name}`)
this.log(chalk.yellow(`Missing address for contract: ${contract.name}`))
}

return { ...contract, address }
}).filter((address) => address !== undefined)
}).filter((contract: DeployedContract) => contract.address !== undefined)

const l2Addresses: DeployedContract[] = L2Contracts.map((contract) => {
const l2Addresses: DeployedContract[] = contracts.filter((contract) => contract.layer === Layer.L2).map((contract) => {
const address = contractsConfig[contract.name]
if (!address) {
this.log(`Missing address for contract: ${contract.name}`)
this.log(chalk.yellow(`Missing address for contract: ${contract.name}`))
}

return { ...contract, address }
}).filter((address) => address !== undefined)
}).filter((contract) => contract.address !== undefined)

try {
// Check Deployments
Expand Down Expand Up @@ -195,34 +206,44 @@ export default class TestContracts extends Command {
(!contract.owned || !notOwned.some((no) => no.name === contract.name)),
)

this.log('\nCorrectly configured contracts:')
this.log(chalk.green('\nCorrectly configured contracts:'))
for (const contract of correctlyConfigured) {
let status = 'Deployed'
if (contract.initializes) status += ', Initialized'
if (contract.owned) status += ', Correctly Owned'
this.log(`- ${contract.name} (${contract.address}): ${status}`)
const link = await addressLink(contract.address!, this.blockExplorers[contract.layer === 'l1' ? Layer.L1 : Layer.L2])
this.log(`- ${chalk.cyan(contract.name)}\n ${chalk.blue(link)}\n Status: ${chalk.green(status)}`)
}

if (notDeployed.length > 0) {
this.log('\nContracts not deployed:')
for (const contract of notDeployed) this.log(`- ${contract.name} (${contract.address})`)
this.log(chalk.red('\nContracts not deployed:'))
for (const contract of notDeployed) {
const link = await addressLink(contract.address!, this.blockExplorers[contract.layer === 'l1' ? Layer.L1 : Layer.L2])
this.log(chalk.red(`- ${contract.name}\n ${chalk.blue(link)}`))
}
}

if (notInitialized.length > 0) {
this.log('\nContracts not initialized:')
for (const contract of notInitialized) this.log(`- ${contract.name} (${contract.address})`)
this.log(chalk.yellow('\nContracts not initialized:'))
for (const contract of notInitialized) {
const link = await addressLink(contract.address!, this.blockExplorers[contract.layer === 'l1' ? Layer.L1 : Layer.L2])
this.log(chalk.yellow(`- ${contract.name}\n ${chalk.blue(link)}`))
}
}

if (notOwned.length > 0) {
this.log('\nContracts without correct owner:')
for (const contract of notInitialized) this.log(`- ${contract.name} (${contract.address})`)
this.log(chalk.yellow('\nContracts without correct owner:'))
for (const contract of notOwned) {
const link = await addressLink(contract.address!, this.blockExplorers[contract.layer === 'l1' ? Layer.L1 : Layer.L2])
this.log(chalk.yellow(`- ${contract.name}\n ${chalk.blue(link)}`))
}
}

if (notDeployed.length === 0 && notInitialized.length === 0 && notOwned.length === 0) {
this.log('\nAll contracts are deployed, initialized and have owner set.')
this.log(chalk.green('\nAll contracts are deployed, initialized and have owner set.'))
}
} catch (error) {
this.error(`Failed to check contracts: ${error}`)
this.error(chalk.red(`Failed to check contracts: ${error}`))
}
}

Expand Down Expand Up @@ -252,8 +273,11 @@ export default class TestContracts extends Command {
for (const c of contracts) {
progressBar.update({ name: `Checking ${c.name}...` })
try {
const initCount = await provider.getStorage(c?.address || '', 0)
if (Number.parseInt(initCount) > 0) {
if (!c.address) {
throw (`No address found for ${c.name}`)
}
const initCount = await provider.getStorage(c.address, 0)
if (Number.parseInt(initCount, 16) <= 0) {
notInitialized.push(c)
}
} catch (error) {
Expand Down
Loading

0 comments on commit b1c2a32

Please sign in to comment.