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.jsonMyNFT.sol 对应 artifacts/contracts/MyNFT.sol/MyNFT.json)。

脚本运行时,只会通过「合约名称」或「合约地址+指定 ABI」绑定目标合约,完全不会管其他 ABI:

示例:多个 ABI 共存时的脚本运行逻辑

假设你有 2 个合约,编译后生成 2 个 ABI:

  1. MyCounter.sol → ABI 路径:artifacts/contracts/MyCounter.sol/MyCounter.json
  2. MyNFT.sol → ABI 路径:artifacts/contracts/MyNFT.sol/MyNFT.json

运行之前的 interact-counter.js 脚本时,核心代码 ethers.getContractFactory("MyCounter") 会做两件事:

  1. artifacts/ 中找到「合约名称为 MyCounter」的 ABI 文件(自动匹配,不会找 MyNFT 的 ABI);
  2. 用这个 ABI 部署/调用 MyCounter 合约,和 MyNFT 的 ABI 完全无关。

只有这 3 种情况会报错(和“多个 ABI”无关)

  1. 脚本中指定的合约名称不存在(比如写 ethers.getContractFactory("MyCounter123"),但没有 MyCounter123.sol 合约);
  2. 合约代码修改后没重新编译,ABI 和合约逻辑不匹配(比如合约删了 increment() 函数,但 ABI 还保留该函数);
  3. 手动修改了 artifacts/ 文件夹下的 ABI 文件(比如删了关键函数定义)。

二、不需要的编译后 ABI,是否需要删除?

结论:不是必须删,但建议“长期不用就删”

1. 不删除的影响(几乎可以忽略)

  • 不会导致脚本报错;
  • 只会增加项目文件夹体积(每个 ABI 文件很小,几十 KB 到几百 KB,多个也不占多少空间);
  • 可能让你在 artifacts/ 文件夹中找目标 ABI 时稍微麻烦一点(但 Hardhat 按合约名分类,影响不大)。

2. 建议删除的场景(可选)

  • 某些合约已经彻底废弃(比如测试用的临时合约、写错的合约),后续不会再用;
  • 项目合约较多,想保持 artifacts/ 文件夹整洁,避免混淆。

3. 正确的删除方法(别直接删 ABI 文件!)

错误做法:直接删除 artifacts/contracts/xxx.sol/xxx.json(会导致 Hardhat 编译缓存错乱,下次编译可能不生成新 ABI)。

正确做法

  1. 先删除 contracts/ 文件夹下「不需要的 Solidity 合约文件」(比如 MyOldContract.sol);
  2. 执行 npx hardhat clean 命令(Hardhat 会自动清理 artifacts/cache/ 中对应的废弃 ABI 和编译缓存);
  3. 重新编译现有合约:npx hardhat compile(只生成当前 contracts/ 下合约的 ABI,彻底清除废弃文件)。

三、实操示例:多个 ABI 共存的运行验证(可选,帮你放心)

你可以亲手测试“多个 ABI 共存”是否正常,步骤很简单:

  1. 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);
    }
    }
  2. 安装 OpenZeppelin 依赖(让合约能编译):npm install @openzeppelin/contracts
  3. 编译所有合约(生成 2 个 ABI):npx hardhat compile(此时 artifacts/ 下有 MyCounterMyNFT 两个 ABI);
  4. 启动节点:npx hardhat node
  5. 运行之前的 interact-counter.js 脚本:npx hardhat run scripts/interact-counter.js --network localhost

结果:脚本会正常运行(部署 MyCounter、调用函数),完全不受 MyNFT 的 ABI 影响,不会报错。

总结

  1. 多个 ABI 共存不会导致脚本报错,Hardhat 会按「合约名称」精准匹配 ABI,互不干扰;
  2. 不需要的 ABI 可删可不删,不删不影响运行,想删就按「删合约文件→clean→重新编译」的步骤操作;
  3. 后续开发中,你可以放心编写、编译多个合约,脚本只需要通过 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
3
4
5
6
7
8
9
10
11
12
13
14
15
// 几乎所有区块链项目都会用到的 JS 代码:

// 部署脚本(Hardhat)
const { ethers } = require("hardhat");
const MyContract = await ethers.getContractFactory("MyToken");
const contract = await MyContract.deploy();

// 测试脚本(使用 ethers.js)
const token = await Token.deploy("My Token", "MTK");
expect(await token.name()).to.equal("My Token");

// 前端 DApp 交互(使用 web3.js 或 ethers.js)
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contract = new ethers.Contract(address, abi, signer);

2. TypeScript 的优势

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// TypeScript 提供类型安全,减少错误

