Skip to content

Commit

Permalink
Merge branch 'initial-testing-fixes'
Browse files Browse the repository at this point in the history
  • Loading branch information
dghelm committed Aug 17, 2024
2 parents ad0604c + 92d0866 commit 87cb4f2
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 142 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pnpm-lock.yaml
!.yarn/versions

charts
.vscode



3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,6 @@
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
"version": "oclif readme && git add README.md"
},
"types": "dist/index.d.ts"
"types": "dist/index.d.ts",
"packageManager": "[email protected]+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
}
211 changes: 117 additions & 94 deletions src/commands/test/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {Command, Flags} from '@oclif/core'
import cliProgress from 'cli-progress'
import {ethers} from 'ethers'
import path from 'node:path'

import {DeployedContract, L1Contracts, L2Contracts} from '../../data/contracts.js'
import {parseTomlConfig} from '../../utils/config-parser.js'
import path from 'path'
import cliProgress from 'cli-progress'
import { L1Contracts, L2Contracts, DeployedContract } from '../../data/contracts.js'

interface ContractsConfig {
[key: string]: string
Expand All @@ -15,18 +16,18 @@ export default class TestContracts extends Command {
static flags = {
config: Flags.string({
char: 'c',
default: './config.toml',
description: 'Path to config.toml file',
default: './charts/scroll-stack/config.toml',
}),
contracts: Flags.string({
char: 't',
default: './config-contracts.toml',
description: 'Path to configs-contracts.toml file',
default: './charts/scroll-stack/configs-contracts.toml',
}),
pod: Flags.boolean({
char: 'p',
description: 'Run inside Kubernetes pod',
default: false,
description: 'Run inside Kubernetes pod',
}),
}

Expand Down Expand Up @@ -55,152 +56,176 @@ export default class TestContracts extends Command {

// Check if RPC URLs are defined
if (!l1RpcUrl || !l2RpcUrl) {
this.error(`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.`);
this.error(
`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(`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(`Contract configuration in ${contractsPath} is empty. Please ensure it contains the necessary contract addresses.`);
this.error(
`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 address = contractsConfig[contract.name];
const l1Addresses: DeployedContract[] = L1Contracts.map((contract) => {
const address = contractsConfig[contract.name]
if (!address) {
this.log(`Missing address for contract: ${contract.name}`);
this.log(`Missing address for contract: ${contract.name}`)
}
return {...contract, address};
}).filter(address => address !== undefined);

const l2Addresses : DeployedContract[] = L2Contracts.map(contract => {
const address = contractsConfig[contract.name];
return {...contract, address}
}).filter((address) => address !== undefined)

const l2Addresses: DeployedContract[] = L2Contracts.map((contract) => {
const address = contractsConfig[contract.name]
if (!address) {
this.log(`Missing address for contract: ${contract.name}`);
this.log(`Missing address for contract: ${contract.name}`)
}
return {...contract, address};
}).filter(address => address !== undefined);

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

try {
// Check Deployments

const multibarDeployment = new cliProgress.MultiBar(
{
clearOnComplete: false,
format: ' {bar} | {percentage}% | {value}/{total} | {name}',
hideCursor: true,
},
cliProgress.Presets.shades_classic,
)

const multibarDeployment = new cliProgress.MultiBar({
clearOnComplete: false,
hideCursor: true,
format: ' {bar} | {percentage}% | {value}/{total} | {name}',
}, cliProgress.Presets.shades_classic)

let l1BarDeploy = multibarDeployment.create(l1Addresses.length, 0, {name: 'Checking L1 contract deployment...'})
let l2BarDeploy = multibarDeployment.create(l2Addresses.length, 0, {name: 'Checking L2 contract deployment...'})
const l1BarDeploy = multibarDeployment.create(l1Addresses.length, 0, {name: 'Checking L1 contract deployment...'})
const l2BarDeploy = multibarDeployment.create(l2Addresses.length, 0, {name: 'Checking L2 contract deployment...'})

const notDeployed: DeployedContract[] = []

await Promise.all([
this.checkContractDeployment(l1Provider, l1Addresses, l1BarDeploy, notDeployed ),
this.checkContractDeployment(l2Provider, l2Addresses, l2BarDeploy, notDeployed ),
this.checkContractDeployment(l1Provider, l1Addresses, l1BarDeploy, notDeployed),
this.checkContractDeployment(l2Provider, l2Addresses, l2BarDeploy, notDeployed),
])


// Check Initializations

const multibarInitialization = new cliProgress.MultiBar({
clearOnComplete: false,
hideCursor: true,
format: ' {bar} | {percentage}% | {value}/{total} | {name}',
}, cliProgress.Presets.shades_classic)

const l1AddressesToInitialize = l1Addresses.filter(contract => contract.initializes && !notDeployed.some(nd => nd.name === contract.name));
const l2AddressesToInitialize = l2Addresses.filter(contract => contract.initializes && !notDeployed.some(nd => nd.name === contract.name));

const l1BarInit = multibarDeployment.create(l1AddressesToInitialize.length, 0, {name: 'Checking L1 contract initialization...'})
const l2BarInit = multibarDeployment.create(l2AddressesToInitialize.length, 0, {name: 'Checking L2 contract initialization...'})
const multibarInitialization = new cliProgress.MultiBar(
{
clearOnComplete: false,
format: ' {bar} | {percentage}% | {value}/{total} | {name}',
hideCursor: true,
},
cliProgress.Presets.shades_classic,
)

const l1AddressesToInitialize = l1Addresses.filter(
(contract) => contract.initializes && !notDeployed.some((nd) => nd.name === contract.name),
)
const l2AddressesToInitialize = l2Addresses.filter(
(contract) => contract.initializes && !notDeployed.some((nd) => nd.name === contract.name),
)

const l1BarInit = multibarDeployment.create(l1AddressesToInitialize.length, 0, {
name: 'Checking L1 contract initialization...',
})
const l2BarInit = multibarDeployment.create(l2AddressesToInitialize.length, 0, {
name: 'Checking L2 contract initialization...',
})

const notInitialized: DeployedContract[] = []

await Promise.all([
this.checkContractInitialization(l1Provider, l1AddressesToInitialize, l1BarInit, notInitialized ),
this.checkContractInitialization(l2Provider, l2AddressesToInitialize, l2BarInit, notInitialized ),
this.checkContractInitialization(l1Provider, l1AddressesToInitialize, l1BarInit, notInitialized),
this.checkContractInitialization(l2Provider, l2AddressesToInitialize, l2BarInit, notInitialized),
])


// Check Owner

const multibarOwner = new cliProgress.MultiBar({
clearOnComplete: false,
hideCursor: true,
format: ' {bar} | {percentage}% | {value}/{total} | {name}',
}, cliProgress.Presets.shades_classic)

const l1AddressesWithOwner = l1Addresses.filter(contract => contract.owned && !notDeployed.some(nd => nd.name === contract.name));
const l2AddressesWithOwner = l2Addresses.filter(contract => contract.owned && !notDeployed.some(nd => nd.name === contract.name));

const l1BarOwner = multibarOwner.create(l1AddressesWithOwner.length, 0, {name: 'Checking L1 contract ownership...'})
const l2BarOwner = multibarOwner.create(l2AddressesWithOwner.length, 0, {name: 'Checking L2 contract ownership...'})
const multibarOwner = new cliProgress.MultiBar(
{
clearOnComplete: false,
format: ' {bar} | {percentage}% | {value}/{total} | {name}',
hideCursor: true,
},
cliProgress.Presets.shades_classic,
)

const l1AddressesWithOwner = l1Addresses.filter(
(contract) => contract.owned && !notDeployed.some((nd) => nd.name === contract.name),
)
const l2AddressesWithOwner = l2Addresses.filter(
(contract) => contract.owned && !notDeployed.some((nd) => nd.name === contract.name),
)

const l1BarOwner = multibarOwner.create(l1AddressesWithOwner.length, 0, {
name: 'Checking L1 contract ownership...',
})
const l2BarOwner = multibarOwner.create(l2AddressesWithOwner.length, 0, {
name: 'Checking L2 contract ownership...',
})

const notOwned: DeployedContract[] = []

await Promise.all([
this.checkContractOwner(l1Provider, l1AddressesWithOwner, l1BarOwner, owner, notOwned ),
this.checkContractOwner(l2Provider, l2AddressesWithOwner, l2BarOwner, owner, notOwned ),
this.checkContractOwner(l1Provider, l1AddressesWithOwner, l1BarOwner, owner, notOwned),
this.checkContractOwner(l2Provider, l2AddressesWithOwner, l2BarOwner, owner, notOwned),
])


multibarDeployment.stop()
multibarInitialization.stop()
multibarOwner.stop()

// Print results
// Print results for correctly deployed, initialized, and owned contracts
const correctlyConfigured = [...l1Addresses, ...l2Addresses].filter(contract =>
!notDeployed.some(nd => nd.name === contract.name) &&
(!contract.initializes || !notInitialized.some(ni => ni.name === contract.name)) &&
(!contract.owned || !notOwned.some(no => no.name === contract.name))
);

this.log('\nCorrectly configured contracts:');
correctlyConfigured.forEach(contract => {
let status = 'Deployed';
if (contract.initializes) status += ', Initialized';
if (contract.owned) status += ', Correctly Owned';
this.log(`- ${contract.name} (${contract.address}): ${status}`);
});
const correctlyConfigured = [...l1Addresses, ...l2Addresses].filter(
(contract) =>
!notDeployed.some((nd) => nd.name === contract.name) &&
(!contract.initializes || !notInitialized.some((ni) => ni.name === contract.name)) &&
(!contract.owned || !notOwned.some((no) => no.name === contract.name)),
)

this.log('\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}`)
}

if (notDeployed.length > 0) {
this.log('\nContracts not deployed:')
notDeployed.forEach(contract => this.log(`- ${contract.name} (${contract.address})`))
for (const contract of notDeployed) this.log(`- ${contract.name} (${contract.address})`)
}

if (notInitialized.length > 0) {
this.log('\nContracts not initialized:')
notInitialized.forEach(contract => this.log(`- ${contract.name} (${contract.address})`))
for (const contract of notInitialized) this.log(`- ${contract.name} (${contract.address})`)
}

if (notOwned.length > 0) {
this.log('\nContracts without correct owner:')
notInitialized.forEach(contract => this.log(`- ${contract.name} (${contract.address})`))
for (const contract of notInitialized) this.log(`- ${contract.name} (${contract.address})`)
}

if (notDeployed.length === 0 && notInitialized.length === 0 && notOwned.length === 0 ) {
if (notDeployed.length === 0 && notInitialized.length === 0 && notOwned.length === 0) {
this.log('\nAll contracts are deployed, initialized and have owner set.')
}

} catch (error) {
this.error(`Failed to check contracts: ${error}`)
}

}


private async checkContractDeployment(
provider: ethers.Provider,
contracts: DeployedContract[],
Expand All @@ -212,10 +237,9 @@ export default class TestContracts extends Command {
const code = await provider.getCode(c.address ?? '')
if (code === '0x') {
notDeployed.push(c)
}
}

progressBar.increment()

}
}

Expand All @@ -228,16 +252,15 @@ 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 (parseInt(initCount) > 0 ) {
const initCount = await provider.getStorage(c?.address || '', 0)
if (Number.parseInt(initCount) > 0) {
notInitialized.push(c)
}
}
} catch (error) {
this.error(`Error checking initialization for ${c.name}: ${error}`);
this.error(`Error checking initialization for ${c.name}: ${error}`)
}

progressBar.increment()

}
}

Expand All @@ -248,23 +271,23 @@ export default class TestContracts extends Command {
expectedOwner: string,
notOwned: DeployedContract[],
) {
const ownableABI = ['function owner() view returns (address)'];
const ownableABI = ['function owner() view returns (address)']

for (const c of contracts) {
progressBar.update({name: `Checking ${c.name}...`})
if (c.owned && c.address) {
const contract = new ethers.Contract(c.address, ownableABI, provider);
const contract = new ethers.Contract(c.address, ownableABI, provider)
try {
const owner = await contract.owner();
const owner = await contract.owner()
if (owner.toLowerCase() !== expectedOwner.toLowerCase()) {
notOwned.push(c);
notOwned.push(c)
}
} catch (error) {
this.error(`Error checking owner for ${c.name}: ${error}`);
this.error(`Error checking owner for ${c.name}: ${error}`)
}
}
progressBar.increment();

progressBar.increment()
}
}

}
}
Loading

0 comments on commit 87cb4f2

Please sign in to comment.