Gate 智能合约工具集 - 字节码检查、合约升级验证、合约状态同步
npm install gate-evm-tools🛠️ Gate 智能合约工具集 - 字节码检查、合约升级验证、合约状态同步
``bash进入项目目录
cd evm-checkcode-cli
$3
`bash
登录 NPM(如果还未登录)
npm login输入用户名、密码、邮箱
`$3
`bash
检查包信息
npm pack --dry-run发布包
npm publish如果包名已被占用,可以发布到作用域下
先修改 package.json 中的 name 为 "@your-username/bytecode-checker-cli"
然后执行:
npm publish --access public
`$3
`bash
更新补丁版本(1.0.0 -> 1.0.1)
npm version patch更新小版本(1.0.0 -> 1.1.0)
npm version minor更新大版本(1.0.0 -> 2.0.0)
npm version major发布新版本
npm publish
`二、使用 NPM 包
$3
在你的 Hardhat 项目中安装:
`bash
npm install --save-dev gate-evm-tools
`或全局安装:
`bash
npm install -g gate-evm-tools
`$3
在项目根目录创建
contractInfo.json 文件:`json
{
"eth": {
"Vault": "0x80aaf2e4636c510e067a5d300d8bafd48027addf",
"VaultCrossChainRelay": "0x060194eec4556096baaabd6bf553d2658d6a66ab"
},
"bsc": {
"Vault": "0x2cb7d2603a5f43b9fe79e98f09fe3eec40b6765d",
"VaultCrossChainRelay": "0x23ae3a565e0896866e7725fe6d49fd777359c162"
}
}
`格式说明:
- 第一层 key 是网络名称(必须与
hardhat.config.js 中的网络名称一致)
- 第二层 key 是合约名称(必须与编译的合约名称一致)
- value 是合约地址(可以是代理合约地址,工具会自动检测并获取实现合约地址)支持可升级合约:
如果配置中的地址是 ERC1967 代理合约,工具会自动:
1. 检测该地址是否为代理合约
2. 读取实现合约地址(从 ERC1967 存储槽)
3. 使用实现合约地址进行字节码比对
这意味着你可以直接在配置文件中填写代理合约地址,无需手动查找实现合约地址。
$3
确保
hardhat.config.js 中配置了相应的网络:`javascript
module.exports = {
networks: {
eth: {
url: "https://eth-mainnet.g.alchemy.com/v2/YOUR-API-KEY",
},
bsc: {
url: "https://bsc-dataseed.binance.org/",
}
}
};
`$3
`bash
npx hardhat compile
`$3
#### 📋 查看帮助
`bash
npx gate-tool --help
`#### 🔧 配置修复(推荐首次使用)
如果在使用过程中遇到 Hardhat 配置导入错误,可以使用
fix 命令自动修复:`bash
自动检测并修复配置问题(交互式)
npx gate-tool fix仅检查问题,不执行修复
npx gate-tool fix --check跳过确认,直接修复
npx gate-tool fix --yes
`常见问题:
-
Cannot find module 'hardhat/config' - 导入语句需要使用 type 关键字
- Did you mean to import "hardhat/config.js"? - ESM 模块兼容性问题fix 命令会自动将:
`typescript
import { HardhatUserConfig } from "hardhat/config";
`
修复为:
`typescript
import type { HardhatUserConfig } from "hardhat/config";
`#### 🔍 字节码检查
`bash
检查所有合约
npx gate-tool check检查指定合约
npx gate-tool check --contract Vault检查指定网络
npx gate-tool check --network eth指定配置文件路径
npx gate-tool check --config ./config/contracts.json指定输出报告路径
npx gate-tool check --output ./reports/result.json
`#### 🔄 同步链上合约状态
当合约通过 calldata 方式由其他人(如多签钱包)执行升级后,本地的
.openzeppelin 文件不会自动更新。使用此命令可以从链上读取最新状态并更新本地文件。`bash
同步合约状态
npx gate-tool sync \
--proxy 0x1234... \
--contract CounterUUPS \
--network sepolia
`#### ✅ 验证升级安全性并生成 calldata
验证合约升级的安全性,并生成
upgradeToAndCall 的 calldata。支持两种模式:
1. 代理合约模式:验证升级安全性并生成 upgradeCalldata
2. 实现合约模式:验证代码一致性并部署新合约
##### 模式 1: 代理合约升级验证
`bash
不同合约升级(从 CounterUUPS 升级到 CounterUUPSV2)
npx gate-tool validate \
--proxy 0x1234... \
--old CounterUUPS \
--new CounterUUPSV2 \
--network sepolia同一合约升级(修改现有合约后升级)
npx gate-tool validate \
--proxy 0x1234... \
--old CounterUUPS \
--new CounterUUPS \
--network sepolia指定输出文件路径
npx gate-tool validate \
--proxy 0x1234... \
--old CounterUUPS \
--new CounterUUPSV2 \
--network sepolia \
--output ./upgrade-info.json
`输出文件:
upgradeCalldata.json包含:
- 代理合约地址
- 旧实现合约地址
- 新实现合约地址
- upgradeToAndCall calldata
##### 模式 2: 实现合约验证与部署
验证新合约与链上实现合约的存储布局兼容性,并部署新的实现合约。
`bash
验证存储布局兼容性并部署新合约
npx gate-tool validate \
--proxy 0xImplementationAddress \
--new LedgerImplA \
--network mainnet注意:实现合约模式不需要 --old 参数
`工作流程:
1. 🔍 自动检测地址类型(代理 or 实现)
2. 📦 编译合约
3. 🔐 验证存储布局兼容性(使用 Hardhat Upgrades 插件)
4. ✅ 验证通过后部署新的实现合约
5. 💾 保存部署信息到
implementationDeploy.json输出文件:
implementationDeploy.json包含:
- 旧实现合约地址
- 新实现合约地址(新部署的)
- 存储布局兼容状态
- 时间戳和网络信息
使用场景:
- ✅ 验证新合约能否安全替换旧实现合约
- ✅ 确认存储槽位布局兼容
- ✅ 在验证通过后立即部署新的实现合约
- ✅ 获取新部署的实现合约地址用于后续升级
重要说明:
- 该模式不是比较代码完全一致
- 而是验证存储布局兼容性
- 即使代码有修改(如新增函数、修改逻辑),只要存储布局兼容就可以升级
- 这是可升级合约的核心安全机制
##### 构造函数参数
`bash
如果新合约的构造函数需要参数
npx gate-tool validate \
--proxy 0x1234... \
--old CounterUUPS \
--new CounterUUPSV2 \
--network sepolia \
--constructor-args '["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", 100]'构造函数参数示例
单个地址参数
--constructor-args '["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"]'多个参数(地址 + 数值)
--constructor-args '["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", 1000000]'复杂参数(地址 + 字符串 + 数值 + 布尔值)
--constructor-args '["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "MyToken", 18, true]'
`##### 工厂部署(可选)
如果需要通过工厂合约进行 Create2 部署,可以传入工厂地址(可选 salt)。
`bash
使用工厂合约部署新实现
npx gate-tool validate \
--proxy 0x1234... \
--old CounterUUPS \
--new CounterUUPSV2 \
--network sepolia \
--factory 0xFactoryAddress指定 salt(bytes32)
npx gate-tool validate \
--proxy 0x1234... \
--old CounterUUPS \
--new CounterUUPSV2 \
--network sepolia \
--factory 0xFactoryAddress \
--factory-salt 0x0000000000000000000000000000000000000000000000000000000000001234
`说明:
- 不传
--factory 时,默认走 EOA 部署逻辑
- --factory-salt 为可选,未传时默认使用全 0注意:
- 代理模式:会部署新实现合约(仅用于验证),但不会升级代理合约。请使用生成的 calldata 通过多签钱包执行升级。
- 实现模式:会部署新实现合约并返回地址,可用于后续的手动升级操作。
构造函数参数格式说明:
--constructor-args 参数接受 JSON 数组格式的字符串。参数类型会自动根据合约定义进行匹配。常见类型示例:
- 地址 (address):
"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
- 数值 (uint256/uint): 1000000 或 "1000000"
- 字符串 (string): "MyToken"
- 布尔值 (bool): true 或 false
- 字节 (bytes): "0x1234..."示例:
`solidity
// 合约构造函数
constructor(
address _token,
string memory _name,
uint256 _decimals,
bool _isPaused
) {
// ...
}
`对应的命令:
`bash
npx gate-tool validate \
--proxy 0x... \
--old OldContract \
--new NewContract \
--network mainnet \
--constructor-args '["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "MyToken", 18, false]'
`#### 📋 解析 Calldata
解析 EVM calldata,将其转换为人类可读的函数调用信息。
`bash
从 JSON 文件读取(推荐)
npx gate-tool parse --input parseCalldata.example.json直接从命令行参数(使用合约名称从 artifacts 查找 ABI)
npx gate-tool parse \
--to 0x5FbDB2315678afecb367f032d93F642f64180aa3 \
--contract Counter \
--calldata 0x3fb5c1cb0000000000000000000000000000000000000000000000000000000000000064使用自定义 ABI 文件
npx gate-tool parse \
--to 0x1234... \
--abi-path ./custom-abi/MyContract.json \
--calldata 0x...批量解析并保存结果
npx gate-tool parse \
--input batch-calldata.json \
--output results.json
`输入文件格式示例:
`json
{
"to": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"contractName": "Counter",
"calldata": "0x3fb5c1cb0000000000000000000000000000000000000000000000000000000000000064"
}
`批量解析格式(数组 包含三种形式):
`json
[
{
"to": "0x...",
"contractName": "Counter",
"calldata": "0x..."
},
{
"to": "0x...",
"abiPath": "./abi.json",
"calldata": "0x..."
},
{
"": "0x...",
"abi": [
{
"inputs": [
{"name": "spender", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"name": "approve",
"outputs": [{"name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function"
}
],
"calldata": "0x..."
}
]
`支持三种 ABI 来源方式:
1. contractName - 从 Hardhat artifacts 自动查找(需要先编译合约)
2. abiPath - 指定 ABI 文件路径
3. abi - 直接在 JSON 中提供 ABI 数组
$3
#### check 命令
| 选项 | 简写 | 说明 | 默认值 |
|------|------|------|--------|
|
--contract | -c | 指定要检查的合约名称 | - |
| --network | -n | 指定要检查的网络名称 | - |
| --config | - | 指定配置文件路径 | ./contractInfo.json |
| --output | -o | 指定输出报告文件路径 | ./bytecode-check-report.json |#### sync 命令
| 选项 | 简写 | 说明 | 必需 |
|------|------|------|------|
|
--proxy | - | 代理合约地址 | ✅ |
| --contract | - | 合约名称 | ✅ |
| --network | -n | 网络名称 | - |#### validate 命令
| 选项 | 简写 | 说明 | 必需 |
|------|------|------|------|
|
--proxy | - | 代理合约地址 | ✅ |
| --old | - | 旧合约名称(代理模式时使用) | - |
| --new | - | 新合约名称 | ✅ |
| --network | -n | 网络名称 | - |
| --output | -o | 输出文件路径 | ./upgradeCalldata.json |
| --constructor-args | - | 新合约构造函数参数(JSON数组格式) | - |
| --factory | - | 工厂合约地址(可选,Create2 部署) | - |
| --factory-salt | - | 工厂部署 salt(bytes32,可选) | - |#### parse 命令
| 选项 | 简写 | 说明 | 默认值 |
|------|------|------|--------|
|
--input | -i | 输入 JSON 文件路径 | - |
| --to | - | 目标合约地址(命令行模式) | - |
| --calldata | - | Calldata 十六进制数据(命令行模式) | - |
| --contract | -c | 合约名称(从 artifacts 查找 ABI) | - |
| --abi-path | - | 自定义 ABI 文件路径 | - |
| --output | -o | 输出 JSON 文件路径 | - |
ABI 来源优先级:直接提供的 abi > abiPath > contractName---
五、完整使用示例
$3
假设你有一个已部署的实现合约,需要验证新合约的存储布局兼容性并部署新版本:
`bash
1. 从 .openzeppelin 文件中找到实现合约地址
cat .openzeppelin/unknown-10088.json | grep "address"2. 验证存储布局兼容性并部署新合约
npx gate-tool validate \
--proxy 0x40397e8F64561AabC793514F1b28B01A2ebE6875 \
--new LedgerImplA \
--network gateLayer输出示例:
✅ 验证成功!
#
存储布局验证与部署结果:
────────────────────────────────────────────────────────────
旧实现合约: 0x40397e8F64561AabC793514F1b28B01A2ebE6875
新实现合约: 0x1234567890abcdef1234567890abcdef12345678
存储布局: ✅ 兼容
#
输出文件: /path/to/implementationDeploy.json
────────────────────────────────────────────────────────────
3. 查看部署信息
cat implementationDeploy.json
`输出文件内容:
`json
{
"type": "implementation",
"oldImplementationAddress": "0x40397e8F64561AabC793514F1b28B01A2ebE6875",
"newImplementationAddress": "0x1234567890abcdef1234567890abcdef12345678",
"contractName": "LedgerImplA",
"storageLayoutCompatible": true,
"timestamp": "2024-01-01T00:00:00.000Z",
"network": "gateLayer"
}
`$3
`bash
1. 验证升级安全性并生成 calldata
npx gate-tool validate \
--proxy 0xProxyAddress \
--old CounterUUPS \
--new CounterUUPSV2 \
--network mainnet输出示例:
✅ 验证成功!
#
升级信息摘要:
────────────────────────────────────────────────────────────
代理合约: 0xProxyAddress
旧实现: 0xOldImpl
新实现: 0xNewImpl
#
Calldata: 0x4f1ef286000000000000000000000000...
#
输出文件: /path/to/upgradeCalldata.json
────────────────────────────────────────────────────────────
2. 使用生成的 calldata 在多签钱包中执行升级
- 打开多签钱包(如 Gnosis Safe)
- 使用 upgradeCalldata.json 中的 target 和 calldata
- 提交交易并收集签名
3. 升级完成后,同步本地状态
npx gate-tool sync \
--proxy 0xProxyAddress \
--contract CounterUUPSV2 \
--network mainnet
`$3
`bash
1. 准备配置文件 contractInfo.json
cat > contractInfo.json << EOF
{
"contracts": {
"mainnet": {
"Vault": "0x1234...",
"Token": "0x5678..."
},
"sepolia": {
"Vault": "0xabcd..."
}
}
}
EOF2. 执行检查
npx gate-tool check3. 查看报告
cat bytecode-check-report.json
`$3
`bash
1. 从多签钱包获取待执行的 calldata
2. 解析 calldata 查看具体操作
npx gate-tool parse \
--to 0xProxyAddress \
--contract CounterUUPS \
--calldata 0x4f1ef286000000000000000000000000...输出示例:
📋 Calldata 解析结果
════════════════════════════════════════════════
目标合约: 0xProxyAddress
合约名称: CounterUUPS
#
函数名称: upgradeToAndCall
函数签名: upgradeToAndCall(address,bytes)
#
参数列表:
────────────────────────────────────────────────
1. newImplementation (address)
0x1234567890abcdef1234567890abcdef12345678
#
2. data (bytes)
0x
════════════════════════════════════════════════
``