gate-evm-tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +239 -0
  3. package/bin/cli.js +9 -0
  4. package/contractInfo.example.json +5 -0
  5. package/dist/commands/check.d.ts +6 -0
  6. package/dist/commands/check.d.ts.map +1 -0
  7. package/dist/commands/check.js +177 -0
  8. package/dist/commands/check.js.map +1 -0
  9. package/dist/commands/sync.d.ts +6 -0
  10. package/dist/commands/sync.d.ts.map +1 -0
  11. package/dist/commands/sync.js +97 -0
  12. package/dist/commands/sync.js.map +1 -0
  13. package/dist/commands/validate.d.ts +6 -0
  14. package/dist/commands/validate.d.ts.map +1 -0
  15. package/dist/commands/validate.js +108 -0
  16. package/dist/commands/validate.js.map +1 -0
  17. package/dist/core/bytecodeChecker.d.ts +105 -0
  18. package/dist/core/bytecodeChecker.d.ts.map +1 -0
  19. package/dist/core/bytecodeChecker.js +413 -0
  20. package/dist/core/bytecodeChecker.js.map +1 -0
  21. package/dist/core/syncUpgradeJson.d.ts +23 -0
  22. package/dist/core/syncUpgradeJson.d.ts.map +1 -0
  23. package/dist/core/syncUpgradeJson.js +260 -0
  24. package/dist/core/syncUpgradeJson.js.map +1 -0
  25. package/dist/core/validateAndGenerateCalldata.d.ts +26 -0
  26. package/dist/core/validateAndGenerateCalldata.d.ts.map +1 -0
  27. package/dist/core/validateAndGenerateCalldata.js +235 -0
  28. package/dist/core/validateAndGenerateCalldata.js.map +1 -0
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +80 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/types.d.ts +41 -0
  34. package/dist/types.d.ts.map +1 -0
  35. package/dist/types.js +2 -0
  36. package/dist/types.js.map +1 -0
  37. package/dist/utils/files.d.ts +18 -0
  38. package/dist/utils/files.d.ts.map +1 -0
  39. package/dist/utils/files.js +75 -0
  40. package/dist/utils/files.js.map +1 -0
  41. package/dist/utils/output.d.ts +14 -0
  42. package/dist/utils/output.d.ts.map +1 -0
  43. package/dist/utils/output.js +67 -0
  44. package/dist/utils/output.js.map +1 -0
  45. package/package.json +60 -0