// 明确的类型定义
interface TokenInfo {
name: string;
symbol: string;
decimals: number;
totalSupply: BigNumber;
}

// 类型安全的合约交互
async function getTokenInfo(address: string): Promise<TokenInfo> {
const contract = new ethers.Contract(address, ERC20_ABI, provider);
const [name, symbol, decimals, totalSupply] = await Promise.all([
contract.name(),
contract.symbol(),
contract.decimals(),
contract.totalSupply(),
]);
return { name, symbol, decimals, totalSupply };
}

🎯 学习路径建议

新手路径(3-6个月)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1-2个月:JavaScript 基础
├── 变量、函数、对象
├── 异步编程(async/awaitPromise
├── ES6+ 特性(箭头函数、解构、模块)
└── Node.js 基础

3个月:区块链开发工具
├── Hardhat/Truffle 基础
├── ethers.js/web3.js
└── 编写简单的部署和测试脚本

4-6个月:TypeScript(可选但推荐)
├── 类型系统基础
├── 接口和泛型
└── 在 Hardhat 项目中使用 TS

项目实战顺序

1
2
3
4
5
6
7
8
# 1. 纯 JavaScript 项目(开始)
npm init -y
npm install --save-dev hardhat
# 编写 .js 脚本

# 2. 逐步引入 TypeScript(进阶)
npm install --save-dev typescript ts-node @typechain/hardhat @types/node
# 将部分文件改为 .ts,逐步学习

💡 为什么 JavaScript 是必须的?

  1. 工具链依赖:Hardhat、Truffle、Foundry 的脚本都是用 JS/TS 写的
  2. 测试框架:Mocha、Chai、Waffle 都基于 JS/TS
  3. 前端交互:DApp 前端必须用 JS 与区块链交互
  4. 自动化脚本:部署、升级、监控都需要 JS 脚本
  5. 生态成熟:90% 的区块链教程和示例代码使用 JS

🚀 快速上手指南

最低要求(能干活)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 只需要会这些 JavaScript 知识就能开始:

// 1. 基础语法(变量、循环、条件)
const accounts = await ethers.getSigners();

// 2. 函数和异步操作
async function deployContract() {
const Contract = await ethers.getContractFactory("MyContract");
return await Contract.deploy();
}

// 3. 对象和数组操作
const contractInfo = {
address: contract.address,
abi: contract.interface.format()
};

// 4. 模块导入导出
module.exports = { deployContract }; // CommonJS
// 或
export { deployContract }; // ES Module

TypeScript 可以后续学习

很多开发者开始只用 JavaScript,等项目复杂了再迁移到 TypeScript。TypeScript 的类型提示和错误预防在大型项目中特别有价值。

📚 学习资源推荐

JavaScript 学习

TypeScript 学习

区块链专用

结论

立即开始:先学习 JavaScript 基础,至少达到能读懂和修改 Hardhat 脚本的水平。

长期规划:在掌握 JavaScript 后,学习 TypeScript,它会显著提高你的开发效率和代码质量。

好消息:如果你已经会其他编程语言(如 Python、Java),学习 JavaScript 会很快。主要需要掌握的是:

  1. 异步编程(Promise/async/await)
  2. 模块系统(CommonJS/ESM)
  3. 基本的对象和数组操作

你现在遇到的就是典型的 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
npm install --save-dev @nomiclabs/hardhat-coverage
# 或 yarn add --dev @nomiclabs/hardhat-coverage

2. 配置 Hardhat

在项目根目录的 hardhat.config.js/hardhat.config.ts 中导入插件:

1
2
3
4
5
6
7
// hardhat.config.js
require("@nomiclabs/hardhat-coverage");

module.exports = {
solidity: "0.8.20", // 你的 Solidity 版本
// 其他配置(比如网络、账户)...
};

3. 运行覆盖率测试

1
npx hardhat coverage

4. 查看结果

运行完成后,会在项目根目录生成 coverage/ 文件夹,打开其中的 index.html 文件(用浏览器打开),就能看到可视化报告:

  • 绿色:已覆盖的代码行/分支/函数
  • 红色:未覆盖的代码行/分支/函数
  • 黄色:部分覆盖(比如一行有多个语句,只执行了部分)

报告还会显示整体覆盖率百分比(比如「语句覆盖率 95%」「分支覆盖率 88%」),以及每个合约的详细覆盖情况。

三、为什么 Solidity 开发必须重视代码覆盖率?

  1. 智能合约的「不可修改性」决定了测试优先级:和传统软件不同,合约部署后无法轻易升级(除非设计了代理模式),未覆盖的代码漏洞一旦被利用,可能直接导致用户资产损失。
  2. 辅助优化测试用例:比如报告显示某 if-elseelse 分支未覆盖,你就需要补充测试用例(比如传入触发 else 的参数),完善测试场景。
  3. 审计和协作的「质量背书」:第三方审计时,通常会要求合约覆盖率达到 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 ❌ 无原生支持 无(需间接导出) 仅适合快速调试,无法量化覆盖率

三、其他常用覆盖率工具(补充)

除了框架自带/插件,还有几个行业常用的独立工具,可搭配框架使用:

  1. solidity-coverage(底层核心库):

    • 上述 Hardhat/Truffle 的插件本质都是基于它实现的,是 Solidity 覆盖率测试的「底层标准」;
    • 支持 Solidity 0.4-0.8+ 全版本,可独立配置使用(但不如框架插件便捷)。
  2. Slither(静态分析+覆盖率):

    • 区块链安全审计常用工具(由 Trail of Bits 开发),不仅能做代码漏洞检测,还能统计「函数覆盖率」;
    • 适合结合框架覆盖率工具,做二次安全校验(比如发现覆盖率达标的代码仍有逻辑漏洞)。
  3. DappTools(Foundry 前身):

    • 基于 Nix 生态,自带 dapp coverage 命令,支持覆盖率测试;
    • 现在更多人迁移到 Foundry,但老项目仍可使用。

四、选型建议

  1. 若用 Hardhat/Truffle(Node.js 生态):直接用对应插件(@nomiclabs/hardhat-coverage/truffle-coverage),配置简单、报告友好,适合大多数项目;
  2. 若用 Foundry(Rust 生态):优先用原生 forge coverage,速度快、无额外依赖,适合追求高效测试的项目;
  3. 若用 Remix 快速开发:先在 Remix 调试合约,再导出到 Hardhat/Foundry 跑覆盖率,避免因 Remix 无原生功能影响测试完整性;
  4. 若需 安全审计级覆盖:搭配 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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Reentrancy漏洞测试", function () {
let attacker, victimContract;

// 部署测试合约
beforeEach(async function () {
const Victim = await ethers.getContractFactory("ReentrancyVictim");
victimContract = await Victim.deploy();
await victimContract.deployed();

[attacker] = await ethers.getSigners();
});

// 测试重入攻击是否能成功
it("攻击者可利用重入漏洞盗取资金", async function () {
// 模拟攻击流程
const Attack = await ethers.getContractFactory("ReentrancyAttack");
const attackContract = await Attack.deploy(victimContract.address);
await attackContract.deployed();

// 执行攻击
await attackContract.attack({ value: ethers.utils.parseEther("1") });

// 断言:受害者合约余额为0(资金被盗)
expect(await ethers.provider.getBalance(victimContract.address)).to.equal(0);
});
});

