From 7c947260d5cd19ade3733900f4198f0d003fc1fb Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Tue, 2 Jul 2024 18:21:15 +0800 Subject: [PATCH 1/6] added testnet manully register script --- scripts/wormhole-bulk-attest/src/manual.ts | 30 ++++++++++++++++++++++ scripts/wormhole-bulk-attest/yarn.lock | 8 +++--- 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 scripts/wormhole-bulk-attest/src/manual.ts diff --git a/scripts/wormhole-bulk-attest/src/manual.ts b/scripts/wormhole-bulk-attest/src/manual.ts new file mode 100644 index 000000000..3980db306 --- /dev/null +++ b/scripts/wormhole-bulk-attest/src/manual.ts @@ -0,0 +1,30 @@ +import { AcalaJsonRpcProvider } from "@acala-network/eth-providers"; +import { createWrappedOnEth, getEmitterAddressEth, getSignedVAA } from "@certusone/wormhole-sdk"; +import { Wallet } from "ethers"; +import dotenv from 'dotenv'; +import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport"; + +dotenv.config(); + +const key = process.env.KEY; +if (!key) throw new Error('no key!'); + +(async () => { + const srcTokenBridgeAddr = '0xDB5492265f6038831E89f495670FF909aDe94bd9'; + const emitterAddress = getEmitterAddressEth(srcTokenBridgeAddr); + const sepoliaWhChainId = 10002; + const signedVaa = await getSignedVAA( + 'https://api.testnet.wormholescan.io', + sepoliaWhChainId, + emitterAddress, + "3270", + { transport: NodeHttpTransport() } + ) + console.log(signedVaa) + + const dstTokenBridgeAddr = '0xe157115ef34c93145Fec2FE53706846853B07F42'; + const provider = new AcalaJsonRpcProvider('https://eth-rpc-acala-testnet.aca-staging.network'); + const wallet = new Wallet(key, provider); + const receipt = await createWrappedOnEth(dstTokenBridgeAddr, wallet, signedVaa.vaaBytes); + console.log(receipt) +})() \ No newline at end of file diff --git a/scripts/wormhole-bulk-attest/yarn.lock b/scripts/wormhole-bulk-attest/yarn.lock index 275555aa0..8cce87695 100644 --- a/scripts/wormhole-bulk-attest/yarn.lock +++ b/scripts/wormhole-bulk-attest/yarn.lock @@ -3415,7 +3415,7 @@ __metadata: "fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7" + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" dependencies: node-gyp: latest conditions: os=darwin @@ -5121,7 +5121,7 @@ __metadata: "resolve@patch:resolve@^1.0.0#~builtin, resolve@patch:resolve@^1.1.6#~builtin": version: 1.22.1 - resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=07638b" + resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=c3c19d" dependencies: is-core-module: ^2.9.0 path-parse: ^1.0.7 @@ -5944,11 +5944,11 @@ __metadata: "typescript@patch:typescript@^4.9.4#~builtin": version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=701156" + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=289587" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 + checksum: 1f8f3b6aaea19f0f67cba79057674ba580438a7db55057eb89cc06950483c5d632115c14077f6663ea76fd09fce3c190e6414bb98582ec80aa5a4eaf345d5b68 languageName: node linkType: hard From 0629d4833397af28e7ebac0a6aa5c7a33246cccf Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Wed, 24 Jul 2024 18:49:45 +0800 Subject: [PATCH 2/6] add debug_traceTx RPC --- packages/eth-providers/package.json | 4 +- packages/eth-providers/src/base-provider.ts | 34 +++ packages/eth-providers/src/utils/trace.ts | 264 ++++++++++++++++++ .../eth-rpc-adapter/src/eip1193-bridge.ts | 11 +- packages/eth-rpc-adapter/src/validate.ts | 7 +- yarn.lock | 40 +-- 6 files changed, 332 insertions(+), 28 deletions(-) create mode 100644 packages/eth-providers/src/utils/trace.ts diff --git a/packages/eth-providers/package.json b/packages/eth-providers/package.json index fce4aa028..167fca134 100644 --- a/packages/eth-providers/package.json +++ b/packages/eth-providers/package.json @@ -10,7 +10,7 @@ "test:e2e": "vitest --run --config vitest.config.e2e.ts" }, "peerDependencies": { - "@acala-network/api": "6.1.0", + "@acala-network/api": "^6.1.3", "@polkadot/api": "^10.11.1" }, "dependencies": { @@ -23,7 +23,7 @@ "lru-cache": "~7.8.2" }, "devDependencies": { - "@acala-network/api": "6.1.0", + "@acala-network/api": "^6.1.3", "@types/bn.js": "~5.1.0", "@types/lru-cache": "~7.6.1", "dotenv": "~10.0.0", diff --git a/packages/eth-providers/src/base-provider.ts b/packages/eth-providers/src/base-provider.ts index 838d3eb2c..d16feabe8 100644 --- a/packages/eth-providers/src/base-provider.ts +++ b/packages/eth-providers/src/base-provider.ts @@ -97,6 +97,7 @@ import { import { BlockCache, CacheInspect } from './utils/BlockCache'; import { MaxSizeSet } from './utils/MaxSizeSet'; import { SubqlProvider } from './utils/subqlProvider'; +import { TracerType, traceCall, traceVM } from './utils/trace'; import { _Metadata } from './utils/gqlTypes'; export interface HeadsInfo { @@ -2164,4 +2165,37 @@ export abstract class BaseProvider extends AbstractProvider { listeners = (_eventName?: EventType): Array => throwNotImplemented('listeners'); off = (_eventName: EventType, _listener?: Listener): Provider => throwNotImplemented('off'); removeAllListeners = (_eventName?: EventType): Provider => throwNotImplemented('removeAllListeners'); + + traceTx = async (txHash: string, traceConf: any) => { + const tracerOptions = Object.values(TracerType); + if (!tracerOptions.includes(traceConf.tracer)) { + logger.throwError( + `traceTx: invalid tracer, must be one of { ${tracerOptions.join(', ')} }`, + Logger.errors.INVALID_ARGUMENT, + { tracer: traceConf.tracer }, + ); + } + + if (!this.api.call.evmTraceApi) { + logger.throwError('traceTx: evm tracing not supported', Logger.errors.NOT_IMPLEMENTED, { txHash }); + } + + const receipt = await this.getReceipt(txHash); + if (!receipt) { + logger.throwError('traceTx: tx not found', Logger.errors.UNKNOWN_ERROR, { txHash }); + } + + const { blockHash, transactionIndex } = receipt; + const blockData = await this.api.rpc.chain.getBlock(blockHash); + const evmExtrinsics = blockData.block.extrinsics.filter(isEvmExtrinsic); + + const targetExtrinsic = evmExtrinsics[transactionIndex]; + if (!targetExtrinsic) { + logger.throwError('traceTx: target extrinsic not found', Logger.errors.UNKNOWN_ERROR, { txHash }); + } + + return traceConf.tracer === TracerType.CallTracer + ? await traceCall(this.api, targetExtrinsic) + : await traceVM(this.api, targetExtrinsic); + }; } diff --git a/packages/eth-providers/src/utils/trace.ts b/packages/eth-providers/src/utils/trace.ts new file mode 100644 index 000000000..730ff9d6d --- /dev/null +++ b/packages/eth-providers/src/utils/trace.ts @@ -0,0 +1,264 @@ +import { ApiPromise } from '@polkadot/api'; +import { Extrinsic } from '@polkadot/types/interfaces'; +import { HexString } from '@polkadot/util/types'; +import { IExtrinsic } from '@polkadot/types/types'; + +export type CallTrace = { + type: 'CALL' | 'CALLCODE' | 'STATICCALL' | 'DELEGATECALL' | 'CREATE' | 'SUICIDE'; + from: HexString; + to: HexString; + input: HexString; + value: HexString; + gas: number; + gasUsed: number; + output: HexString | null; + error: string | null; + revertReason: string | null; + depth: number; + calls: CallTrace[]; +} + +export interface StepBase { + pc: number; + depth: number; + gas: number; + stack: HexString[]; + memory: string[] | null; +} + +export interface StepRaw extends StepBase { + op: number; +} + +export interface Step extends StepBase { + op: string; +} + +export enum TracerType { + CallTracer = 'callTracer', + OpcodeTracer = 'opcodeTracer' +} + +export const OPNAME_TABLE = { + '0x00': 'STOP', + '0x01': 'ADD', + '0x02': 'MUL', + '0x03': 'SUB', + '0x04': 'DIV', + '0x05': 'SDIV', + '0x06': 'MOD', + '0x07': 'SMOD', + '0x08': 'ADDMOD', + '0x09': 'MULMOD', + '0x0a': 'EXP', + '0x0b': 'SIGNEXTEND', + '0x10': 'LT', + '0x11': 'GT', + '0x12': 'SLT', + '0x13': 'SGT', + '0x14': 'EQ', + '0x15': 'ISZERO', + '0x16': 'AND', + '0x17': 'OR', + '0x18': 'XOR', + '0x19': 'NOT', + '0x1a': 'BYTE', + '0x35': 'CALLDATALOAD', + '0x36': 'CALLDATASIZE', + '0x37': 'CALLDATACOPY', + '0x38': 'CODESIZE', + '0x39': 'CODECOPY', + '0x1b': 'SHL', + '0x1c': 'SHR', + '0x1d': 'SAR', + '0x50': 'POP', + '0x51': 'MLOAD', + '0x52': 'MSTORE', + '0x53': 'MSTORE8', + '0x56': 'JUMP', + '0x57': 'JUMPI', + '0x58': 'PC', + '0x59': 'MSIZE', + '0x5b': 'JUMPDEST', + '0x5f': 'PUSH0', + '0x60': 'PUSH1', + '0x61': 'PUSH2', + '0x62': 'PUSH3', + '0x63': 'PUSH4', + '0x64': 'PUSH5', + '0x65': 'PUSH6', + '0x66': 'PUSH7', + '0x67': 'PUSH8', + '0x68': 'PUSH9', + '0x69': 'PUSH10', + '0x6a': 'PUSH11', + '0x6b': 'PUSH12', + '0x6c': 'PUSH13', + '0x6d': 'PUSH14', + '0x6e': 'PUSH15', + '0x6f': 'PUSH16', + '0x70': 'PUSH17', + '0x71': 'PUSH18', + '0x72': 'PUSH19', + '0x73': 'PUSH20', + '0x74': 'PUSH21', + '0x75': 'PUSH22', + '0x76': 'PUSH23', + '0x77': 'PUSH24', + '0x78': 'PUSH25', + '0x79': 'PUSH26', + '0x7a': 'PUSH27', + '0x7b': 'PUSH28', + '0x7c': 'PUSH29', + '0x7d': 'PUSH30', + '0x7e': 'PUSH31', + '0x7f': 'PUSH32', + '0x80': 'DUP1', + '0x81': 'DUP2', + '0x82': 'DUP3', + '0x83': 'DUP4', + '0x84': 'DUP5', + '0x85': 'DUP6', + '0x86': 'DUP7', + '0x87': 'DUP8', + '0x88': 'DUP9', + '0x89': 'DUP10', + '0x8a': 'DUP11', + '0x8b': 'DUP12', + '0x8c': 'DUP13', + '0x8d': 'DUP14', + '0x8e': 'DUP15', + '0x8f': 'DUP16', + '0x90': 'SWAP1', + '0x91': 'SWAP2', + '0x92': 'SWAP3', + '0x93': 'SWAP4', + '0x94': 'SWAP5', + '0x95': 'SWAP6', + '0x96': 'SWAP7', + '0x97': 'SWAP8', + '0x98': 'SWAP9', + '0x99': 'SWAP10', + '0x9a': 'SWAP11', + '0x9b': 'SWAP12', + '0x9c': 'SWAP13', + '0x9d': 'SWAP14', + '0x9e': 'SWAP15', + '0x9f': 'SWAP16', + '0xf3': 'RETURN', + '0xfd': 'REVERT', + '0xfe': 'INVALID', + '0xef': 'EOFMAGIC', + '0x20': 'SHA3', + '0x30': 'ADDRESS', + '0x31': 'BALANCE', + '0x47': 'SELFBALANCE', + '0x48': 'BASEFEE', + '0x32': 'ORIGIN', + '0x33': 'CALLER', + '0x34': 'CALLVALUE', + '0x3a': 'GASPRICE', + '0x3b': 'EXTCODESIZE', + '0x3c': 'EXTCODECOPY', + '0x3f': 'EXTCODEHASH', + '0x3d': 'RETURNDATASIZE', + '0x3e': 'RETURNDATACOPY', + '0x40': 'BLOCKHASH', + '0x41': 'COINBASE', + '0x42': 'TIMESTAMP', + '0x43': 'NUMBER', + '0x44': 'DIFFICULTY', + '0x45': 'GASLIMIT', + '0x54': 'SLOAD', + '0x55': 'SSTORE', + '0x5a': 'GAS', + '0xa0': 'LOG0', + '0xa1': 'LOG1', + '0xa2': 'LOG2', + '0xa3': 'LOG3', + '0xa4': 'LOG4', + '0xf0': 'CREATE', + '0xf5': 'CREATE2', + '0xf1': 'CALL', + '0xf2': 'CALLCODE', + '0xf4': 'DELEGATECALL', + '0xfa': 'STATICCALL', + '0xff': 'SUICIDE', + '0x46': 'CHAINID', +}; + +export const opName = (opCode: number): string => { + const opCodeHex = `0x${opCode.toString(16).padStart(2, '0')}`; + return OPNAME_TABLE[opCodeHex] ?? opCodeHex; +}; + +export const traceVM = async ( + api: ApiPromise, + extrinsic: Extrinsic | IExtrinsic | string | Uint8Array, +) => { + const pageSize = 10000; + const traceConf = { + page: 0, + pageSize, + disableStack: false, + enableMemory: true, + }; + + let traceNextPage = true; + let steps: Step[] = []; + while (traceNextPage) { + const res = await api.call.evmTraceApi.traceExtrinsic(extrinsic, { OpcodeTracer: traceConf }); + + if (!res.isOk) { + throw new Error(`traceVM: trace failed. Err: ${res.asErr.toString()}`); + } + + const okRes = res.asOk; + if (!okRes.isSteps) { + throw new Error('traceVM: invalid outcome'); + } + + const curSteps = okRes.asSteps.toJSON() as StepRaw[]; + + steps = steps.concat( + curSteps.map(step => ({ + ...step, + op: opName(step.op), + // transform memory to 64 bytes chunks + memory: step.memory + ? step.memory.map((chunk, idx) => { + // remove 0x prefix + const slice = chunk.slice(2); + // make sure each chunk is 64 bytes + return slice.length < 64 && idx + 1 < step.memory!.length + ? slice.padStart(64, '0') + : slice; + }) + : null, + })), + ); + + traceConf.page++; + traceNextPage = curSteps.length == pageSize; + } + + return steps; +}; + +export const traceCall = async ( + api: ApiPromise, + extrinsic: Extrinsic | IExtrinsic | string | Uint8Array, +): Promise => { + const traceConf = { CallTracer: null }; + const res = await api.call.evmTraceApi.traceExtrinsic(extrinsic, traceConf); + if (!res.isOk) { + throw new Error(`traceCall: trace failed. Err: ${res.asErr.toString()}`); + } + + const okRes = res.asOk; + if (!okRes.isCalls) { + throw new Error('traceVM: invalid outcome'); + } + + return okRes.asCalls.toJSON() as CallTrace[]; +}; diff --git a/packages/eth-rpc-adapter/src/eip1193-bridge.ts b/packages/eth-rpc-adapter/src/eip1193-bridge.ts index be92e0a59..88791b311 100644 --- a/packages/eth-rpc-adapter/src/eip1193-bridge.ts +++ b/packages/eth-rpc-adapter/src/eip1193-bridge.ts @@ -32,12 +32,8 @@ export class Eip1193Bridge extends EventEmitter { return this.send(request.method, request.params || []); } - isMethodValid(method: string): boolean { - return method.startsWith('eth_') || method.startsWith('net_') || method.startsWith('web3_') || method.startsWith('txpool_'); - } - isMethodImplemented(method: string): method is keyof Eip1193BridgeImpl { - return this.isMethodValid(method) && method in this.#impl; + return method in this.#impl; } async send(method: string, params: any[] = [], ws?: WebSocket): Promise { @@ -501,4 +497,9 @@ class Eip1193BridgeImpl { validate([], params); return this.#provider.txpoolContent(); } + + async debug_traceTransaction(params: any[]): Promise { + validate([{ type: 'trasactionHash' }, { type: '?' }], params); + return this.#provider.traceTx(params[0], params[1]); + } } diff --git a/packages/eth-rpc-adapter/src/validate.ts b/packages/eth-rpc-adapter/src/validate.ts index 2e2d51054..57cf2b8ce 100644 --- a/packages/eth-rpc-adapter/src/validate.ts +++ b/packages/eth-rpc-adapter/src/validate.ts @@ -16,7 +16,8 @@ export type Schema = { | 'message' | 'hexNumber' | 'eventName' - | 'substrateGasParams?'; + | 'substrateGasParams?' + | '?'; }[]; export const validateEventName = (value: any) => { @@ -201,6 +202,10 @@ export const validate = (schema: Schema, data: unknown[]) => { data[i] && validateSubstrateGasParams(data[i] as any); break; } + case '?': { + // TODO: refactor the param validating process + break; + } default: break; } diff --git a/yarn.lock b/yarn.lock index 317e14941..9f638b831 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,26 +12,26 @@ __metadata: languageName: node linkType: hard -"@acala-network/api-derive@npm:6.1.0": - version: 6.1.0 - resolution: "@acala-network/api-derive@npm:6.1.0" +"@acala-network/api-derive@npm:6.1.3": + version: 6.1.3 + resolution: "@acala-network/api-derive@npm:6.1.3" dependencies: - "@acala-network/types": 6.1.0 + "@acala-network/types": 6.1.3 peerDependencies: - "@polkadot/api": ^10.9.1 - checksum: a29227d804e451a26e9011d312fec3d35e872107e2420accd6ba76445eaf603c163150120a0325b851556ef263412ecd668aabba82acb40ef13e30ff4e71d025 + "@polkadot/api": ^12 + checksum: b5ad7dd41188a4246f9b27230ef0aefc82a220ff3a0ed2383c91833c7bb3807bacff9e63516f9c90158a8faad4f95cb35286e74992e9642fe632ff0dbf85013c languageName: node linkType: hard -"@acala-network/api@npm:6.1.0": - version: 6.1.0 - resolution: "@acala-network/api@npm:6.1.0" +"@acala-network/api@npm:^6.1.3": + version: 6.1.3 + resolution: "@acala-network/api@npm:6.1.3" dependencies: - "@acala-network/api-derive": 6.1.0 - "@acala-network/types": 6.1.0 + "@acala-network/api-derive": 6.1.3 + "@acala-network/types": 6.1.3 peerDependencies: - "@polkadot/api": ^10.9.1 - checksum: 286aa8b219d1255c89f8be8c9af2594192178b78a992b8528e1d0df5dc647f6c02dac291c3fa03025a6a30fc6b9e77a00ac4368191d1f4bd07838e32070a3181 + "@polkadot/api": ^12 + checksum: 4a187e649e7807cb18886204544fbbaf0844d333d413c6a9bb457c250f4ad92f0efa086fb66cf3eae6648483c263ebf2393f7a76c4abf910cb76f71d90906b3a languageName: node linkType: hard @@ -69,7 +69,7 @@ __metadata: version: 0.0.0-use.local resolution: "@acala-network/eth-providers@workspace:packages/eth-providers" dependencies: - "@acala-network/api": 6.1.0 + "@acala-network/api": ^6.1.3 "@acala-network/contracts": 4.3.4 "@acala-network/eth-transactions": "workspace:*" "@types/bn.js": ~5.1.0 @@ -83,7 +83,7 @@ __metadata: lru-cache: ~7.8.2 vitest: 0.34.2 peerDependencies: - "@acala-network/api": 6.1.0 + "@acala-network/api": ^6.1.3 "@polkadot/api": ^10.11.1 languageName: unknown linkType: soft @@ -147,12 +147,12 @@ __metadata: languageName: unknown linkType: soft -"@acala-network/types@npm:6.1.0": - version: 6.1.0 - resolution: "@acala-network/types@npm:6.1.0" +"@acala-network/types@npm:6.1.3": + version: 6.1.3 + resolution: "@acala-network/types@npm:6.1.3" peerDependencies: - "@polkadot/api": ^10.9.1 - checksum: 52790bf0e75ceaa2cf8533c87182b362b5da6c27055767ac535dafbcc207bd2f5ddfc7a3582d0d14e40cb5b52ef66848222ed620777b6c874c9c9936db2b300e + "@polkadot/api": ^12 + checksum: e53c202a3388a23aad5613402b7ca8db35105f609a786bde18ee84f5857130ddf57bccf42e0899b4033f2e973b481270fe23aa105da458442090451ff650df68 languageName: node linkType: hard From e38535d288821465b25b5c04efa6138767cf5db4 Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Wed, 24 Jul 2024 18:52:30 +0800 Subject: [PATCH 3/6] revert unrelated change --- scripts/wormhole-bulk-attest/yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/wormhole-bulk-attest/yarn.lock b/scripts/wormhole-bulk-attest/yarn.lock index 8cce87695..275555aa0 100644 --- a/scripts/wormhole-bulk-attest/yarn.lock +++ b/scripts/wormhole-bulk-attest/yarn.lock @@ -3415,7 +3415,7 @@ __metadata: "fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=18f3a7" dependencies: node-gyp: latest conditions: os=darwin @@ -5121,7 +5121,7 @@ __metadata: "resolve@patch:resolve@^1.0.0#~builtin, resolve@patch:resolve@^1.1.6#~builtin": version: 1.22.1 - resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=c3c19d" + resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=07638b" dependencies: is-core-module: ^2.9.0 path-parse: ^1.0.7 @@ -5944,11 +5944,11 @@ __metadata: "typescript@patch:typescript@^4.9.4#~builtin": version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=289587" + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=701156" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 1f8f3b6aaea19f0f67cba79057674ba580438a7db55057eb89cc06950483c5d632115c14077f6663ea76fd09fce3c190e6414bb98582ec80aa5a4eaf345d5b68 + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 languageName: node linkType: hard From 2ba7725048ae124089b9db152dde60c8a2cb7f5f Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Wed, 24 Jul 2024 18:53:54 +0800 Subject: [PATCH 4/6] revert --- scripts/wormhole-bulk-attest/src/manual.ts | 30 ---------------------- 1 file changed, 30 deletions(-) delete mode 100644 scripts/wormhole-bulk-attest/src/manual.ts diff --git a/scripts/wormhole-bulk-attest/src/manual.ts b/scripts/wormhole-bulk-attest/src/manual.ts deleted file mode 100644 index 3980db306..000000000 --- a/scripts/wormhole-bulk-attest/src/manual.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { AcalaJsonRpcProvider } from "@acala-network/eth-providers"; -import { createWrappedOnEth, getEmitterAddressEth, getSignedVAA } from "@certusone/wormhole-sdk"; -import { Wallet } from "ethers"; -import dotenv from 'dotenv'; -import { NodeHttpTransport } from "@improbable-eng/grpc-web-node-http-transport"; - -dotenv.config(); - -const key = process.env.KEY; -if (!key) throw new Error('no key!'); - -(async () => { - const srcTokenBridgeAddr = '0xDB5492265f6038831E89f495670FF909aDe94bd9'; - const emitterAddress = getEmitterAddressEth(srcTokenBridgeAddr); - const sepoliaWhChainId = 10002; - const signedVaa = await getSignedVAA( - 'https://api.testnet.wormholescan.io', - sepoliaWhChainId, - emitterAddress, - "3270", - { transport: NodeHttpTransport() } - ) - console.log(signedVaa) - - const dstTokenBridgeAddr = '0xe157115ef34c93145Fec2FE53706846853B07F42'; - const provider = new AcalaJsonRpcProvider('https://eth-rpc-acala-testnet.aca-staging.network'); - const wallet = new Wallet(key, provider); - const receipt = await createWrappedOnEth(dstTokenBridgeAddr, wallet, signedVaa.vaaBytes); - console.log(receipt) -})() \ No newline at end of file From ac07392a30ea41dd7a2210ba82feba65e775a270 Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Tue, 6 Aug 2024 11:34:38 +0800 Subject: [PATCH 5/6] polish --- packages/bodhi/src/utils.ts | 6 +- packages/eth-providers/src/consts.ts | 97 ------------- packages/eth-providers/src/consts/gas.ts | 14 ++ packages/eth-providers/src/consts/index.ts | 5 + packages/eth-providers/src/consts/misc.ts | 16 +++ packages/eth-providers/src/consts/msgs.ts | 26 ++++ packages/eth-providers/src/consts/trace.ts | 152 ++++++++++++++++++++ packages/eth-providers/src/consts/tx.ts | 23 +++ packages/eth-providers/src/utils/trace.ts | 157 +-------------------- 9 files changed, 240 insertions(+), 256 deletions(-) delete mode 100644 packages/eth-providers/src/consts.ts create mode 100644 packages/eth-providers/src/consts/gas.ts create mode 100644 packages/eth-providers/src/consts/index.ts create mode 100644 packages/eth-providers/src/consts/misc.ts create mode 100644 packages/eth-providers/src/consts/msgs.ts create mode 100644 packages/eth-providers/src/consts/trace.ts create mode 100644 packages/eth-providers/src/consts/tx.ts diff --git a/packages/bodhi/src/utils.ts b/packages/bodhi/src/utils.ts index 3b45e93bf..22e79a074 100644 --- a/packages/bodhi/src/utils.ts +++ b/packages/bodhi/src/utils.ts @@ -1,15 +1,11 @@ -/* eslint-disable prefer-promise-reject-errors */ -import { BigNumber } from '@ethersproject/bignumber'; import { BodhiProvider } from '@acala-network/eth-providers'; -import { BodhiSigner } from './BodhiSigner'; import { BytesLike } from '@ethersproject/bytes'; import { KeyringPair } from '@polkadot/keyring/types'; import { WsProvider } from '@polkadot/api'; import { bufferToU8a, isBuffer, isU8a, u8aToHex } from '@polkadot/util'; import { createTestPairs } from '@polkadot/keyring'; -export const U32MAX = BigNumber.from('0xffffffff'); -export const U64MAX = BigNumber.from('0xffffffffffffffff'); +import { BodhiSigner } from './BodhiSigner'; export const dataToString = (bytes: BytesLike): string => { if (isBuffer(bytes)) { diff --git a/packages/eth-providers/src/consts.ts b/packages/eth-providers/src/consts.ts deleted file mode 100644 index 5c0e9258d..000000000 --- a/packages/eth-providers/src/consts.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { BigNumber } from '@ethersproject/bignumber'; - -export const ZERO = 0; -export const BIGNUMBER_ONE = BigNumber.from(1); -export const EMPTY_HEX_STRING = '0x'; - -export const BIGNUMBER_ZERO = BigNumber.from(ZERO); - -export const GAS_PRICE = BIGNUMBER_ONE; -export const MAX_FEE_PER_GAS = BIGNUMBER_ONE; -export const MAX_PRIORITY_FEE_PER_GAS = BIGNUMBER_ONE; -export const U32MAX = BigNumber.from('0xffffffff'); -export const U64MAX = BigNumber.from('0xffffffffffffffff'); - -export const DUMMY_BLOCK_HASH = '0xdummydummy'; -export const DUMMY_ADDRESS = '0x1111111111333333333355555555558888888888'; -export const DUMMY_LOGS_BLOOM = - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; -export const DUMMY_V = '0x25'; -export const DUMMY_R = '0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea'; -export const DUMMY_S = '0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c'; -export const DUMMY_V_R_S = { - v: DUMMY_V, - r: DUMMY_R, - s: DUMMY_S, -}; -export const DUMMY_BLOCK_NONCE = '0x0000000000000000'; -export const ZERO_BLOCK_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000'; -export const EMTPY_UNCLE_HASH = '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'; -export const EMTPY_UNCLES = []; -export const ERROR_PATTERN = [ - // Assume that Error is nested only once - /execution fatal: Module\(ModuleError { index: (\d+), error: \[(\d+), 0, 0, 0\], message: None }\)/, - /execution fatal: Module\(ModuleError { index: (\d+), error: (\d+), message: None }\)/, -]; -export const ERC20_ABI = [ - // Read-Only Functions - 'function balanceOf(address owner) view returns (uint256)', - 'function decimals() view returns (uint8)', - 'function symbol() view returns (string)', - - // Authenticated Functions - 'function transfer(address to, uint amount) returns (bool)', - - // Events - 'event Transfer(address indexed from, address indexed to, uint amount)', -]; - -export const LOCAL_MODE_MSG = ` - ------------------------------- - 🔨 local development mode is ON - ❌ don't use it for production! - ------------------------------- -`; - -export const PROD_MODE_MSG = ` - ------------------------------------------ - ⚡️ running in production (standard) mode ⚡️ - ------------------------------------------ -`; - -export const SAFE_MODE_WARNING_MSG = ` - ------------------------------- WARNING ----------------------------- - 🔒 SafeMode is ON, and RPCs behave very differently than usual world! - ❗ This mode is DEPRECATED, please use \`finalized\` block tag - --------------------------------------------------------------------- -`; - -export const CACHE_SIZE_WARNING = ` - ------------------- WARNING ------------------- - Max cached blocks is big, please be cautious! - If memory exploded, try decrease MAX_CACHE_SIZE - ----------------------------------------------- -`; - -export const ORPHAN_TX_DEFAULT_INFO = { - value: '0x0', - gas: 2_100_000, - input: '0x', - nonce: 0, - ...DUMMY_V_R_S, -}; - -export const BLOCK_GAS_LIMIT = 29_990_016; -export const BLOCK_STORAGE_LIMIT = 3_670_016; -export const MAX_GAS_LIMIT_CC = 21; // log2(BLOCK_STORAGE_LIMIT) - -export const ONE_GWEI = 1_000_000_000n; -export const TEN_GWEI = ONE_GWEI * 10n; -export const ONE_HUNDRED_GWEI = ONE_GWEI * 100n; -export const ONE_THOUSAND_GWEI = ONE_GWEI * 1000n; - -export const GAS_MASK = 100000; -export const STORAGE_MASK = 100; -export const GAS_LIMIT_CHUNK = BigNumber.from(30000); - -export const U32_MAX = 4_294_967_295n; diff --git a/packages/eth-providers/src/consts/gas.ts b/packages/eth-providers/src/consts/gas.ts new file mode 100644 index 000000000..52257c26a --- /dev/null +++ b/packages/eth-providers/src/consts/gas.ts @@ -0,0 +1,14 @@ +import { BigNumber } from 'ethers'; + +export const BLOCK_GAS_LIMIT = 29_990_016; +export const BLOCK_STORAGE_LIMIT = 3_670_016; +export const MAX_GAS_LIMIT_CC = 21; // log2(BLOCK_STORAGE_LIMIT) + +export const ONE_GWEI = 1_000_000_000n; +export const TEN_GWEI = ONE_GWEI * 10n; +export const ONE_HUNDRED_GWEI = ONE_GWEI * 100n; +export const ONE_THOUSAND_GWEI = ONE_GWEI * 1000n; + +export const GAS_MASK = 100000; +export const STORAGE_MASK = 100; +export const GAS_LIMIT_CHUNK = BigNumber.from(30000); diff --git a/packages/eth-providers/src/consts/index.ts b/packages/eth-providers/src/consts/index.ts new file mode 100644 index 000000000..9b5fc84aa --- /dev/null +++ b/packages/eth-providers/src/consts/index.ts @@ -0,0 +1,5 @@ +export * from './gas'; +export * from './misc'; +export * from './msgs'; +export * from './trace'; +export * from './tx'; diff --git a/packages/eth-providers/src/consts/misc.ts b/packages/eth-providers/src/consts/misc.ts new file mode 100644 index 000000000..8ade559c3 --- /dev/null +++ b/packages/eth-providers/src/consts/misc.ts @@ -0,0 +1,16 @@ +import { BigNumber } from '@ethersproject/bignumber'; + +export const ZERO = 0; +export const EMPTY_HEX_STRING = '0x'; + +export const BIGNUMBER_ZERO = BigNumber.from(ZERO); +export const U32_MAX = 4_294_967_295n; + +export const U32MAX = BigNumber.from('0xffffffff'); +export const U64MAX = BigNumber.from('0xffffffffffffffff'); + +export const ERROR_PATTERN = [ + // Assume that Error is nested only once + /execution fatal: Module\(ModuleError { index: (\d+), error: \[(\d+), 0, 0, 0\], message: None }\)/, + /execution fatal: Module\(ModuleError { index: (\d+), error: (\d+), message: None }\)/, +]; diff --git a/packages/eth-providers/src/consts/msgs.ts b/packages/eth-providers/src/consts/msgs.ts new file mode 100644 index 000000000..d1527edeb --- /dev/null +++ b/packages/eth-providers/src/consts/msgs.ts @@ -0,0 +1,26 @@ +export const LOCAL_MODE_MSG = ` + ------------------------------- + 🔨 local development mode is ON + ❌ don't use it for production! + ------------------------------- +`; + +export const PROD_MODE_MSG = ` + ------------------------------------------ + ⚡️ running in production (standard) mode ⚡️ + ------------------------------------------ +`; + +export const SAFE_MODE_WARNING_MSG = ` + ------------------------------- WARNING ----------------------------- + 🔒 SafeMode is ON, and RPCs behave very differently than usual world! + ❗ This mode is DEPRECATED, please use \`finalized\` block tag + --------------------------------------------------------------------- +`; + +export const CACHE_SIZE_WARNING = ` + ------------------- WARNING ------------------- + Max cached blocks is big, please be cautious! + If memory exploded, try decrease MAX_CACHE_SIZE + ----------------------------------------------- +`; diff --git a/packages/eth-providers/src/consts/trace.ts b/packages/eth-providers/src/consts/trace.ts new file mode 100644 index 000000000..f05a84b38 --- /dev/null +++ b/packages/eth-providers/src/consts/trace.ts @@ -0,0 +1,152 @@ +export const OPNAME_TABLE = { + '0x00': 'STOP', + '0x01': 'ADD', + '0x02': 'MUL', + '0x03': 'SUB', + '0x04': 'DIV', + '0x05': 'SDIV', + '0x06': 'MOD', + '0x07': 'SMOD', + '0x08': 'ADDMOD', + '0x09': 'MULMOD', + '0x0a': 'EXP', + '0x0b': 'SIGNEXTEND', + '0x10': 'LT', + '0x11': 'GT', + '0x12': 'SLT', + '0x13': 'SGT', + '0x14': 'EQ', + '0x15': 'ISZERO', + '0x16': 'AND', + '0x17': 'OR', + '0x18': 'XOR', + '0x19': 'NOT', + '0x1a': 'BYTE', + '0x35': 'CALLDATALOAD', + '0x36': 'CALLDATASIZE', + '0x37': 'CALLDATACOPY', + '0x38': 'CODESIZE', + '0x39': 'CODECOPY', + '0x1b': 'SHL', + '0x1c': 'SHR', + '0x1d': 'SAR', + '0x50': 'POP', + '0x51': 'MLOAD', + '0x52': 'MSTORE', + '0x53': 'MSTORE8', + '0x56': 'JUMP', + '0x57': 'JUMPI', + '0x58': 'PC', + '0x59': 'MSIZE', + '0x5b': 'JUMPDEST', + '0x5f': 'PUSH0', + '0x60': 'PUSH1', + '0x61': 'PUSH2', + '0x62': 'PUSH3', + '0x63': 'PUSH4', + '0x64': 'PUSH5', + '0x65': 'PUSH6', + '0x66': 'PUSH7', + '0x67': 'PUSH8', + '0x68': 'PUSH9', + '0x69': 'PUSH10', + '0x6a': 'PUSH11', + '0x6b': 'PUSH12', + '0x6c': 'PUSH13', + '0x6d': 'PUSH14', + '0x6e': 'PUSH15', + '0x6f': 'PUSH16', + '0x70': 'PUSH17', + '0x71': 'PUSH18', + '0x72': 'PUSH19', + '0x73': 'PUSH20', + '0x74': 'PUSH21', + '0x75': 'PUSH22', + '0x76': 'PUSH23', + '0x77': 'PUSH24', + '0x78': 'PUSH25', + '0x79': 'PUSH26', + '0x7a': 'PUSH27', + '0x7b': 'PUSH28', + '0x7c': 'PUSH29', + '0x7d': 'PUSH30', + '0x7e': 'PUSH31', + '0x7f': 'PUSH32', + '0x80': 'DUP1', + '0x81': 'DUP2', + '0x82': 'DUP3', + '0x83': 'DUP4', + '0x84': 'DUP5', + '0x85': 'DUP6', + '0x86': 'DUP7', + '0x87': 'DUP8', + '0x88': 'DUP9', + '0x89': 'DUP10', + '0x8a': 'DUP11', + '0x8b': 'DUP12', + '0x8c': 'DUP13', + '0x8d': 'DUP14', + '0x8e': 'DUP15', + '0x8f': 'DUP16', + '0x90': 'SWAP1', + '0x91': 'SWAP2', + '0x92': 'SWAP3', + '0x93': 'SWAP4', + '0x94': 'SWAP5', + '0x95': 'SWAP6', + '0x96': 'SWAP7', + '0x97': 'SWAP8', + '0x98': 'SWAP9', + '0x99': 'SWAP10', + '0x9a': 'SWAP11', + '0x9b': 'SWAP12', + '0x9c': 'SWAP13', + '0x9d': 'SWAP14', + '0x9e': 'SWAP15', + '0x9f': 'SWAP16', + '0xf3': 'RETURN', + '0xfd': 'REVERT', + '0xfe': 'INVALID', + '0xef': 'EOFMAGIC', + '0x20': 'SHA3', + '0x30': 'ADDRESS', + '0x31': 'BALANCE', + '0x47': 'SELFBALANCE', + '0x48': 'BASEFEE', + '0x32': 'ORIGIN', + '0x33': 'CALLER', + '0x34': 'CALLVALUE', + '0x3a': 'GASPRICE', + '0x3b': 'EXTCODESIZE', + '0x3c': 'EXTCODECOPY', + '0x3f': 'EXTCODEHASH', + '0x3d': 'RETURNDATASIZE', + '0x3e': 'RETURNDATACOPY', + '0x40': 'BLOCKHASH', + '0x41': 'COINBASE', + '0x42': 'TIMESTAMP', + '0x43': 'NUMBER', + '0x44': 'DIFFICULTY', + '0x45': 'GASLIMIT', + '0x54': 'SLOAD', + '0x55': 'SSTORE', + '0x5a': 'GAS', + '0xa0': 'LOG0', + '0xa1': 'LOG1', + '0xa2': 'LOG2', + '0xa3': 'LOG3', + '0xa4': 'LOG4', + '0xf0': 'CREATE', + '0xf5': 'CREATE2', + '0xf1': 'CALL', + '0xf2': 'CALLCODE', + '0xf4': 'DELEGATECALL', + '0xfa': 'STATICCALL', + '0xff': 'SUICIDE', + '0x46': 'CHAINID', +}; + +export const opName = (opCode: number): string => { + const opCodeHex = `0x${opCode.toString(16).padStart(2, '0')}`; + return OPNAME_TABLE[opCodeHex] ?? opCodeHex; +}; diff --git a/packages/eth-providers/src/consts/tx.ts b/packages/eth-providers/src/consts/tx.ts new file mode 100644 index 000000000..198f6d2b6 --- /dev/null +++ b/packages/eth-providers/src/consts/tx.ts @@ -0,0 +1,23 @@ +export const DUMMY_ADDRESS = '0x1111111111333333333355555555558888888888'; +export const DUMMY_LOGS_BLOOM = + '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; +export const DUMMY_V = '0x25'; +export const DUMMY_R = '0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea'; +export const DUMMY_S = '0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c'; +export const DUMMY_V_R_S = { + v: DUMMY_V, + r: DUMMY_R, + s: DUMMY_S, +}; +export const DUMMY_BLOCK_NONCE = '0x0000000000000000'; +export const ZERO_BLOCK_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000'; +export const EMTPY_UNCLE_HASH = '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'; +export const EMTPY_UNCLES = []; + +export const ORPHAN_TX_DEFAULT_INFO = { + value: '0x0', + gas: 2_100_000, + input: '0x', + nonce: 0, + ...DUMMY_V_R_S, +}; diff --git a/packages/eth-providers/src/utils/trace.ts b/packages/eth-providers/src/utils/trace.ts index 730ff9d6d..d6e3acf44 100644 --- a/packages/eth-providers/src/utils/trace.ts +++ b/packages/eth-providers/src/utils/trace.ts @@ -3,6 +3,8 @@ import { Extrinsic } from '@polkadot/types/interfaces'; import { HexString } from '@polkadot/util/types'; import { IExtrinsic } from '@polkadot/types/types'; +import { opName } from '../consts'; + export type CallTrace = { type: 'CALL' | 'CALLCODE' | 'STATICCALL' | 'DELEGATECALL' | 'CREATE' | 'SUICIDE'; from: HexString; @@ -39,159 +41,6 @@ export enum TracerType { OpcodeTracer = 'opcodeTracer' } -export const OPNAME_TABLE = { - '0x00': 'STOP', - '0x01': 'ADD', - '0x02': 'MUL', - '0x03': 'SUB', - '0x04': 'DIV', - '0x05': 'SDIV', - '0x06': 'MOD', - '0x07': 'SMOD', - '0x08': 'ADDMOD', - '0x09': 'MULMOD', - '0x0a': 'EXP', - '0x0b': 'SIGNEXTEND', - '0x10': 'LT', - '0x11': 'GT', - '0x12': 'SLT', - '0x13': 'SGT', - '0x14': 'EQ', - '0x15': 'ISZERO', - '0x16': 'AND', - '0x17': 'OR', - '0x18': 'XOR', - '0x19': 'NOT', - '0x1a': 'BYTE', - '0x35': 'CALLDATALOAD', - '0x36': 'CALLDATASIZE', - '0x37': 'CALLDATACOPY', - '0x38': 'CODESIZE', - '0x39': 'CODECOPY', - '0x1b': 'SHL', - '0x1c': 'SHR', - '0x1d': 'SAR', - '0x50': 'POP', - '0x51': 'MLOAD', - '0x52': 'MSTORE', - '0x53': 'MSTORE8', - '0x56': 'JUMP', - '0x57': 'JUMPI', - '0x58': 'PC', - '0x59': 'MSIZE', - '0x5b': 'JUMPDEST', - '0x5f': 'PUSH0', - '0x60': 'PUSH1', - '0x61': 'PUSH2', - '0x62': 'PUSH3', - '0x63': 'PUSH4', - '0x64': 'PUSH5', - '0x65': 'PUSH6', - '0x66': 'PUSH7', - '0x67': 'PUSH8', - '0x68': 'PUSH9', - '0x69': 'PUSH10', - '0x6a': 'PUSH11', - '0x6b': 'PUSH12', - '0x6c': 'PUSH13', - '0x6d': 'PUSH14', - '0x6e': 'PUSH15', - '0x6f': 'PUSH16', - '0x70': 'PUSH17', - '0x71': 'PUSH18', - '0x72': 'PUSH19', - '0x73': 'PUSH20', - '0x74': 'PUSH21', - '0x75': 'PUSH22', - '0x76': 'PUSH23', - '0x77': 'PUSH24', - '0x78': 'PUSH25', - '0x79': 'PUSH26', - '0x7a': 'PUSH27', - '0x7b': 'PUSH28', - '0x7c': 'PUSH29', - '0x7d': 'PUSH30', - '0x7e': 'PUSH31', - '0x7f': 'PUSH32', - '0x80': 'DUP1', - '0x81': 'DUP2', - '0x82': 'DUP3', - '0x83': 'DUP4', - '0x84': 'DUP5', - '0x85': 'DUP6', - '0x86': 'DUP7', - '0x87': 'DUP8', - '0x88': 'DUP9', - '0x89': 'DUP10', - '0x8a': 'DUP11', - '0x8b': 'DUP12', - '0x8c': 'DUP13', - '0x8d': 'DUP14', - '0x8e': 'DUP15', - '0x8f': 'DUP16', - '0x90': 'SWAP1', - '0x91': 'SWAP2', - '0x92': 'SWAP3', - '0x93': 'SWAP4', - '0x94': 'SWAP5', - '0x95': 'SWAP6', - '0x96': 'SWAP7', - '0x97': 'SWAP8', - '0x98': 'SWAP9', - '0x99': 'SWAP10', - '0x9a': 'SWAP11', - '0x9b': 'SWAP12', - '0x9c': 'SWAP13', - '0x9d': 'SWAP14', - '0x9e': 'SWAP15', - '0x9f': 'SWAP16', - '0xf3': 'RETURN', - '0xfd': 'REVERT', - '0xfe': 'INVALID', - '0xef': 'EOFMAGIC', - '0x20': 'SHA3', - '0x30': 'ADDRESS', - '0x31': 'BALANCE', - '0x47': 'SELFBALANCE', - '0x48': 'BASEFEE', - '0x32': 'ORIGIN', - '0x33': 'CALLER', - '0x34': 'CALLVALUE', - '0x3a': 'GASPRICE', - '0x3b': 'EXTCODESIZE', - '0x3c': 'EXTCODECOPY', - '0x3f': 'EXTCODEHASH', - '0x3d': 'RETURNDATASIZE', - '0x3e': 'RETURNDATACOPY', - '0x40': 'BLOCKHASH', - '0x41': 'COINBASE', - '0x42': 'TIMESTAMP', - '0x43': 'NUMBER', - '0x44': 'DIFFICULTY', - '0x45': 'GASLIMIT', - '0x54': 'SLOAD', - '0x55': 'SSTORE', - '0x5a': 'GAS', - '0xa0': 'LOG0', - '0xa1': 'LOG1', - '0xa2': 'LOG2', - '0xa3': 'LOG3', - '0xa4': 'LOG4', - '0xf0': 'CREATE', - '0xf5': 'CREATE2', - '0xf1': 'CALL', - '0xf2': 'CALLCODE', - '0xf4': 'DELEGATECALL', - '0xfa': 'STATICCALL', - '0xff': 'SUICIDE', - '0x46': 'CHAINID', -}; - -export const opName = (opCode: number): string => { - const opCodeHex = `0x${opCode.toString(16).padStart(2, '0')}`; - return OPNAME_TABLE[opCodeHex] ?? opCodeHex; -}; - export const traceVM = async ( api: ApiPromise, extrinsic: Extrinsic | IExtrinsic | string | Uint8Array, @@ -218,7 +67,7 @@ export const traceVM = async ( throw new Error('traceVM: invalid outcome'); } - const curSteps = okRes.asSteps.toJSON() as StepRaw[]; + const curSteps = okRes.asSteps.toJSON() as unknown as StepRaw[]; steps = steps.concat( curSteps.map(step => ({ From 69c294f6890eee801241401a948f2367743116b6 Mon Sep 17 00:00:00 2001 From: Shunji Zhan Date: Tue, 6 Aug 2024 17:54:10 +0800 Subject: [PATCH 6/6] polish and add tests --- .../e2e/__snapshots__/trace.test.ts.snap | Bin 0 -> 31751 bytes .../src/__tests__/e2e/trace.test.ts | 44 ++++++++++++++++++ packages/eth-providers/src/base-provider.ts | 9 ++-- packages/eth-providers/src/utils/trace.ts | 10 +++- packages/eth-providers/vitest.config.e2e.ts | 2 +- 5 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 packages/eth-providers/src/__tests__/e2e/__snapshots__/trace.test.ts.snap create mode 100644 packages/eth-providers/src/__tests__/e2e/trace.test.ts diff --git a/packages/eth-providers/src/__tests__/e2e/__snapshots__/trace.test.ts.snap b/packages/eth-providers/src/__tests__/e2e/__snapshots__/trace.test.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..649d90bde7bc05bc60e416934ab924057d794864 GIT binary patch literal 31751 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 literal 0 HcmV?d00001 diff --git a/packages/eth-providers/src/__tests__/e2e/trace.test.ts b/packages/eth-providers/src/__tests__/e2e/trace.test.ts new file mode 100644 index 000000000..673fde5bf --- /dev/null +++ b/packages/eth-providers/src/__tests__/e2e/trace.test.ts @@ -0,0 +1,44 @@ +import { afterAll, describe, expect, it } from 'vitest'; + +import { EvmRpcProvider } from '../../rpc-provider'; + +const LOCAL_NODE_WITH_TRACING = 'ws://localhost:8000'; +const ACALA_SUBQL = 'https://subql-query-acala.aca-api.network'; + +describe('tracing', async () => { + const provider = EvmRpcProvider.from(LOCAL_NODE_WITH_TRACING, { subqlUrl: ACALA_SUBQL }); + await provider.isReady(); + + afterAll(async () => { + await provider.disconnect(); + }); + + describe('trace calls', () => { + const tracerConf = { tracer: 'callTracer' }; + + it('send native token', async () => { + const trace = await provider.traceTx('0x89dd673cd8527943939904cb0d1f11992a9fd60a171ad7588c4dedf8712cfb7c', tracerConf); + expect(trace).to.toMatchSnapshot(); + }); + + it('transfer erc20', async () => { + const trace = await provider.traceTx('0xf93095f41414f28b09866553ba2ac9957d865f32b6d2b0e220b08ff20e47612a', tracerConf); + expect(trace).to.toMatchSnapshot(); + }); + + it('euphrates stake', async () => { + const trace = await provider.traceTx('0x16a70b2202ceb4968dcd1c44ee782a145a51bf016b92cc871b25ca5723ceffc8', tracerConf); + expect(trace).to.toMatchSnapshot(); + }); + + // it('dex swap', async () => { + // const trace = await provider.traceTx('0x42c61da1a663e7c097399b2031d6bc38e0dff083e04de7083e145884bbfe8d9f', tracerConf); + // expect(trace).to.toMatchSnapshot(); + // }); + }); + + // describe('trace opcodes', () => { + // const tracerConf = { tracer: 'opcodeTracer' }; + // }); + +}); diff --git a/packages/eth-providers/src/base-provider.ts b/packages/eth-providers/src/base-provider.ts index d16feabe8..bc99531fd 100644 --- a/packages/eth-providers/src/base-provider.ts +++ b/packages/eth-providers/src/base-provider.ts @@ -2185,13 +2185,12 @@ export abstract class BaseProvider extends AbstractProvider { logger.throwError('traceTx: tx not found', Logger.errors.UNKNOWN_ERROR, { txHash }); } - const { blockHash, transactionIndex } = receipt; - const blockData = await this.api.rpc.chain.getBlock(blockHash); - const evmExtrinsics = blockData.block.extrinsics.filter(isEvmExtrinsic); + const blockData = await this.api.rpc.chain.getBlock(receipt.blockHash); - const targetExtrinsic = evmExtrinsics[transactionIndex]; + const targetExtrinsic = blockData.block.extrinsics.find(ex => ex.hash.toHex() === txHash); if (!targetExtrinsic) { - logger.throwError('traceTx: target extrinsic not found', Logger.errors.UNKNOWN_ERROR, { txHash }); + // if receipt can be found, but no evm extrinsic, it's either orphan or batch tx + logger.throwError('traceTx: tracing for orphan/batch tx is not supported', Logger.errors.UNKNOWN_ERROR, { txHash }); } return traceConf.tracer === TracerType.CallTracer diff --git a/packages/eth-providers/src/utils/trace.ts b/packages/eth-providers/src/utils/trace.ts index d6e3acf44..d8d7a5184 100644 --- a/packages/eth-providers/src/utils/trace.ts +++ b/packages/eth-providers/src/utils/trace.ts @@ -44,7 +44,11 @@ export enum TracerType { export const traceVM = async ( api: ApiPromise, extrinsic: Extrinsic | IExtrinsic | string | Uint8Array, -) => { +): Promise => { + if (!api.call.evmTraceApi) { + throw new Error('traceCall: EVM tracing is not supported by the node'); + } + const pageSize = 10000; const traceConf = { page: 0, @@ -98,6 +102,10 @@ export const traceCall = async ( api: ApiPromise, extrinsic: Extrinsic | IExtrinsic | string | Uint8Array, ): Promise => { + if (!api.call.evmTraceApi) { + throw new Error('traceCall: EVM tracing is not supported by the node'); + } + const traceConf = { CallTracer: null }; const res = await api.call.evmTraceApi.traceExtrinsic(extrinsic, traceConf); if (!res.isOk) { diff --git a/packages/eth-providers/vitest.config.e2e.ts b/packages/eth-providers/vitest.config.e2e.ts index 110cc112c..776e20714 100644 --- a/packages/eth-providers/vitest.config.e2e.ts +++ b/packages/eth-providers/vitest.config.e2e.ts @@ -8,7 +8,7 @@ export default defineConfig({ testTimeout: 300_000, hookTimeout: 60_000, environment: 'jsdom', - exclude: ['src/__tests__/utils.test.ts'], + // exclude: ['src/__tests__/utils.test.ts'], }, plugins: [swc.vite(), tsconfigPaths()], });