@@ -0,0 +1,108 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { validateAndGenerateCalldata } from '../core/validateAndGenerateCalldata.js';
4
+ import fs from 'fs-extra';
5
+ import path from 'path';
6
+ import { createRequire } from 'module';
7
+ const require = createRequire(import.meta.url);
8
+ /**
9
+ * 执行升级验证并生成 calldata
10
+ */
11
+ export async function validateUpgrade(options) {
12
+ const spinner = ora();
13
+ try {
14
+ // 1. 验证必需参数
15
+ if (!options.proxy) {
16
+ throw new Error('必须提供代理合约地址(--proxy)');
17
+ }
18
+ if (!options.old) {
19
+ throw new Error('必须提供旧合约名称(--old)');
20
+ }
21
+ if (!options.new) {
22
+ throw new Error('必须提供新合约名称(--new)');
23
+ }
24
+ // 2. 检查是否在 Hardhat 项目中
25
+ const cwd = process.cwd();
26
+ const hardhatConfigExists = fs.existsSync(path.join(cwd, 'hardhat.config.js')) ||
27
+ fs.existsSync(path.join(cwd, 'hardhat.config.ts'));
28
+ if (!hardhatConfigExists) {
29
+ throw new Error('当前目录不是 Hardhat 项目,请在 Hardhat 项目根目录下运行此命令');
30
+ }
31
+ // 3. 如果指定了网络,在加载 Hardhat 之前设置环境变量
32
+ if (options.network) {
33
+ process.env.HARDHAT_NETWORK = options.network;
34
+ spinner.info(`设置网络: ${chalk.cyan(options.network)}`);
35
+ }
36
+ // 4. 动态加载 hardhat
37
+ spinner.start('正在加载 Hardhat 环境...');
38
+ let hre;
39
+ try {
40
+ // 尝试使用 require 加载(适用于大多数项目)
41
+ hre = require('hardhat');
42
+ }
43
+ catch (requireError) {
44
+ // 如果 require 失败,尝试使用 import(适用于 ES 模块项目)
45
+ try {
46
+ const hardhatModule = await import('hardhat');
47
+ hre = hardhatModule.default || hardhatModule;
48
+ }
49
+ catch (importError) {
50
+ throw requireError;
51
+ }
52
+ }
53
+ spinner.succeed(`Hardhat 环境已加载 (网络: ${chalk.cyan(hre.network.name)})`);
54
+ // 5. 执行验证
55
+ console.log('');
56
+ const result = await validateAndGenerateCalldata({
57
+ proxyAddress: options.proxy,
58
+ oldContractName: options.old,
59
+ newContractName: options.new,
60
+ outputPath: options.output,
61
+ hre
62
+ });
63
+ // 6. 显示成功信息
64
+ console.log(chalk.green.bold('\n✅ 验证成功!\n'));
65
+ console.log(chalk.cyan('升级信息摘要:'));
66
+ console.log(chalk.gray('─'.repeat(60)));
67
+ console.log(`${chalk.white('代理合约:')} ${chalk.yellow(result.proxyAddress)}`);
68
+ console.log(`${chalk.white('旧实现:')} ${chalk.gray(result.oldImplementation)}`);
69
+ console.log(`${chalk.white('新实现:')} ${chalk.green(result.newImplementation)}`);
70
+ console.log('');
71
+ console.log(`${chalk.white('Calldata:')} ${chalk.cyan(result.calldata)}`);
72
+ console.log('');
73
+ console.log(`${chalk.white('输出文件:')} ${chalk.gray(result.outputFile)}`);
74
+ console.log(chalk.gray('─'.repeat(60)));
75
+ }
76
+ catch (error) {
77
+ spinner.fail('验证失败');
78
+ // 检测常见的错误并给出友好提示
79
+ if (error.message && error.message.includes('Cannot find module') &&
80
+ error.message.includes('hardhat/config')) {
81
+ console.error(chalk.red('\n❌ Hardhat 配置文件导入错误\n'));
82
+ console.error(chalk.yellow('问题:你的 hardhat.config.ts 中的导入语句与当前环境不兼容。\n'));
83
+ console.error(chalk.cyan('💡 解决方案:\n'));
84
+ console.error(chalk.white('方案 1:修改导入语句(推荐)'));
85
+ console.error(chalk.gray(' 将 hardhat.config.ts 中的导入语句改为:'));
86
+ console.error(chalk.green(' import { HardhatUserConfig } from "hardhat/config.js"'));
87
+ console.error(chalk.gray(' (添加 .js 扩展名)\n'));
88
+ }
89
+ else if (error.message && error.message.includes('not found in config')) {
90
+ console.error(chalk.red('\n❌ 网络配置错误\n'));
91
+ console.error(chalk.yellow(`网络 "${options.network}" 未在 hardhat.config 中配置\n`));
92
+ console.error(chalk.cyan('💡 解决方案:\n'));
93
+ console.error(chalk.white('请在 hardhat.config 中添加该网络的配置'));
94
+ }
95
+ else if (error.message && error.message.includes('升级存在风险')) {
96
+ console.error(chalk.red('\n❌ 升级安全性验证失败\n'));
97
+ console.error(chalk.yellow('请查看上面的详细错误信息,并修复后重试'));
98
+ }
99
+ else {
100
+ console.error(chalk.red('\n错误:'), error.message);
101
+ if (error.stack && process.env.DEBUG) {
102
+ console.error(chalk.gray(error.stack));
103
+ }
104
+ }
105
+ process.exit(1);
106
+ }
107
+ }
108
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ import { ContractConfig, CheckResult } from '../types.js';
2
+ type HardhatRuntimeEnvironment = any;
3
+ interface LocalBytecodeData {
4
+ bytecode: string;
5
+ abi: any[];
6
+ }
7
+ interface ConstructorInput {
8
+ type: string;
9
+ name: string;
10
+ inputs?: ConstructorInput[];
11
+ }
12
+ interface Constructor {
13
+ type: string;
14
+ inputs: ConstructorInput[];
15
+ }
16
+ interface ComparisonResult {
17
+ matches: boolean;
18
+ reason: string;
19
+ constructorDetails?: any[];
20
+ }
21
+ interface ConstructorCheckResult {
22
+ isConstructorDiff: boolean;
23
+ reason: string;
24
+ differences?: any[];
25
+ diffCount?: number;
26
+ }
27
+ export declare class BytecodeChecker {
28
+ private hre;
29
+ private addressData;
30
+ constructor(hre: HardhatRuntimeEnvironment, addressData: ContractConfig);
31
+ /**
32
+ * 获取链上合约的bytecode
33
+ */
34
+ getOnchainBytecode(address: string, network: string): Promise<string>;
35
+ /**
36
+ * 获取本地编译的bytecode(使用deployedBytecode)
37
+ */
38
+ getLocalBytecode(contractName: string): Promise<LocalBytecodeData>;
39
+ /**
40
+ * 检查是否是constructor参数差异(主要是immutable变量)
41
+ */
42
+ checkConstructorParamsDifference(onchainCode: string, localCode: string, abi?: any[] | null): ConstructorCheckResult;
43
+ /**
44
+ * 基于ABI的智能分析
45
+ */
46
+ smartAnalyzeWithABI(onchainCode: string, localCode: string, abi: any[]): ConstructorCheckResult;
47
+ /**
48
+ * 检测immutable变量
49
+ */
50
+ detectImmutableVariables(onchainCode: string, localCode: string): ConstructorCheckResult;
51
+ /**
52
+ * 检测constructor参数
53
+ */
54
+ detectConstructorParams(onchainCode: string, localCode: string, constructor: Constructor): ConstructorCheckResult;
55
+ /**
56
+ * 去重参数:按顺序匹配参数
57
+ */
58
+ deduplicateParams(allMatches: any[], params: ConstructorInput[]): any[];
59
+ /**
60
+ * 查找地址参数
61
+ */
62
+ findAddressParams(onchainCode: string, localCode: string, param: ConstructorInput): any[];
63
+ /**
64
+ * 查找数值参数
65
+ */
66
+ findUintParams(onchainCode: string, localCode: string, param: ConstructorInput): any[];
67
+ /**
68
+ * 回退分析方法
69
+ */
70
+ fallbackAnalyze(onchainCode: string, localCode: string): ConstructorCheckResult;
71
+ /**
72
+ * 标准化bytecode(移除metadata)
73
+ */
74
+ normalizeBytecode(bytecode: string): string;
75
+ /**
76
+ * 比较两个bytecode
77
+ */
78
+ compareBytecode(onchainBytecode: string, localBytecode: string, abi?: any[] | null): ComparisonResult;
79
+ /**
80
+ * 检查单个合约
81
+ */
82
+ checkContract(contractInfo: {
83
+ name: string;
84
+ address: string;
85
+ network: string;
86
+ }): Promise<CheckResult>;
87
+ /**
88
+ * 检查指定网络的合约
89
+ */
90
+ checkNetworkContracts(networkName: string): Promise<CheckResult[]>;
91
+ /**
92
+ * 检查指定合约(跨所有网络)
93
+ */
94
+ checkSpecificContract(contractName: string): Promise<CheckResult[]>;
95
+ /**
96
+ * 检查所有合约
97
+ */
98
+ checkAllContracts(): Promise<CheckResult[]>;
99
+ /**
100
+ * 生成以network为key,contractName为二级key的结果结构
101
+ */
102
+ generateNetworkContractResults(results: CheckResult[]): Record<string, Record<string, any>>;
103
+ }
104
+ export {};
105
+ //# sourceMappingURL=bytecodeChecker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bytecodeChecker.d.ts","sourceRoot":"","sources":["../../src/core/bytecodeChecker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1D,KAAK,yBAAyB,GAAG,GAAG,CAAC;AAErC,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,GAAG,EAAE,CAAC;CACZ;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,GAAG,EAAE,CAAC;CAC5B;AAED,UAAU,sBAAsB;IAC9B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAA4B;IACvC,OAAO,CAAC,WAAW,CAAiB;gBAExB,GAAG,EAAE,yBAAyB,EAAE,WAAW,EAAE,cAAc;IAKvE;;OAEG;IACG,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgB3E;;OAEG;IACG,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAYxE;;OAEG;IACH,gCAAgC,CAC9B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,GAAG,EAAE,GAAG,IAAW,GACvB,sBAAsB;IAmBzB;;OAEG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,sBAAsB;IAU/F;;OAEG;IACH,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,sBAAsB;IAqDxF;;OAEG;IACH,uBAAuB,CACrB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,WAAW,GACvB,sBAAsB;IA6BzB;;OAEG;IACH,iBAAiB,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,GAAG,EAAE;IAgCvE;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,GAAG,EAAE;IAqCzF;;OAEG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,GAAG,EAAE;IA+BtF;;OAEG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,sBAAsB;IAoB/E;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAiB3C;;OAEG;IACH,eAAe,CACb,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACrB,GAAG,GAAE,GAAG,EAAE,GAAG,IAAW,GACvB,gBAAgB;IA4BnB;;OAEG;IACG,aAAa,CAAC,YAAY,EAAE;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,WAAW,CAAC;IA+BxB;;OAEG;IACG,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAsBxE;;OAEG;IACG,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAuBzE;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAejD;;OAEG;IACH,8BAA8B,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAwB5F"}
@@ -0,0 +1,413 @@
1
+ export class BytecodeChecker {
2
+ hre;
3
+ addressData;
4
+ constructor(hre, addressData) {
5
+ this.hre = hre;
6
+ this.addressData = addressData;
7
+ }
8
+ /**
9
+ * 获取链上合约的bytecode
10
+ */
11
+ async getOnchainBytecode(address, network) {
12
+ try {
13
+ const networkConfig = this.hre.config.networks[network];
14
+ if (!networkConfig) {
15
+ throw new Error(`Network ${network} not found in hardhat config`);
16
+ }
17
+ const ethers = this.hre.ethers;
18
+ const provider = new ethers.JsonRpcProvider(networkConfig.url);
19
+ const bytecode = await provider.getCode(address);
20
+ return bytecode;
21
+ }
22
+ catch (error) {
23
+ throw new Error(`Failed to get onchain bytecode: ${error.message}`);
24
+ }
25
+ }
26
+ /**
27
+ * 获取本地编译的bytecode(使用deployedBytecode)
28
+ */
29
+ async getLocalBytecode(contractName) {
30
+ try {
31
+ const artifact = await this.hre.artifacts.readArtifact(contractName);
32
+ return {
33
+ bytecode: artifact.deployedBytecode,
34
+ abi: artifact.abi
35
+ };
36
+ }
37
+ catch (error) {
38
+ throw new Error(`Failed to get local bytecode: ${error.message}`);
39
+ }
40
+ }
41
+ /**
42
+ * 检查是否是constructor参数差异(主要是immutable变量)
43
+ */
44
+ checkConstructorParamsDifference(onchainCode, localCode, abi = null) {
45
+ if (onchainCode.length !== localCode.length) {
46
+ return { isConstructorDiff: false, reason: "长度不同" };
47
+ }
48
+ if (onchainCode === localCode) {
49
+ return { isConstructorDiff: false, reason: "完全相同" };
50
+ }
51
+ if (abi) {
52
+ const smartAnalysis = this.smartAnalyzeWithABI(onchainCode, localCode, abi);
53
+ if (smartAnalysis.isConstructorDiff) {
54
+ return smartAnalysis;
55
+ }
56
+ }
57
+ return this.fallbackAnalyze(onchainCode, localCode);
58
+ }
59
+ /**
60
+ * 基于ABI的智能分析
61
+ */
62
+ smartAnalyzeWithABI(onchainCode, localCode, abi) {
63
+ const constructor = abi.find(item => item.type === 'constructor');
64
+ if (!constructor || !constructor.inputs || constructor.inputs.length === 0) {
65
+ return this.detectImmutableVariables(onchainCode, localCode);
66
+ }
67
+ return this.detectConstructorParams(onchainCode, localCode, constructor);
68
+ }
69
+ /**
70
+ * 检测immutable变量
71
+ */
72
+ detectImmutableVariables(onchainCode, localCode) {
73
+ const matches = [];
74
+ const zeroPattern64 = /0{64}/g;
75
+ let match;
76
+ while ((match = zeroPattern64.exec(localCode)) !== null) {
77
+ const position = match.index;
78
+ const onchainSegment = onchainCode.substr(position, 64);
79
+ const localSegment = match[0];
80
+ if (onchainSegment !== localSegment && /^[0-9a-f]{64}$/i.test(onchainSegment)) {
81
+ if (onchainSegment.startsWith('000000000000000000000000') &&
82
+ onchainSegment.substr(24, 40) !== '0000000000000000000000000000000000000000') {
83
+ const address = onchainSegment.substr(24, 40);
84
+ matches.push({
85
+ position: position,
86
+ length: 64,
87
+ onchainValue: onchainSegment,
88
+ localValue: localSegment,
89
+ type: "address",
90
+ description: `Immutable地址变量: 0x${address}`
91
+ });
92
+ }
93
+ else {
94
+ try {
95
+ const value = BigInt('0x' + onchainSegment);
96
+ matches.push({
97
+ position: position,
98
+ length: 64,
99
+ onchainValue: onchainSegment,
100
+ localValue: localSegment,
101
+ type: "uint256",
102
+ description: `Immutable uint256变量: ${value.toString()}`
103
+ });
104
+ }
105
+ catch (e) {
106
+ // 忽略无法解析的值
107
+ }
108
+ }
109
+ }
110
+ }
111
+ if (matches.length > 0) {
112
+ const descriptions = matches.map(m => m.description).join(", ");
113
+ return {
114
+ isConstructorDiff: true,
115
+ reason: `Immutable变量差异: ${descriptions}`,
116
+ differences: matches,
117
+ diffCount: matches.reduce((sum, m) => sum + m.length, 0)
118
+ };
119
+ }
120
+ return { isConstructorDiff: false, reason: "未检测到immutable变量模式" };
121
+ }
122
+ /**
123
+ * 检测constructor参数
124
+ */
125
+ detectConstructorParams(onchainCode, localCode, constructor) {
126
+ const params = constructor.inputs;
127
+ const allMatches = [];
128
+ for (const param of params) {
129
+ if (param.type === 'address') {
130
+ const addressMatches = this.findAddressParams(onchainCode, localCode, param);
131
+ allMatches.push(...addressMatches);
132
+ }
133
+ else if (param.type.startsWith('uint')) {
134
+ const uintMatches = this.findUintParams(onchainCode, localCode, param);
135
+ allMatches.push(...uintMatches);
136
+ }
137
+ }
138
+ if (allMatches.length > 0) {
139
+ const uniqueParams = this.deduplicateParams(allMatches, params);
140
+ const descriptions = uniqueParams.map(p => p.description).join(", ");
141
+ return {
142
+ isConstructorDiff: true,
143
+ reason: `Constructor参数差异(${params.map(p => `${p.type} ${p.name}`).join(', ')}): ${descriptions}`,
144
+ differences: uniqueParams,
145
+ diffCount: allMatches.reduce((sum, m) => sum + m.length, 0)
146
+ };
147
+ }
148
+ return { isConstructorDiff: false, reason: "未检测到constructor参数模式" };
149
+ }
150
+ /**
151
+ * 去重参数:按顺序匹配参数
152
+ */
153
+ deduplicateParams(allMatches, params) {
154
+ const uniqueAddresses = [];
155
+ const seenAddresses = new Set();
156
+ for (const match of allMatches) {
157
+ const address = match.address || match.onchainValue;
158
+ if (!seenAddresses.has(address)) {
159
+ seenAddresses.add(address);
160
+ uniqueAddresses.push({
161
+ address: address,
162
+ match: match
163
+ });
164
+ }
165
+ }
166
+ const uniqueParams = [];
167
+ const addressParams = params.filter(p => p.type === 'address');
168
+ const reversedAddresses = [...uniqueAddresses].reverse();
169
+ for (let i = 0; i < addressParams.length && i < reversedAddresses.length; i++) {
170
+ const param = addressParams[i];
171
+ const addressInfo = reversedAddresses[i];
172
+ uniqueParams.push({
173
+ ...addressInfo.match,
174
+ description: `${param.name}(${param.type}): 0x${addressInfo.address}`
175
+ });
176
+ }
177
+ return uniqueParams;
178
+ }
179
+ /**
180
+ * 查找地址参数
181
+ */
182
+ findAddressParams(onchainCode, localCode, param) {
183
+ const matches = [];
184
+ const zeroPattern64 = /0{64}/g;
185
+ let match;
186
+ while ((match = zeroPattern64.exec(localCode)) !== null) {
187
+ const position = match.index;
188
+ const onchainSegment = onchainCode.substr(position, 64);
189
+ const localSegment = match[0];
190
+ if (onchainSegment !== localSegment && /^[0-9a-f]{64}$/i.test(onchainSegment)) {
191
+ if (onchainSegment.startsWith('000000000000000000000000')) {
192
+ const address = onchainSegment.substr(24, 40);
193
+ if (address !== '0000000000000000000000000000000000000000') {
194
+ const alreadyExists = matches.some(m => m.address === address && m.position === position);
195
+ if (!alreadyExists) {
196
+ matches.push({
197
+ position: position,
198
+ length: 64,
199
+ onchainValue: onchainSegment,
200
+ localValue: localSegment,
201
+ type: "address",
202
+ address: address,
203
+ description: `${param.name}(${param.type}): 0x${address}`
204
+ });
205
+ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ return matches;
211
+ }
212
+ /**
213
+ * 查找数值参数
214
+ */
215
+ findUintParams(onchainCode, localCode, param) {
216
+ const matches = [];
217
+ const bitSize = param.type === 'uint' ? 256 : parseInt(param.type.replace('uint', ''));
218
+ const hexLength = bitSize / 4;
219
+ const zeroPattern = new RegExp(`0{${hexLength}}`, 'g');
220
+ let match;
221
+ while ((match = zeroPattern.exec(localCode)) !== null) {
222
+ const position = match.index;
223
+ const onchainSegment = onchainCode.substr(position, hexLength);
224
+ if (onchainSegment !== match[0] && new RegExp(`^[0-9a-f]{${hexLength}}$`, 'i').test(onchainSegment)) {
225
+ try {
226
+ const value = BigInt('0x' + onchainSegment);
227
+ matches.push({
228
+ position: position,
229
+ length: hexLength,
230
+ onchainValue: onchainSegment,
231
+ localValue: match[0],
232
+ type: param.type,
233
+ description: `${param.name}(${param.type}): ${value.toString()}`
234
+ });
235
+ }
236
+ catch (e) {
237
+ // 忽略无法解析的值
238
+ }
239
+ }
240
+ }
241
+ return matches;
242
+ }
243
+ /**
244
+ * 回退分析方法
245
+ */
246
+ fallbackAnalyze(onchainCode, localCode) {
247
+ const wethAddress = 'c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
248
+ const zeroAddress = '0000000000000000000000000000000000000000';
249
+ const onchainNormalized = onchainCode.replace(new RegExp(wethAddress, 'g'), zeroAddress);
250
+ if (onchainNormalized === localCode) {
251
+ return {
252
+ isConstructorDiff: true,
253
+ reason: "Constructor参数差异: WETH地址",
254
+ differences: [{ description: `WETH地址: 0x${wethAddress}` }],
255
+ diffCount: 40
256
+ };
257
+ }
258
+ return {
259
+ isConstructorDiff: false,
260
+ reason: "未知代码差异"
261
+ };
262
+ }
263
+ /**
264
+ * 标准化bytecode(移除metadata)
265
+ */
266
+ normalizeBytecode(bytecode) {
267
+ let code = bytecode;
268
+ if (code.startsWith("0x")) {
269
+ code = code.slice(2);
270
+ }
271
+ const metadataMarker = 'a264697066735822';
272
+ const metadataPos = code.indexOf(metadataMarker);
273
+ if (metadataPos > 0) {
274
+ code = code.slice(0, metadataPos);
275
+ }
276
+ return code.toLowerCase();
277
+ }
278
+ /**
279
+ * 比较两个bytecode
280
+ */
281
+ compareBytecode(onchainBytecode, localBytecode, abi = null) {
282
+ const onchainNormalized = this.normalizeBytecode(onchainBytecode);
283
+ const localNormalized = this.normalizeBytecode(localBytecode);
284
+ if (onchainNormalized === localNormalized) {
285
+ return { matches: true, reason: "完全匹配" };
286
+ }
287
+ const constructorCheck = this.checkConstructorParamsDifference(onchainNormalized, localNormalized, abi);
288
+ if (constructorCheck.isConstructorDiff) {
289
+ return {
290
+ matches: true,
291
+ reason: constructorCheck.reason,
292
+ constructorDetails: constructorCheck.differences
293
+ };
294
+ }
295
+ if (onchainNormalized.startsWith(localNormalized)) {
296
+ return { matches: true, reason: "前缀匹配(可能包含constructor参数)" };
297
+ }
298
+ if (localNormalized.startsWith(onchainNormalized)) {
299
+ return { matches: true, reason: "链上代码是本地代码的前缀" };
300
+ }
301
+ return { matches: false, reason: "代码存在显著差异" };
302
+ }
303
+ /**
304
+ * 检查单个合约
305
+ */
306
+ async checkContract(contractInfo) {
307
+ const result = {
308
+ contract: contractInfo.name,
309
+ contractName: contractInfo.name,
310
+ network: contractInfo.network,
311
+ address: contractInfo.address,
312
+ matches: false,
313
+ error: null,
314
+ reason: "",
315
+ onChainBytecodeLength: 0,
316
+ localBytecodeLength: 0
317
+ };
318
+ try {
319
+ const onchainBytecode = await this.getOnchainBytecode(contractInfo.address, contractInfo.network);
320
+ result.onChainBytecodeLength = onchainBytecode.length;
321
+ const localData = await this.getLocalBytecode(contractInfo.name);
322
+ result.localBytecodeLength = localData.bytecode.length;
323
+ const comparison = this.compareBytecode(onchainBytecode, localData.bytecode, localData.abi);
324
+ result.matches = comparison.matches;
325
+ result.reason = comparison.reason;
326
+ }
327
+ catch (error) {
328
+ result.error = error.message;
329
+ }
330
+ return result;
331
+ }
332
+ /**
333
+ * 检查指定网络的合约
334
+ */
335
+ async checkNetworkContracts(networkName) {
336
+ if (!this.addressData[networkName]) {
337
+ throw new Error(`No contracts found for network: ${networkName}`);
338
+ }
339
+ const results = [];
340
+ const contracts = this.addressData[networkName];
341
+ for (const [contractName, address] of Object.entries(contracts)) {
342
+ const contractInfo = {
343
+ name: contractName,
344
+ address: address,
345
+ network: networkName
346
+ };
347
+ const result = await this.checkContract(contractInfo);
348
+ results.push(result);
349
+ }
350
+ return results;
351
+ }
352
+ /**
353
+ * 检查指定合约(跨所有网络)
354
+ */
355
+ async checkSpecificContract(contractName) {
356
+ const results = [];
357
+ for (const [networkName, contracts] of Object.entries(this.addressData)) {
358
+ if (contracts[contractName]) {
359
+ const contractInfo = {
360
+ name: contractName,
361
+ address: contracts[contractName],
362
+ network: networkName
363
+ };
364
+ const result = await this.checkContract(contractInfo);
365
+ results.push(result);
366
+ }
367
+ }
368
+ if (results.length === 0) {
369
+ throw new Error(`Contract ${contractName} not found on any network`);
370
+ }
371
+ return results;
372
+ }
373
+ /**
374
+ * 检查所有合约
375
+ */
376
+ async checkAllContracts() {
377
+ const results = [];
378
+ for (const network of Object.keys(this.addressData)) {
379
+ try {
380
+ const networkResults = await this.checkNetworkContracts(network);
381
+ results.push(...networkResults);
382
+ }
383
+ catch (error) {
384
+ console.log(`⚠️ Skipping network ${network}: ${error.message}`);
385
+ }
386
+ }
387
+ return results;
388
+ }
389
+ /**
390
+ * 生成以network为key,contractName为二级key的结果结构
391
+ */
392
+ generateNetworkContractResults(results) {
393
+ const networkResults = {};
394
+ results.forEach(result => {
395
+ const network = result.network;
396
+ const contractName = result.contractName;
397
+ if (!networkResults[network]) {
398
+ networkResults[network] = {};
399
+ }
400
+ networkResults[network][contractName] = {
401
+ contract: result.contract,
402
+ address: result.address,
403
+ matches: result.matches,
404
+ error: result.error,
405
+ reason: result.reason,
406
+ onChainBytecodeLength: result.onChainBytecodeLength,
407
+ localBytecodeLength: result.localBytecodeLength
408
+ };
409
+ });
410
+ return networkResults;
411
+ }
412
+ }
413
+ //# sourceMappingURL=bytecodeChecker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bytecodeChecker.js","sourceRoot":"","sources":["../../src/core/bytecodeChecker.ts"],"names":[],"mappings":"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"}