场景2:写脚本部署合约/执行攻击(非测试)

比如你需要部署靶场合约、手动执行攻击脚本(而非自动化测试)——这类脚本放在scripts文件夹,命名通常为deploy.js/attack.js(如scripts/attack-reentrancy.js)。
示例(scripts/attack-reentrancy.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const { ethers } = require("hardhat");

async function main() {
// 部署受害者合约
const Victim = await ethers.getContractFactory("ReentrancyVictim");
const victim = await Victim.deploy();
await victim.deployed();
console.log("受害者合约部署地址:", victim.address);

// 部署攻击合约并执行攻击
const Attack = await ethers.getContractFactory("ReentrancyAttack");
const attack = await Attack.deploy(victim.address);
await attack.deployed();
await attack.attack({ value: ethers.utils.parseEther("1") });
console.log("攻击执行完成,受害者余额:", await ethers.provider.getBalance(victim.address));
}

main().catch((error) => {
console.error(error);
process.exitCode = 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)。

四、适配你审计场景的小技巧

  1. 练DVD靶场时:
    • 把“漏洞验证逻辑”写在test文件夹(自动化验证漏洞是否存在);
    • 把“手动部署/攻击流程”写在scripts文件夹(快速复现攻击);
  2. 脚本命名规范:
    测试脚本后缀统一用.test.js,便于Hardhat识别和区分;
  3. 复用逻辑:
    可把通用函数(如部署合约、转账)抽成utils文件夹,在testscripts中都能引用,避免重复代码。

总结

  • JS测试脚本(验证/断言/自动化测试)→ test文件夹(核心适配你的审计漏洞验证需求);
  • 部署/手动攻击/交互脚本 → scripts文件夹(辅助你快速操作合约)。

这种分工是Hardhat的通用规范,既符合行业惯例,也能让你后续整理GitHub作品集时结构清晰(雇主看审计项目时,更关注test文件夹的漏洞验证逻辑)。