javascript4
假设我编译生成了多个abi,然后启动节点,运行脚本。最后会不会报错呢?之前不要的编译后的abi是否需要删除呢
结论先行:编译多个 ABI 后启动节点、运行脚本,默认不会报错;不需要的编译后 ABI 也不是必须删除——核心原因是 Hardhat 会自动管理 ABI 的对应关系,脚本只会调用「你指定的合约」的 ABI,不会被其他 ABI 干扰。
一、为什么“多个 ABI 共存”不会报错?
Hardhat 编译合约时,会遵循「1 个 Solidity 合约 → 1 个 ABI 文件」的规则,所有 ABI 都会保存在 artifacts/contracts/ 文件夹下,且按合约文件名分类(比如 MyCounter.sol 对应 artifacts/contracts/MyCounter.sol/MyCounter.json,MyNFT.sol 对应 artifacts/contracts/MyNFT.sol/MyNFT.json)。
脚本运行时,只会通过「合约名称」或「合约地址+指定 ABI」绑定目标合约,完全不会管其他 ABI:
示例:多个 ABI 共存时的脚本运行逻辑
假设你有 2 个合约,编译后生成 2 个 ABI:
MyCounter.sol→ ABI 路径:artifacts/contracts/MyCounter.sol/MyCounter.jsonMyNFT.sol→ ABI 路径:artifacts/contracts/MyNFT.sol/MyNFT.json
运行之前的 interact-counter.js 脚本时,核心代码 ethers.getContractFactory("MyCounter") 会做两件事:
- 从
artifacts/中找到「合约名称为MyCounter」的 ABI 文件(自动匹配,不会找MyNFT的 ABI); - 用这个 ABI 部署/调用
MyCounter合约,和MyNFT的 ABI 完全无关。
只有这 3 种情况会报错(和“多个 ABI”无关)
- 脚本中指定的合约名称不存在(比如写
ethers.getContractFactory("MyCounter123"),但没有MyCounter123.sol合约); - 合约代码修改后没重新编译,ABI 和合约逻辑不匹配(比如合约删了
increment()函数,但 ABI 还保留该函数); - 手动修改了
artifacts/文件夹下的 ABI 文件(比如删了关键函数定义)。
二、不需要的编译后 ABI,是否需要删除?
结论:不是必须删,但建议“长期不用就删”
1. 不删除的影响(几乎可以忽略)
- 不会导致脚本报错;
- 只会增加项目文件夹体积(每个 ABI 文件很小,几十 KB 到几百 KB,多个也不占多少空间);
- 可能让你在
artifacts/文件夹中找目标 ABI 时稍微麻烦一点(但 Hardhat 按合约名分类,影响不大)。
2. 建议删除的场景(可选)
- 某些合约已经彻底废弃(比如测试用的临时合约、写错的合约),后续不会再用;
- 项目合约较多,想保持
artifacts/文件夹整洁,避免混淆。
3. 正确的删除方法(别直接删 ABI 文件!)
错误做法:直接删除 artifacts/contracts/xxx.sol/xxx.json(会导致 Hardhat 编译缓存错乱,下次编译可能不生成新 ABI)。
正确做法:
- 先删除
contracts/文件夹下「不需要的 Solidity 合约文件」(比如MyOldContract.sol); - 执行
npx hardhat clean命令(Hardhat 会自动清理artifacts/和cache/中对应的废弃 ABI 和编译缓存); - 重新编译现有合约:
npx hardhat compile(只生成当前contracts/下合约的 ABI,彻底清除废弃文件)。
三、实操示例:多个 ABI 共存的运行验证(可选,帮你放心)
你可以亲手测试“多个 ABI 共存”是否正常,步骤很简单:
- 在
contracts/下新建第二个合约MyNFT.sol(随便写个极简 NFT 合约):1
2
3
4
5
6
7
8
9
10
11// contracts/MyNFT.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract MyNFT is ERC721 {
constructor() ERC721("TestNFT", "TNFT") {}
function mint(address to) external {
_safeMint(to, 1);
}
} - 安装 OpenZeppelin 依赖(让合约能编译):
npm install @openzeppelin/contracts; - 编译所有合约(生成 2 个 ABI):
npx hardhat compile(此时artifacts/下有MyCounter和MyNFT两个 ABI); - 启动节点:
npx hardhat node; - 运行之前的
interact-counter.js脚本:npx hardhat run scripts/interact-counter.js --network localhost。
结果:脚本会正常运行(部署 MyCounter、调用函数),完全不受 MyNFT 的 ABI 影响,不会报错。
总结
- 多个 ABI 共存不会导致脚本报错,Hardhat 会按「合约名称」精准匹配 ABI,互不干扰;
- 不需要的 ABI 可删可不删,不删不影响运行,想删就按「删合约文件→clean→重新编译」的步骤操作;
- 后续开发中,你可以放心编写、编译多个合约,脚本只需要通过
ethers.getContractFactory("目标合约名称")指定要交互的合约即可,无需担心其他 ABI 的影响。
我做solidity开发,是不是typescript和javascript都要会啊?
对于 Solidity 开发,JavaScript 是必须会的,TypeScript 是强烈推荐的加分项。让我详细解释:
📊 必需程度对比
| 技能 | 必需程度 | 使用场景 | 学习建议 |
|---|---|---|---|
| JavaScript | ⭐⭐⭐⭐⭐ 必须会 | 1. Hardhat/Truffle 脚本 2. 测试编写 3. 部署脚本 4. 前端交互 |
优先级最高,至少掌握基础语法 |
| TypeScript | ⭐⭐⭐⭐ 强烈推荐 | 1. 大型项目开发 2. 类型安全的合约交互 3. 更好的 IDE 支持 |
建议学会 JS 后立即学习 |
| Solidity | ⭐⭐⭐⭐⭐ 核心技能 | 1. 智能合约开发 2. DeFi/NFT/DAO 等 |
核心,必须精通 |
🔧 实际工作中的使用情况
1. JavaScript 的必要性
1 | |
2. TypeScript 的优势
1 | |
🎯 学习路径建议
新手路径(3-6个月)
1 | |
项目实战顺序
1 | |
💡 为什么 JavaScript 是必须的?
- 工具链依赖:Hardhat、Truffle、Foundry 的脚本都是用 JS/TS 写的
- 测试框架:Mocha、Chai、Waffle 都基于 JS/TS
- 前端交互:DApp 前端必须用 JS 与区块链交互
- 自动化脚本:部署、升级、监控都需要 JS 脚本
- 生态成熟:90% 的区块链教程和示例代码使用 JS
🚀 快速上手指南
最低要求(能干活)
1 | |
TypeScript 可以后续学习
很多开发者开始只用 JavaScript,等项目复杂了再迁移到 TypeScript。TypeScript 的类型提示和错误预防在大型项目中特别有价值。
📚 学习资源推荐
JavaScript 学习
- MDN JavaScript 指南(免费,权威)
- JavaScript.info(现代 JS 教程)
- 《JavaScript 高级程序设计》(红宝书)
TypeScript 学习
- TypeScript 官方文档
- TypeScript 入门教程(中文)
- 《TypeScript 编程》
区块链专用
✅ 结论
立即开始:先学习 JavaScript 基础,至少达到能读懂和修改 Hardhat 脚本的水平。
长期规划:在掌握 JavaScript 后,学习 TypeScript,它会显著提高你的开发效率和代码质量。
好消息:如果你已经会其他编程语言(如 Python、Java),学习 JavaScript 会很快。主要需要掌握的是:
- 异步编程(Promise/async/await)
- 模块系统(CommonJS/ESM)
- 基本的对象和数组操作
你现在遇到的就是典型的 JavaScript 模块系统问题。按照我之前的建议,使用 .cjs 扩展名(CommonJS)先让脚本运行起来,然后慢慢学习 ES 模块和 TypeScript。
代码覆盖率是什么?在solidity开发的hardhat文档中看到的
在 Solidity 智能合约开发中,代码覆盖率(Code Coverage) 是衡量你的 测试用例对合约源代码执行程度 的核心指标(通常以百分比表示),本质是回答:「我的测试到底跑了合约里多少代码?」
它的核心价值是帮你发现 未被测试覆盖的代码死角——这些死角可能藏着逻辑漏洞、边界条件错误(比如溢出、权限问题),而智能合约一旦部署到区块链,几乎无法修改,漏洞代价极高。
一、代码覆盖率的核心衡量维度(Solidity 场景下)
Hardhat 的 hardhat-coverage 插件会从 4 个关键维度统计,帮你精准定位「没测到的代码」:
| 维度 | 含义(Solidity 示例) |
|---|---|
| 语句覆盖率(Statement) | 合约中「可执行语句」被执行的比例(比如 uint256 a = 1;、require(msg.sender == owner);) |
| 分支覆盖率(Branch) | 条件判断的「所有分支」是否都被触发(比如 if (x > 0) { ... } else { ... } 的两个分支) |
| 函数覆盖率(Function) | 合约中「所有函数」是否都被调用过(包括构造函数、external/public/internal 函数) |
| 行覆盖率(Line) | 合约代码「每一行」是否被执行(注意:一行可能包含多个语句,行覆盖 100% 不代表语句覆盖 100%) |
二、Hardhat 中如何使用代码覆盖率工具
Hardhat 生态的官方推荐插件是 @nomiclabs/hardhat-coverage,使用步骤超简单:
1. 安装插件
1 | |
2. 配置 Hardhat
在项目根目录的 hardhat.config.js/hardhat.config.ts 中导入插件:
1 | |
3. 运行覆盖率测试
1 | |
4. 查看结果
运行完成后,会在项目根目录生成 coverage/ 文件夹,打开其中的 index.html 文件(用浏览器打开),就能看到可视化报告:
- 绿色:已覆盖的代码行/分支/函数
- 红色:未覆盖的代码行/分支/函数
- 黄色:部分覆盖(比如一行有多个语句,只执行了部分)
报告还会显示整体覆盖率百分比(比如「语句覆盖率 95%」「分支覆盖率 88%」),以及每个合约的详细覆盖情况。
三、为什么 Solidity 开发必须重视代码覆盖率?
- 智能合约的「不可修改性」决定了测试优先级:和传统软件不同,合约部署后无法轻易升级(除非设计了代理模式),未覆盖的代码漏洞一旦被利用,可能直接导致用户资产损失。
- 辅助优化测试用例:比如报告显示某
if-else的else分支未覆盖,你就需要补充测试用例(比如传入触发else的参数),完善测试场景。 - 审计和协作的「质量背书」:第三方审计时,通常会要求合约覆盖率达到 80% 以上(无绝对标准,但高覆盖率是质量的重要参考);团队协作中,覆盖率也能确保新写的代码被测试覆盖。
四、关键误区:100% 覆盖率 ≠ 无 Bug
不要盲目追求 100% 覆盖率!它只是「测试完整性」的指标,不是「代码正确性」的保证:
- 比如逻辑错误(
if (x < 0)本该写if (x > 0)),但测试用例刚好传入x < 0的值,覆盖率仍是 100%,但漏洞依然存在; - 比如边界条件(
uint256溢出,虽然 Solidity 0.8+ 有内置检查,但如果是自定义逻辑),若测试没覆盖极端值,覆盖率可能达标但漏洞仍在。
因此,代码覆盖率是「辅助工具」,需结合:
- 单元测试(测单个函数/逻辑)
- 集成测试(测合约间交互)
- 人工代码审查
- 第三方安全审计
总结
代码覆盖率是 Solidity 开发中「提升合约安全性」的关键工具,Hardhat 通过简单的插件集成,就能帮你快速定位未测试的代码死角。它的核心作用是「倒逼测试完善」,而非「证明代码无错」——结合严谨的测试用例和安全审计,才能最大程度避免合约漏洞。
代码覆盖率,哪些工具可以测试?remix, hardhat, fountry, truffle都可以吗
在 Solidity 开发中,并非所有主流工具都原生支持代码覆盖率测试——Hardhat、Truffle、Foundry 是支持的(部分需插件),而 Remix 目前无原生覆盖率功能(需间接方案)。下面按工具逐一拆解支持情况、核心用法和特点,帮你精准选择:
一、四大工具的代码覆盖率支持详情
1. Hardhat → 完全支持(生态成熟,推荐)
- 支持状态:✅ 原生生态支持(通过官方推荐插件)
- 核心工具:
@nomiclabs/hardhat-coverage(底层依赖solidity-coverage库,行业标准) - 使用方式:之前已详细讲过,步骤极简:
1
2
3
4
5
6# 1. 安装插件
npm install --save-dev @nomiclabs/hardhat-coverage
# 2. hardhat.config 导入插件
require("@nomiclabs/hardhat-coverage");
# 3. 运行测试
npx hardhat coverage - 特点:
- 支持语句/分支/函数/行覆盖率,可视化 HTML 报告(绿色=覆盖,红色=未覆盖);
- 兼容 Hardhat 所有测试框架(Mocha/Chai、Waffle 等);
- 支持 Solidity 0.5+ 版本,适配主流编译器。
2. Truffle → 完全支持(插件成熟,老牌框架)
- 支持状态:✅ 生态支持(官方推荐插件)
- 核心工具:
truffle-coverage(同样基于solidity-coverage底层,与 Hardhat 同源) - 使用方式:
1
2
3
4
5# 1. 安装插件
npm install --save-dev truffle-coverage
# 2. truffle-config.js 无需额外配置(自动识别)
# 3. 运行测试
npx truffle run coverage - 特点:
- 报告形式与 Hardhat 一致(HTML 可视化),统计维度相同;
- 兼容 Truffle 的测试语法(Mocha/Chai);
- 适合长期使用 Truffle 的老项目,迁移成本低。
3. Foundry → 完全支持(原生集成,速度快)
- 支持状态:✅ 原生支持(无需额外插件,Foundry v0.2.0+ 内置)
- 核心工具:Foundry 自带
coverage命令(基于 Rust 实现,不依赖solidity-coverage) - 使用方式:
1
2
3
4
5# 1. 无需安装额外工具(Foundry 安装后直接可用)
# 2. 运行测试(在 Foundry 项目根目录)
forge coverage
# 3. 生成可视化 HTML 报告(可选)
forge coverage --report lcov && genhtml lcov.info -o coverage-report - 特点:
- 速度极快(Rust 编译优化,比 Hardhat/Truffle 快 2-5 倍);
- 支持语句/分支/函数覆盖率,终端直接输出统计结果,也可生成 HTML 报告;
- 兼容 Foundry 原生测试框架(DappTools 语法),适合用 Foundry 开发的项目。
4. Remix → 不支持原生覆盖,需间接方案
- 支持状态:❌ 无原生代码覆盖率功能(Remix 核心定位是「在线编辑+快速测试」,而非完整测试工程化)
- 间接方案:
- 方案 1:在 Remix 编写合约和简单测试(验证逻辑),然后将合约代码导出到 Hardhat/Foundry/Truffle 项目,用对应工具跑覆盖率;
- 方案 2:使用 Remix 的「测试面板」手动覆盖场景,但无法统计覆盖率百分比(只能靠肉眼确认是否测过,无量化指标)。
- 结论:Remix 不适合作为「覆盖率测试工具」,仅适合前期快速调试合约。
二、主流工具对比表(清晰选型)
| 工具 | 是否支持覆盖率 | 核心工具/插件 | 核心命令 | 关键特点 |
|---|---|---|---|---|
| Hardhat | ✅ 完全支持 | @nomiclabs/hardhat-coverage | npx hardhat coverage | 生态成熟,可视化报告完善,兼容 Mocha/Waffle |
| Truffle | ✅ 完全支持 | truffle-coverage | npx truffle run coverage | 老牌框架适配,与 Hardhat 同源底层 |
| Foundry | ✅ 完全支持 | 原生内置(无需插件) | forge coverage | 速度极快,Rust 驱动,终端+HTML 报告 |
| Remix | ❌ 无原生支持 | 无(需间接导出) | 无 | 仅适合快速调试,无法量化覆盖率 |
三、其他常用覆盖率工具(补充)
除了框架自带/插件,还有几个行业常用的独立工具,可搭配框架使用:
solidity-coverage(底层核心库):
- 上述 Hardhat/Truffle 的插件本质都是基于它实现的,是 Solidity 覆盖率测试的「底层标准」;
- 支持 Solidity 0.4-0.8+ 全版本,可独立配置使用(但不如框架插件便捷)。
Slither(静态分析+覆盖率):
- 区块链安全审计常用工具(由 Trail of Bits 开发),不仅能做代码漏洞检测,还能统计「函数覆盖率」;
- 适合结合框架覆盖率工具,做二次安全校验(比如发现覆盖率达标的代码仍有逻辑漏洞)。
DappTools(Foundry 前身):
- 基于 Nix 生态,自带
dapp coverage命令,支持覆盖率测试; - 现在更多人迁移到 Foundry,但老项目仍可使用。
- 基于 Nix 生态,自带
四、选型建议
- 若用 Hardhat/Truffle(Node.js 生态):直接用对应插件(
@nomiclabs/hardhat-coverage/truffle-coverage),配置简单、报告友好,适合大多数项目; - 若用 Foundry(Rust 生态):优先用原生
forge coverage,速度快、无额外依赖,适合追求高效测试的项目; - 若用 Remix 快速开发:先在 Remix 调试合约,再导出到 Hardhat/Foundry 跑覆盖率,避免因 Remix 无原生功能影响测试完整性;
- 若需 安全审计级覆盖:搭配
solidity-coverage(量化)+Slither(漏洞检测),双重保障。
总结
- 支持覆盖率测试的工具:Hardhat、Truffle、Foundry(均为工程化框架,推荐);
- 不支持原生覆盖的工具:Remix(需间接导出);
- 核心原则:选择与你当前开发框架匹配的工具(减少配置成本),优先框架原生/官方推荐插件(稳定性更高)。
Hardhat 编译合约时,有scripts文件夹,也有test文件夹。js测试脚本放在哪个文件里呢?
在Hardhat项目中,JS测试脚本和脚本文件的分工明确,核心原则是:测试脚本(验证合约逻辑/漏洞的代码)放在test文件夹,部署/交互类脚本放在scripts文件夹,以下是详细拆解:
一、核心分工:test vs scripts 文件夹
| 文件夹 | 用途(JS脚本场景) | 典型脚本类型 |
|---|---|---|
test |
专门存放合约测试脚本(核心目的:验证合约功能、排查漏洞、自动化测试) | 1. 单元测试(验证单个函数逻辑,如转账、授权); 2. 集成测试(验证合约间交互); 3. 漏洞测试(如复现重入、溢出等,适配你练DVD靶场的场景); 4. 断言验证(如检查合约状态、事件是否符合预期)。 |
scripts |
存放非测试类的执行脚本(核心目的:部署合约、调用合约、批量操作、数据提取等) | 1. 合约部署脚本(deploy.js); 2. 手动调用合约函数的脚本(如给合约充值、触发漏洞的攻击脚本); 3. 合约升级/迁移脚本; 4. 批量查询合约数据的脚本。 |
二、具体场景:你的JS脚本该放哪?
结合你练Damn Vulnerable DeFi靶场、做Solidity审计的核心需求,分场景说明:
场景1:写测试脚本验证合约漏洞(最核心)
比如你想验证某合约是否存在重入漏洞、整数溢出,或验证修复后的合约是否生效——这类脚本必须放在test文件夹,命名通常为[合约名].test.js(如Reentrancy.test.js)。
示例(test/Reentrancy.test.js):
1 | |
场景2:写脚本部署合约/执行攻击(非测试)
比如你需要部署靶场合约、手动执行攻击脚本(而非自动化测试)——这类脚本放在scripts文件夹,命名通常为deploy.js/attack.js(如scripts/attack-reentrancy.js)。
示例(scripts/attack-reentrancy.js):
1 | |
三、执行脚本的命令(关键区分)
- 运行
test文件夹的测试脚本:npx hardhat test(会自动执行test下所有.test.js文件),或指定文件npx hardhat test test/Reentrancy.test.js; - 运行
scripts文件夹的执行脚本:npx hardhat run scripts/attack-reentrancy.js(可指定网络,如--network sepolia)。
四、适配你审计场景的小技巧
- 练DVD靶场时:
- 把“漏洞验证逻辑”写在
test文件夹(自动化验证漏洞是否存在); - 把“手动部署/攻击流程”写在
scripts文件夹(快速复现攻击);
- 把“漏洞验证逻辑”写在
- 脚本命名规范:
测试脚本后缀统一用.test.js,便于Hardhat识别和区分; - 复用逻辑:
可把通用函数(如部署合约、转账)抽成utils文件夹,在test和scripts中都能引用,避免重复代码。
总结
- JS测试脚本(验证/断言/自动化测试)→ test文件夹(核心适配你的审计漏洞验证需求);
- 部署/手动攻击/交互脚本 → scripts文件夹(辅助你快速操作合约)。
这种分工是Hardhat的通用规范,既符合行业惯例,也能让你后续整理GitHub作品集时结构清晰(雇主看审计项目时,更关注test文件夹的漏洞验证逻辑)。