UNPKG

@hyperlane-xyz/core

Version:

Core solidity contracts for Hyperlane

159 lines (136 loc) 4.45 kB
import fs from 'fs' import { Command } from 'commander' import { ethers } from 'ethers' import { getContractInterface } from '@eth-optimism/contracts' import { version } from '../package.json' import { advancedQueryFilter } from '../src/advanced-query' const program = new Command() program .name('migration-data-query') .description('CLI for querying Bedrock migration data') .version(version) program .command('parse-state-dump') .description('parses state dump to json') .option('--file <file>', 'path to state dump file') .action(async (options) => { const iface = getContractInterface('OVM_L2ToL1MessagePasser') const dump = fs.readFileSync(options.file, 'utf-8') const addrs: string[] = [] const msgs: any[] = [] for (const line of dump.split('\n')) { if (line.startsWith('ETH')) { addrs.push(line.split('|')[1].replace('\r', '')) } else if (line.startsWith('MSG')) { const msg = '0x' + line.split('|')[2].replace('\r', '') const parsed = iface.decodeFunctionData('passMessageToL1', msg) msgs.push({ who: line.split('|')[1], msg: parsed._message, }) } } fs.writeFileSync( './data/evm-addresses.json', JSON.stringify(addrs, null, 2) ) fs.writeFileSync('./data/evm-messages.json', JSON.stringify(msgs, null, 2)) }) program .command('evm-sent-messages') .description('queries messages sent after the EVM upgrade') .option('--rpc <rpc>', 'rpc url to use') .action(async (options) => { const provider = new ethers.providers.JsonRpcProvider(options.rpc) const xdm = new ethers.Contract( '0x4200000000000000000000000000000000000007', getContractInterface('L2CrossDomainMessenger'), provider ) const sent: any[] = await advancedQueryFilter(xdm, { queryFilter: xdm.filters.SentMessage(), }) const messages: any[] = [] for (const s of sent) { messages.push({ who: '0x4200000000000000000000000000000000000007', msg: xdm.interface.encodeFunctionData('relayMessage', [ s.args.target, s.args.sender, s.args.message, s.args.messageNonce, ]), }) } fs.writeFileSync( './data/evm-messages.json', JSON.stringify(messages, null, 2) ) }) program .command('sent-slots') .description('queries storage slots in the message passer') .option('--rpc <rpc>', 'rpc url to use') .action(async (options) => { const provider = new ethers.providers.JsonRpcProvider(options.rpc) let nextKey = '0x' let slots: any[] = [] while (nextKey) { const latestBlock = await provider.getBlock('latest') const ret = await provider.send('debug_storageRangeAt', [ latestBlock.hash, 0, '0x4200000000000000000000000000000000000000', nextKey, 10000, ]) slots = slots.concat( Object.values(ret.storage).map((s: any) => { return s.key }) ) // Update next key and potentially try again nextKey = ret.nextKey } fs.writeFileSync('./data/slots.json', JSON.stringify(slots, null, 2)) }) program .command('accounting') .description('verifies that we have sufficient slot data') .action(async () => { const parseMessageFile = ( path: string ): Array<{ message: string slot: string }> => { const messages: any[] = JSON.parse(fs.readFileSync(path, 'utf8')) return messages.map((message) => { return { message, slot: ethers.utils.keccak256( ethers.utils.hexConcat([ ethers.utils.keccak256( ethers.utils.hexConcat([message.msg, message.who]) ), ethers.constants.HashZero, ]) ), } }) } const ovmMessages = parseMessageFile('./data/ovm-messages.json') const evmMessages = parseMessageFile('./data/evm-messages.json') const slotList: string[] = JSON.parse( fs.readFileSync('./data/slots.json', 'utf8') ) const unaccounted = slotList.filter((slot) => { return ( !ovmMessages.some((m) => m.slot === slot) && !evmMessages.some((m) => m.slot === slot) ) }) console.log(`Total slots: ${slotList.length}`) console.log(`Unaccounted slots: ${unaccounted.length}`) }) program.parse(process.argv)