<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>RainWeb3</title>
        <link>https://paragraph.com/@rainweb3</link>
        <description>undefined</description>
        <lastBuildDate>Mon, 06 Jul 2026 05:43:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>RainWeb3</title>
            <url>https://storage.googleapis.com/papyrus_images/a8ea76bef8c66055e5a3b7d87d54bf77bf838a18093e3f22aaa97fd8f658663a.png</url>
            <link>https://paragraph.com/@rainweb3</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[《给 Hardhat 的信：我的 Web3 技术写作启程》]]></title>
            <link>https://paragraph.com/@rainweb3/hardhat-web3</link>
            <guid>H2wpxBXNu2n3YFWowOjQ</guid>
            <pubDate>Thu, 09 Oct 2025 10:44:28 GMT</pubDate>
            <description><![CDATA[我想说的是：编写完善、无障碍、流畅的环境搭建指南，只是我的起点。 我相信，任何技术与工具，最终都是为人、为项目、为业务服务的。如果能不依赖图片、不依赖流程图（这些占用文档资源的形式），仅通过文字描述的清晰度和步骤的明确性，就能把技术的复杂度、工具使用的复杂度、版本冲突与不兼容的探索成本，彻底降低—— 那么，这种被极致解构并组织得流畅清晰的指引，本身就该成为技术体验的一部分。 它应当让人感受到：技术本可以如此简单、直接、可掌控，就像我们今天使用 AI 工具一样自然。 而我几乎很少见到这样的文档。 每当我写文档时，总是本能地极致细化，只为确保未来再次经历相同场景时，不会踩坑、不会卡壳，甚至希望它能成为“傻瓜式指引”，像吃饭喝水一样顺畅。 也许我的想法有些天真，或过于理想，但我愿意在学习中去做，在实践中调整。不同环境总有难以预测的问题，正因如此，我才更想做这件事——即便它暂时没有经济价值。📝 说明这不是一篇技术教程，而是一次坦诚的分享： 为什么我更愿意写文档，而不是只写代码？ 希望这段文字能带给你一点力量。 这是我在 Hardhat 官方 GitHub 仓库中回复团队的一段话，原文为...]]></description>
            <content:encoded><![CDATA[<blockquote><p>我想说的是：编写完善、无障碍、流畅的环境搭建指南，只是我的起点。</p><p>我相信，任何技术与工具，最终都是为人、为项目、为业务服务的。如果能<strong>不依赖图片、不依赖流程图</strong>（这些占用文档资源的形式），仅通过<strong>文字描述的清晰度</strong>和<strong>步骤的明确性</strong>，就能把技术的复杂度、工具使用的复杂度、版本冲突与不兼容的探索成本，彻底降低——</p><p>那么，这种被极致解构并组织得流畅清晰的指引，本身就该成为技术体验的一部分。</p><p>它应当让人感受到：技术本可以如此简单、直接、可掌控，就像我们今天使用 AI 工具一样自然。</p><p>而我几乎很少见到这样的文档。</p><p>每当我写文档时，总是本能地<strong>极致细化</strong>，只为确保未来再次经历相同场景时，不会踩坑、不会卡壳，甚至希望它能成为“<strong>傻瓜式指引</strong>”，像吃饭喝水一样顺畅。</p><p>也许我的想法有些天真，或过于理想，但我愿意在学习中去做，在实践中调整。不同环境总有难以预测的问题，正因如此，我才更想做这件事——即便它暂时没有经济价值。</p></blockquote><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">📝 说明</h3><blockquote><p>这不是一篇技术教程，而是一次坦诚的分享：</p><p>为什么我更愿意写文档，而不是只写代码？</p><p>希望这段文字能带给你一点力量。</p><p>这是我在 Hardhat 官方 GitHub 仓库中回复团队的一段话，原文为英文。我选择保留英文原文，因为它已是公开 Issue 的一部分，且我希望全球开发者都能无障碍阅读。</p></blockquote><hr><blockquote><p>I&apos;d like to share with you the motivation behind my actions. I&apos;m a developer transitioning from Web2 to Web3, and I want to explain why this shift means so much to me.</p><p>While Web2 has evolved over the years with diverse tech stacks and a vast ecosystem, it also carries numerous longstanding issues. In recent times, especially within China, the industry appears to be approaching a stagnation point. When I discovered Web3, I was immediately drawn to its core principles: decentralization, openness, and user sovereignty. These values resonated deeply with me.</p><p>One major pain point in Web2 is the lack of proper documentation. Outside of a few top-tier companies, most organizations don’t prioritize maintaining technical documentation. Even when documentation policies exist, the quality is often inconsistent—written reactively to meet internal requirements rather than to support knowledge sharing. Critical information frequently gets lost between development phases, making it difficult to trace decisions or onboard new team members efficiently.</p><p>Moreover, most Web2 technologies and codebases are closed-source or only partially open. While this is understandable from a business perspective, it creates significant barriers for developers trying to learn or debug systems. Despite the large developer community, finding accurate, up-to-date, and comprehensive resources can be extremely challenging—let alone accessing knowledge about systems that are entirely proprietary or outdated.</p><p>In contrast, Web3 greatly reduces these issues. The transparency of on-chain smart contracts, which anyone can audit, represents a fundamental improvement. When I began learning Web3, my initial goal was to become a smart contract developer. However, as I documented my learning process, I realized I have a stronger passion and aptitude for creating detailed, beginner-friendly technical guides and tutorials.</p><p>Currently, the Web3 space lacks in-depth, well-structured documentation. While there are many learning platforms and video tutorials, they often leave learners to navigate numerous pitfalls on their own, consuming significant time and effort. If developers could spend less time troubleshooting tooling issues and instead focus on core aspects—such as business logic, security audits, user experience, gas optimization, and data accuracy (on-chain and off-chain)—it would greatly accelerate the growth and maturity of the Web3 ecosystem.</p><p>This insight inspired me to start building a personal Web3 knowledge base and to actively provide feedback to tools and educators I use. My long-term goal is to contribute meaningfully to the Web3 space—ideally securing a role in technical documentation, developer relations, or developer experience. I’ve found that writing documentation gives me far more motivation and fulfillment than coding itself.</p><p>For example, I’ve been learning through Patrick Collins’ excellent platform at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://updraft.cyfrin.io/">https://updraft.cyfrin.io/</a>. His courses are clear, high-quality, and very accessible. However, some parts—particularly around tooling setup and environment configuration—have become slightly outdated. I tried reaching out to him via Twitter DM, but couldn’t send a message. I also sent a friend request on Discord, which hasn’t been accepted—likely due to his busy schedule. Eventually, I submitted feedback through his platform, though I’m unsure if he’s seen it.</p><p>After that, I decided to file issues directly on the Hardhat GitHub repository, hoping to help other learners who might encounter the same challenges.</p><p>Regarding your suggestion about creating a new issue: for now, I don’t think it’s necessary. If I have additional feedback, I’ll organize it into a well-structured document and submit it as a new issue or discussion.</p><p>The documentation I’m creating may also serve as a helpful supplement for users navigating your official tools. With clear guidance, learners should be able to get up and running within 30 to 60 minutes, minimizing the need to jump between multiple sources.</p><p>As for why I haven’t translated my documents into English yet: I want to ensure accuracy, and I’m not confident that my English proficiency would allow me to properly review or refine machine-translated content. Inaccurate translations could mislead readers, which would defeat the purpose. Even in Chinese, as long as the logic and steps are clearly laid out, English-speaking developers can follow along effectively using translation tools or by tracing the detailed instructions.</p></blockquote>]]></content:encoded>
            <author>rainweb3@newsletter.paragraph.com (RainWeb3)</author>
        </item>
        <item>
            <title><![CDATA[Hardhat v2.26.3 + Node.js v20.18.0精准稳定版部署指南]]></title>
            <link>https://paragraph.com/@rainweb3/hardhat-v2-26-3-node-js-v20-18-0</link>
            <guid>mWlowasjPKhCKXxguj8F</guid>
            <pubDate>Sat, 04 Oct 2025 15:11:17 GMT</pubDate>
            <description><![CDATA[版本：v4.8.0最后更新时间：2025年10月3日 目标：规避 hardhat@3.x 的兼容性问题，精准锁定稳定版 v2.26.3，确保在 Node.js v20.18.0 环境下构建无冲突、可部署、可维护的 TypeScript 项目。快速上手-可访问下载此模版项目：v2.26.3 hardhat-project-template下载后-先执行：npm run reinstall（安装node_modules）其他国家可访问：https://rainweb3.github.io/ [web知识库]() 中国内地可访问：\web知识库\📚 目录（点击跳转）🔧 一、环境准备（Node.js v20.18.0 稳定适配）✅ 1.1 前提条件🛠 二、初始化项目结构（强制使用 hardhat@2.26.3）✅ 2.1 创建项目并初始化✅ 2.2 安装 Hardhat 稳定版本 v2.26.3（关键步骤）交互式选项详解（逐行说明）📁 三、项目结构演变：从原生生成到完整配置✅ 3.1 初始生成的项目结构（执行 npx hardhat init 后）✅ 3.2 完整项目结构（添加所...]]></description>
            <content:encoded><![CDATA[<blockquote><p><strong>版本：v4.8.0最后更新时间：2025年10月3日</strong> <strong>目标：规避</strong> <code>hardhat@3.x</code> 的兼容性问题，精准锁定稳定版 <code>v2.26.3</code>，确保在 Node.js v20.18.0 环境下构建无冲突、可部署、可维护的 TypeScript 项目。</p></blockquote><hr><ul><li><p>快速上手-可访问下载此模版项目：</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/rainweb3/hardhat-project-template/tree/main">v2.26.3 hardhat-project-template</a></p></li><li><p>下载后-先执行：npm run reinstall（安装node_modules）</p></li></ul><hr><p>其他国家可访问：<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rainweb3.github.io/">https://rainweb3.github.io/</a> [web知识库]()</p><p>中国内地可访问：\web知识库\</p><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📚 目录（点击跳转）</h2><ul><li><p>🔧 一、环境准备（Node.js v20.18.0 稳定适配）</p><ul><li><p>✅ 1.1 前提条件</p></li></ul></li><li><p>🛠 二、初始化项目结构（强制使用 <code>hardhat@2.26.3</code>）</p><ul><li><p>✅ 2.1 创建项目并初始化</p></li><li><p>✅ 2.2 安装 Hardhat 稳定版本 v2.26.3（关键步骤）</p></li><li><p>交互式选项详解（逐行说明）</p></li></ul></li><li><p>📁 三、项目结构演变：从原生生成到完整配置</p><ul><li><p>✅ 3.1 初始生成的项目结构（执行 <code>npx hardhat init</code> 后）</p></li><li><p>✅ 3.2 完整项目结构（添加所有配置文件后）</p></li><li><p>✅ 3.3 新增/修改的配置文件说明（对比初始结构）</p></li></ul></li><li><p>⚙️ 四、修复 Ignition 导入错误与 Solidity 编译器版本不匹配问题</p><ul><li><p>🚫 4.0 <code>hardhat@2.26.3</code> 不支持 Ignition：原因与替代方案详解</p></li><li><p>✅ 4.1 移除 Ignition 相关代码（<code>hardhat@2.26.3</code> 不支持）</p></li><li><p>✅ 4.2 修正 <code>hardhat.config.ts</code> 中的 Solidity 编译器版本</p></li><li><p>✅ 4.3 更新 <code>package.json</code> 脚本（移除 Ignition 相关）</p></li></ul></li><li><p>🧩 五、依赖版本对齐（精确锁定，避免 <code>3.x</code> 升级）</p><ul><li><p>✅ 5.1 清理并替换 <code>package.json</code></p></li><li><p>✅ 5.2 使用更新后的 <code>package.json</code>（项目名已更改为 <code>hardhat-project</code>）</p></li><li><p>✅ 5.3 安装最终依赖</p></li></ul></li><li><p>⚙️ 六、新增与修改的配置文件详解</p><ul><li><p>✅ 6.1 <code>.prettierrc</code>（新增）</p></li><li><p>✅ 6.2 <code>eslint.config.js</code>（新增）</p></li><li><p>✅ 6.3 <code>.editorconfig</code>（新增）</p></li><li><p>✅ 6.4 <code>.env</code>（新增）</p></li><li><p>✅ 6.5 <code>.gitignore</code>（增强）</p></li><li><p>✅ 6.6 <code>.vscode/settings.json</code>（增强）</p></li></ul></li><li><p>⚠️ 七、修复 VS Code TypeScript 编译器错误（<code>tsconfig.json</code> 问题）</p><ul><li><p>🚫 7.0 问题描述</p></li><li><p>🔍 7.1 根本原因分析</p></li><li><p>✅ 7.2 推荐解决方案（无需修改源码）</p></li><li><p>✅ 7.3 替代方案（修改 <code>tsconfig.json</code>，不推荐）</p></li></ul></li><li><p>🧪 八、验证环境（确保 <code>v2.26.3</code> 正常工作）</p><ul><li><p>✅ 8.1 编译合约</p></li><li><p>✅ 8.2 运行测试</p></li><li><p>✅ 8.3 启动本地节点</p></li><li><p>✅ 8.4 部署测试</p></li></ul></li><li><p>📦 九、智能合约开发常用命令汇总（含 ts-node 执行）</p></li><li><p>⚠️ 十、安全审计问题说明与处理建议</p></li><li><p>✅ 十一、结论 -\📄 Hardhat 单文件编译指南\ -\📚 Hardhat 项目中 ESLint &amp; Prettier 集成问题全记录\</p></li></ul><hr><h2 id="h-nodejs-v20180" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🔧 一、环境准备（Node.js v20.18.0 稳定适配）</h2><h3 id="h-11" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 1.1 前提条件</h3><ul><li><p><strong>Node.js</strong>：<code>v20.18.0</code>（LTS，推荐）</p></li><li><p><strong>npm</strong>：<code>v10.8.2</code>（随 Node.js v20 安装）</p></li><li><p><strong>Git</strong>（可选）</p></li><li><p><strong>文本编辑器</strong>：推荐使用 <strong>VS Code</strong></p></li></ul><blockquote><p>⚠️ <strong>重要提醒</strong>：<code>hardhat@3.x</code> 版本（如 <code>3.0.4</code>）为<strong>早期主版本</strong>，存在 API 变更、插件不兼容、文档缺失等问题，<strong>不建议在生产或学习项目中使用</strong>。</p></blockquote><pre data-type="codeBlock" text="# 检查版本
node -v  # 预期输出：v20.18.0
npm -v   # 预期输出：10.8.2
"><code><span class="hljs-comment"># 检查版本</span>
node -v  <span class="hljs-comment"># 预期输出：v20.18.0</span>
npm -v   <span class="hljs-comment"># 预期输出：10.8.2</span>
</code></pre><blockquote><p>💡 若版本不符，请使用 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/nvm-sh/nvm">nvm</a> 切换：</p></blockquote><pre data-type="codeBlock" text="# 安装 nvm（Linux/macOS）
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# 重启终端后
nvm install 20.18.0
nvm use 20.18.0
nvm alias default 20.18.0
"><code><span class="hljs-comment"># 安装 nvm（Linux/macOS）</span>
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

<span class="hljs-comment"># 重启终端后</span>
nvm install 20.18.0
nvm use 20.18.0
nvm <span class="hljs-built_in">alias</span> default 20.18.0
</code></pre><hr><h2 id="h-hardhat2263" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🛠 二、初始化项目结构（强制使用 <code>hardhat@2.26.3</code>）</h2><h3 id="h-21" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 2.1 创建项目并初始化</h3><pre data-type="codeBlock" text="mkdir hardhat-project
cd hardhat-project
npm init -y
"><code>mkdir hardhat<span class="hljs-operator">-</span>project
cd hardhat<span class="hljs-operator">-</span>project
npm init <span class="hljs-operator">-</span>y
</code></pre><hr><h3 id="h-22-hardhat-v2263" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 2.2 安装 Hardhat <strong>稳定版本 v2.26.3</strong>（关键步骤）</h3><blockquote><p>⚠️ <strong>切勿使用</strong> <code>npm install --save-dev hardhat</code>，否则会安装最新的 <code>3.0.4</code>，该版本存在严重兼容性问题。</p></blockquote><pre data-type="codeBlock" text="npm install --save-dev hardhat@2.26.3
npx hardhat init
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev hardhat@<span class="hljs-number">2.26</span><span class="hljs-number">.3</span>
npx hardhat init
</code></pre><hr><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">交互式选项详解（逐行说明）：</h4><pre data-type="codeBlock" text="? What do you want to do? 
  Create a JavaScript project
&gt; Create a TypeScript project
  Create a TypeScript project (with Viem)
  Create an empty hardhat.config.js
  Quit
"><code>? What do you want <span class="hljs-keyword">to</span> do? 
  <span class="hljs-keyword">Create</span> a JavaScript project
<span class="hljs-operator">></span> <span class="hljs-keyword">Create</span> a TypeScript project
  <span class="hljs-keyword">Create</span> a TypeScript project (<span class="hljs-keyword">with</span> Viem)
  <span class="hljs-keyword">Create</span> an <span class="hljs-keyword">empty</span> hardhat.config.js
  Quit
</code></pre><p>✅ <strong>选择：</strong><code>Create a TypeScript project</code></p><blockquote><p><strong>原因</strong>：本人的配置使用 <code>ethers</code> 而非 <code>viem</code>，选择此项将生成基于 <code>ethers</code> 和 <code>chai</code> 的标准 TypeScript 项目结构。</p></blockquote><hr><pre data-type="codeBlock" text="? Hardhat project root: /your/path/hardhat-project
"><code>? Hardhat project root: <span class="hljs-operator">/</span>your<span class="hljs-operator">/</span>path<span class="hljs-operator">/</span>hardhat<span class="hljs-operator">-</span>project
</code></pre><p>✅ 回车确认默认路径。</p><hr><pre data-type="codeBlock" text="? Do you want to add a .gitignore? (Y/n)
"><code>? Do you want to add a .gitignore? (Y<span class="hljs-operator">/</span>n)
</code></pre><p>✅ 输入 <code>Y</code>，自动创建 <code>.gitignore</code>。</p><hr><pre data-type="codeBlock" text="? Do you want to install this sample project&apos;s dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) »
"><code>? <span class="hljs-selector-tag">Do</span> <span class="hljs-selector-tag">you</span> <span class="hljs-selector-tag">want</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">install</span> <span class="hljs-selector-tag">this</span> <span class="hljs-selector-tag">sample</span> <span class="hljs-selector-tag">project</span>'<span class="hljs-selector-tag">s</span> <span class="hljs-selector-tag">dependencies</span> <span class="hljs-selector-tag">with</span> <span class="hljs-selector-tag">npm</span> (<span class="hljs-variable">@nomicfoundation</span>/hardhat-toolbox)? (Y/n) »
</code></pre><p>✅ <strong>输入</strong> <code>y</code></p><blockquote><p><strong>选项说明</strong>：</p><ul><li><p>此选项询问是否自动安装 <code>@nomicfoundation/hardhat-toolbox</code> 及其依赖（如 <code>eslint</code>, <code>prettier</code>, <code>typescript</code>, <code>chai</code>, <code>ethers</code> 等）。</p></li><li><p>✅ <strong>选择</strong> <code>y</code>：自动安装推荐的开发依赖，节省手动配置时间，且版本与 <code>hardhat@2.26.3</code> 兼容。</p></li><li><p>❌ 选择 <code>n</code>：需手动安装所有依赖，容易出错且耗时。</p></li><li><p><strong>注意</strong>：即使选择 <code>y</code>，后续仍需用本人提供的 <code>package.json</code> 替换以锁定精确版本。</p></li></ul></blockquote><hr><blockquote><p>⚠️ <strong>关于安装过程中的警告说明</strong></p><p>执行 <code>npm install</code> 时可能出现：</p><pre data-type="codeBlock" text="npm warn deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported
npm warn deprecated eslint@8.57.1: This version is no longer supported...
"><code>npm <span class="hljs-keyword">warn</span> deprecated <span class="hljs-keyword">glob</span>@8.<span class="hljs-number">1.0</span>: Glob versions prior to v9 are <span class="hljs-keyword">no</span> longer supported
npm <span class="hljs-keyword">warn</span> deprecated eslint@8.<span class="hljs-number">57.1</span>: This version is <span class="hljs-keyword">no</span> longer supported...
</code></pre><p><strong>结论</strong>：这些是<strong>非阻塞性警告</strong>，源于 <code>hardhat-toolbox</code> 对旧版 <code>eslint</code> 的依赖。<code>hardhat@2.26.3 + toolbox@^4.0.0 + eslint@^8.57.0</code> 是当前最稳定的组合，<strong>无需修复</strong>。</p></blockquote><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📁 三、项目结构演变：从原生生成到完整配置</h2><p>本节清晰区分 <strong>初始生成结构</strong> 与 <strong>最终完整结构</strong>，并说明新增/修改项。</p><h3 id="h-31-npx-hardhat-init" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 3.1 初始生成的项目结构（执行 <code>npx hardhat init</code> 后）</h3><p>执行 <code>npx hardhat init</code> 并选择 <code>Create a TypeScript project</code> 后，Hardhat 自动生成的项目结构如下：</p><pre data-type="codeBlock" text="hardhat-project/
├── contracts/                 # 存放 Solidity 智能合约源代码（.sol 文件）
│   └── Lock.sol               # 示例合约：带时间锁的转账合约
├── scripts/                   # 存放自定义部署或交互脚本（.ts 文件）
│   └── deploy.ts              # 示例：部署合约到指定网络的脚本
├── test/                      # 存放合约测试用例（.ts 文件）
│   └── Lock.ts                # 示例：对 Lock 合约进行单元测试
├── node_modules/              # npm 安装的所有依赖包（自动生成）
├── .gitignore                 # Git 忽略文件规则（已包含基础规则）
├── hardhat.config.ts          # Hardhat 主配置文件（网络、Solidity 版本等）
├── package-lock.json          # npm 依赖锁定文件（自动生成）
├── package.json               # 项目元信息与依赖声明
├── README.md                  # 项目说明文档
└── tsconfig.json              # TypeScript 编译配置
"><code>hardhat<span class="hljs-operator">-</span>project<span class="hljs-operator">/</span>
├── contracts<span class="hljs-operator">/</span>                 # 存放 Solidity 智能合约源代码（.sol 文件）
│   └── Lock.sol               # 示例合约：带时间锁的转账合约
├── scripts<span class="hljs-operator">/</span>                   # 存放自定义部署或交互脚本（.ts 文件）
│   └── deploy.ts              # 示例：部署合约到指定网络的脚本
├── test<span class="hljs-operator">/</span>                      # 存放合约测试用例（.ts 文件）
│   └── Lock.ts                # 示例：对 Lock 合约进行单元测试
├── node_modules<span class="hljs-operator">/</span>              # npm 安装的所有依赖包（自动生成）
├── .gitignore                 # Git 忽略文件规则（已包含基础规则）
├── hardhat.config.ts          # Hardhat 主配置文件（网络、Solidity 版本等）
├── package<span class="hljs-operator">-</span>lock.json          # npm 依赖锁定文件（自动生成）
├── package.json               # 项目元信息与依赖声明
├── README.md                  # 项目说明文档
└── tsconfig.json              # TypeScript 编译配置
</code></pre><blockquote><p>⚠️ <strong>此时缺少</strong>：<code>.prettierrc</code>, <code>eslint.config.js</code>, <code>.editorconfig</code>, <code>.env</code>, <code>.vscode/settings.json</code> 等高级配置文件。</p></blockquote><hr><h3 id="h-32" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 3.2 完整项目结构（添加所有配置文件后）</h3><p>在添加所有配置文件和环境变量后，最终的项目结构如下：</p><pre data-type="codeBlock" text="hardhat-project/
├── contracts/                 # 存放 Solidity 智能合约源代码（.sol 文件）
│   └── Lock.sol               # 示例合约：带时间锁的转账合约
├── scripts/                   # 存放自定义部署或交互脚本（.ts 文件）
│   └── deploy.ts              # 示例：部署合约到指定网络的脚本
├── test/                      # 存放合约测试用例（.ts 文件）
│   └── Lock.ts                # 示例：对 Lock 合约进行单元测试
├── node_modules/              # npm 安装的所有依赖包（自动生成）
├── .vscode/                   # VS Code 编辑器配置
│   └── settings.json          # 编辑器格式化、保存等行为配置
├── .env                       # 环境变量文件（本地开发使用，不应提交到 Git）
├── .env.local                 # 本地环境变量覆盖文件（Git 忽略）
├── encryptedKey.json          # 加密的私钥文件（Git 忽略）
├── .editorconfig              # 统一编辑器缩进、换行等风格
├── .eslint.config.js          # ESLint 代码规范检查配置
├── .gitignore                 # Git 忽略文件规则
├── .prettierrc                # Prettier 代码格式化配置
├── hardhat.config.ts          # Hardhat 主配置文件（网络、Solidity 版本等）
├── package-lock.json          # npm 依赖锁定文件（自动生成）
├── package.json               # 项目元信息与依赖声明
├── README.md                  # 项目说明文档
└── tsconfig.json              # TypeScript 编译配置
"><code>hardhat<span class="hljs-operator">-</span>project<span class="hljs-operator">/</span>
├── contracts<span class="hljs-operator">/</span>                 # 存放 Solidity 智能合约源代码（.sol 文件）
│   └── Lock.sol               # 示例合约：带时间锁的转账合约
├── scripts<span class="hljs-operator">/</span>                   # 存放自定义部署或交互脚本（.ts 文件）
│   └── deploy.ts              # 示例：部署合约到指定网络的脚本
├── test<span class="hljs-operator">/</span>                      # 存放合约测试用例（.ts 文件）
│   └── Lock.ts                # 示例：对 Lock 合约进行单元测试
├── node_modules<span class="hljs-operator">/</span>              # npm 安装的所有依赖包（自动生成）
├── .vscode/                   # VS Code 编辑器配置
│   └── settings.json          # 编辑器格式化、保存等行为配置
├── .env                       # 环境变量文件（本地开发使用，不应提交到 Git）
├── .env.local                 # 本地环境变量覆盖文件（Git 忽略）
├── encryptedKey.json          # 加密的私钥文件（Git 忽略）
├── .editorconfig              # 统一编辑器缩进、换行等风格
├── .eslint.config.js          # ESLint 代码规范检查配置
├── .gitignore                 # Git 忽略文件规则
├── .prettierrc                # Prettier 代码格式化配置
├── hardhat.config.ts          # Hardhat 主配置文件（网络、Solidity 版本等）
├── package<span class="hljs-operator">-</span>lock.json          # npm 依赖锁定文件（自动生成）
├── package.json               # 项目元信息与依赖声明
├── README.md                  # 项目说明文档
└── tsconfig.json              # TypeScript 编译配置
</code></pre><blockquote><p>✅ <strong>变化说明</strong>：</p><ul><li><p>已<strong>移除</strong> <code>ignition/</code> 目录，因为 <code>hardhat@2.26.3</code> 不支持 <code>hardhat-ignition</code>。</p></li><li><p>新增 <code>.vscode/</code>, <code>.prettierrc</code>, <code>.eslint.config.js</code>, <code>.editorconfig</code>, <code>.env</code> 等配置文件。</p></li><li><p><code>.gitignore</code> 内容被增强，以忽略更多文件。</p></li></ul></blockquote><hr><h3 id="h-33" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 3.3 新增/修改的配置文件说明（对比初始结构）</h3><p>| 文件/目录 | 类型 | 作用说明 |</p><p>|----------|------|----------|</p><p>| <code>.prettierrc</code> | 新增 | Prettier 格式化配置，统一代码风格 |</p><p>| <code>eslint.config.js</code> | 新增 | ESLint 代码规范检查配置，集成 Prettier，确保代码质量 |</p><p>| <code>.editorconfig</code> | 新增 | 统一不同编辑器的缩进、换行等基础风格 |</p><p>| <code>.env</code> | 新增 | 存放私钥、RPC URL 等敏感环境变量 |</p><p>| <code>.env.local</code> | 新增 | 本地环境变量覆盖，优先级高于 <code>.env</code> |</p><p>| <code>encryptedKey.json</code> | 新增 | 存放加密后的私钥文件 |</p><p>| <code>.vscode/settings.json</code> | 新增 | VS Code 编辑器行为配置，实现保存时自动格式化与修复 |</p><p>| <code>.gitignore</code> | 修改 | 在初始基础上增强，新增忽略 <code>dist/</code>, <code>cache/</code>, <code>coverage/</code>, <code>encryptedKey.json</code>, <code>.env.*</code> 等 |</p><hr><h2 id="h-ignition-solidity" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">⚙️ 四、修复 Ignition 导入错误与 Solidity 编译器版本不匹配问题</h2><blockquote><p>🛠 <strong>问题描述</strong>：</p><ol><li><p><code>import { buildModule } from &quot;@nomicfoundation/hardhat-ignition/modules&quot;;</code> 报错：找不到模块。</p></li><li><p><code>npx hardhat compile</code> 报错：<code>Error HH606: The project cannot be compiled</code>，Solidity 版本 <code>^0.8.28</code> 与配置不匹配。</p></li></ol><p><strong>根本原因</strong>：</p><ul><li><p><code>hardhat@2.26.3</code> <strong>不支持</strong> <code>hardhat-ignition</code>，该功能是 <code>hardhat@3.x</code> 的实验性功能。</p></li><li><p><code>hardhat-toolbox</code> 默认配置的 Solidity 编译器版本可能不包含 <code>0.8.28</code>。</p></li></ul></blockquote><hr><h3 id="h-40-hardhat2263-ignition" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🚫 4.0 <code>hardhat@2.26.3</code> 不支持 Ignition：原因与替代方案详解</h3><blockquote><p><strong>⚠️ 核心原因说明</strong>：</p><p><code>@nomicfoundation/hardhat-ignition</code> 是 Hardhat 团队为 <strong>Hardhat v3.x 系列</strong>开发的<strong>全新、实验性</strong>的模块化部署系统。它旨在简化复杂合约系统的部署流程，提供更强大的依赖管理和部署状态追踪能力。</p><p><code>hardhat@2.26.3</code>（属于 v2.x 系列）发布于 Hardhat Ignition 功能之前，其代码库中完全不包含 <code>hardhat-ignition</code> 模块。 因此，尝试在 <code>v2.26.3</code> 项目中导入 <code>@nomicfoundation/hardhat-ignition/modules</code> 会直接导致模块解析失败，报错：</p><pre data-type="codeBlock" text="Error: Cannot find module &apos;@nomicfoundation/hardhat-ignition/modules&apos;
"><code>Error: Cannot find <span class="hljs-keyword">module</span> <span class="hljs-string">'@nomicfoundation/hardhat-ignition/modules'</span>
</code></pre><p><strong>这不是配置错误，而是版本不兼容的必然结果。</strong></p><p><strong>📌 重要提示</strong>：即使本人手动通过 <code>npm install @nomicfoundation/hardhat-ignition</code> 安装该插件，它也无法在 <code>v2.26.3</code> 上正常工作，因为其底层依赖和 API 与 v2.x 不兼容。</p></blockquote><hr><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">✅ <strong>替代方案与操作步骤</strong></h4><p>由于 <code>hardhat@2.26.3</code> 不支持 Ignition，必须使用 <strong>传统的部署方式</strong>，即通过 Hardhat Runtime Environment (HRE) 中的 <code>ethers</code> 插件来手动部署合约。</p><p><strong>替代方案：使用</strong> <code>ethers.deployContract()</code></p><p>这是 Hardhat v2.x 的标准部署方法，稳定、可靠、文档完善。</p><p><strong>操作步骤如下</strong>：</p><ol><li><p><strong>删除</strong> <code>ignition/</code> 目录（如果存在）：</p><pre data-type="codeBlock" text="rm -rf ignition
"><code><span class="hljs-built_in">rm</span> -rf ignition
</code></pre></li><li><p><strong>修改或创建部署脚本</strong>（如 <code>scripts/deploy.ts</code>），使用 <code>ethers.deployContract</code> 代替 <code>buildModule</code>：</p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;;

async function main() {
  // 部署 Lock 合约，构造函数参数为解锁时间戳
  const unlockTime = Math.floor(Date.now() / 1000) + 60; // 60秒后解锁
  const lockedAmount = ethers.parseEther(&quot;1&quot;); // 锁定1 ETH

  const lock = await ethers.deployContract(&quot;Lock&quot;, [unlockTime], {
    value: lockedAmount
  });

  await lock.waitForDeployment();
  console.log(`Lock contract deployed to ${lock.target}`);
}

main()
  .then(() =&gt; process.exit(0))
  .catch((error) =&gt; {
    console.error(error);
    process.exit(1);
  });
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"hardhat"</span>;

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// 部署 Lock 合约，构造函数参数为解锁时间戳</span>
  const unlockTime <span class="hljs-operator">=</span> Math.floor(Date.now() <span class="hljs-operator">/</span> <span class="hljs-number">1000</span>) <span class="hljs-operator">+</span> <span class="hljs-number">60</span>; <span class="hljs-comment">// 60秒后解锁</span>
  const lockedAmount <span class="hljs-operator">=</span> ethers.parseEther(<span class="hljs-string">"1"</span>); <span class="hljs-comment">// 锁定1 ETH</span>

  const lock <span class="hljs-operator">=</span> await ethers.deployContract(<span class="hljs-string">"Lock"</span>, [unlockTime], {
    <span class="hljs-built_in">value</span>: lockedAmount
  });

  await lock.waitForDeployment();
  console.log(`Lock <span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">deployed</span> <span class="hljs-title">to</span> <span class="hljs-title">$</span></span>{lock.target}`);
}

main()
  .then(() <span class="hljs-operator">=</span><span class="hljs-operator">></span> process.exit(<span class="hljs-number">0</span>))
  .catch((<span class="hljs-function"><span class="hljs-keyword">error</span>) => </span>{
    console.error(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
    process.exit(<span class="hljs-number">1</span>);
  });
</code></pre><blockquote><p>✅ <strong>说明</strong>：</p><ul><li><p><code>ethers.deployContract(&quot;Lock&quot;, [unlockTime], { value: lockedAmount })</code>：直接部署合约，传入构造函数参数和交易选项（如 <code>value</code>）。</p></li><li><p><code>await lock.waitForDeployment()</code>：等待部署交易上链并确认。</p></li><li><p><code>lock.target</code>：获取部署后的合约地址。</p></li></ul></blockquote></li><li><p><strong>无需修改</strong> <code>hardhat.config.ts</code> 来支持此方案，<code>ethers</code> 插件已由 <code>@nomicfoundation/hardhat-toolbox</code> 自动加载。</p></li><li><p><strong>更新</strong> <code>package.json</code> 脚本，移除 <code>deploy:ignition</code> 等相关命令，仅保留基于 <code>scripts/</code> 的部署命令。</p></li></ol><hr><h3 id="h-41-ignition-hardhat2263" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 4.1 移除 Ignition 相关代码（<code>hardhat@2.26.3</code> 不支持）</h3><blockquote><p><strong>（此节为 4.0 节的实践总结）</strong></p></blockquote><ol><li><p><strong>删除</strong> <code>ignition/</code> 目录（如果存在）：</p><pre data-type="codeBlock" text="rm -rf ignition
"><code><span class="hljs-built_in">rm</span> -rf ignition
</code></pre></li><li><p><strong>修改</strong> <code>scripts/deploy.ts</code>（如果引用了 <code>buildModule</code>）：</p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;;

async function main() {
  const lock = await ethers.deployContract(&quot;Lock&quot;, [Date.now() + 1000]);
  await lock.waitForDeployment();
  console.log(`Lock deployed to ${lock.target}`);
}

main().catch((error) =&gt; {
  console.error(error);
  process.exitCode = 1;
});
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"hardhat"</span>;

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  const lock <span class="hljs-operator">=</span> await ethers.deployContract(<span class="hljs-string">"Lock"</span>, [Date.now() <span class="hljs-operator">+</span> <span class="hljs-number">1000</span>]);
  await lock.waitForDeployment();
  console.log(`Lock deployed to ${lock.target}`);
}

main().catch((<span class="hljs-function"><span class="hljs-keyword">error</span>) => </span>{
  console.error(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
  process.exitCode <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
});
</code></pre><blockquote><p>✅ <strong>说明</strong>：使用 <code>ethers.deployContract</code> 代替 <code>buildModule</code>，这是 <code>hardhat@2.x</code> 的标准部署方式。</p></blockquote></li></ol><hr><h3 id="h-42-hardhatconfigts-solidity" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 4.2 修正 <code>hardhat.config.ts</code> 中的 Solidity 编译器版本</h3><p>确保 <code>hardhat.config.ts</code> 中的 <code>solidity</code> 配置包含 <code>0.8.28</code>：</p><pre data-type="codeBlock" text="import { HardhatUserConfig } from &quot;hardhat/config&quot;;
import &quot;@nomicfoundation/hardhat-toolbox&quot;;

const config: HardhatUserConfig = {
  solidity: {
    version: &quot;0.8.28&quot;,
    settings: {
      optimizer: {
        enabled: true,
        runs: 200,
      },
    },
  },
  networks: {
    hardhat: {
      chainId: 1337,
    },
  },
  paths: {
    sources: &quot;./contracts&quot;,
    tests: &quot;./test&quot;,
    cache: &quot;./cache&quot;,
    artifacts: &quot;./artifacts&quot;
  },
  mocha: {
    timeout: 40000
  }
};

export default config;
"><code>import { HardhatUserConfig } <span class="hljs-selector-tag">from</span> "hardhat/config";
import "<span class="hljs-keyword">@nomicfoundation</span>/hardhat-toolbox";

const config: HardhatUserConfig = {
  solidity: {
    version: <span class="hljs-string">"0.8.28"</span>,
    settings: {
      optimizer: {
        enabled: true,
        runs: <span class="hljs-number">200</span>,
      },
    },
  },
  networks: {
    hardhat: {
      chainId: <span class="hljs-number">1337</span>,
    },
  },
  paths: {
    sources: <span class="hljs-string">"./contracts"</span>,
    tests: <span class="hljs-string">"./test"</span>,
    cache: <span class="hljs-string">"./cache"</span>,
    artifacts: <span class="hljs-string">"./artifacts"</span>
  },
  mocha: {
    timeout: <span class="hljs-number">40000</span>
  }
};

export default config;
</code></pre><blockquote><p>✅ <strong>关键点</strong>：</p><ul><li><p>明确设置 <code>version: &quot;0.8.28&quot;</code>，与 <code>Lock.sol</code> 中的 <code>pragma solidity ^0.8.28;</code> 匹配。</p></li><li><p><code>hardhat-toolbox</code> 支持 <code>0.8.28</code>，无需额外安装编译器。</p></li></ul></blockquote><hr><h3 id="h-43-packagejson-ignition" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 4.3 更新 <code>package.json</code> 脚本（移除 Ignition 相关）</h3><p>确保 <code>package.json</code> 中的脚本不包含 <code>ignition</code> 相关命令：</p><pre data-type="codeBlock" text="&quot;scripts&quot;: {
  &quot;ts-node&quot;: &quot;npx ts-node&quot;,
  &quot;build&quot;: &quot;tsc&quot;,
  &quot;compile&quot;: &quot;hardhat compile&quot;,
  &quot;test&quot;: &quot;hardhat test&quot;,
  &quot;node&quot;: &quot;hardhat node&quot;,
  &quot;deploy:local&quot;: &quot;hardhat run scripts/deploy.ts --network localhost&quot;,
  &quot;deploy:sepolia&quot;: &quot;hardhat run scripts/deploy.ts --network sepolia&quot;,
  &quot;clean&quot;: &quot;npx rimraf node_modules package-lock.json dist artifacts cache coverage types&quot;,
  &quot;outdated&quot;: &quot;npm outdated&quot;,
  &quot;format&quot;: &quot;prettier --plugin prettier-plugin-solidity --write \&quot;**/*.{js,cjs,ts,sol}\&quot;&quot;,
  &quot;format:check&quot;: &quot;prettier --plugin prettier-plugin-solidity --check \&quot;**/*.{js,cjs,ts,sol}\&quot;&quot;,
  &quot;lint&quot;: &quot;eslint \&quot;**/*.{ts,js,sol}\&quot; --ext .ts,.js&quot;,
  &quot;lint:fix&quot;: &quot;eslint \&quot;**/*.{ts,js,sol}\&quot; --ext .ts,.js --fix&quot;,
  &quot;reinstall&quot;: &quot;npm run clean &amp;&amp; npm install&quot;
}
"><code><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-string">"ts-node"</span>: <span class="hljs-string">"npx ts-node"</span>,
  <span class="hljs-string">"build"</span>: <span class="hljs-string">"tsc"</span>,
  <span class="hljs-string">"compile"</span>: <span class="hljs-string">"hardhat compile"</span>,
  <span class="hljs-string">"test"</span>: <span class="hljs-string">"hardhat test"</span>,
  <span class="hljs-string">"node"</span>: <span class="hljs-string">"hardhat node"</span>,
  <span class="hljs-string">"deploy:local"</span>: <span class="hljs-string">"hardhat run scripts/deploy.ts --network localhost"</span>,
  <span class="hljs-string">"deploy:sepolia"</span>: <span class="hljs-string">"hardhat run scripts/deploy.ts --network sepolia"</span>,
  <span class="hljs-string">"clean"</span>: <span class="hljs-string">"npx rimraf node_modules package-lock.json dist artifacts cache coverage types"</span>,
  <span class="hljs-string">"outdated"</span>: <span class="hljs-string">"npm outdated"</span>,
  <span class="hljs-string">"format"</span>: <span class="hljs-string">"prettier --plugin prettier-plugin-solidity --write <span class="hljs-subst">\"</span>**/*.{js,cjs,ts,sol}<span class="hljs-subst">\"</span>"</span>,
  <span class="hljs-string">"format:check"</span>: <span class="hljs-string">"prettier --plugin prettier-plugin-solidity --check <span class="hljs-subst">\"</span>**/*.{js,cjs,ts,sol}<span class="hljs-subst">\"</span>"</span>,
  <span class="hljs-string">"lint"</span>: <span class="hljs-string">"eslint <span class="hljs-subst">\"</span>**/*.{ts,js,sol}<span class="hljs-subst">\"</span> --ext .ts,.js"</span>,
  <span class="hljs-string">"lint:fix"</span>: <span class="hljs-string">"eslint <span class="hljs-subst">\"</span>**/*.{ts,js,sol}<span class="hljs-subst">\"</span> --ext .ts,.js --fix"</span>,
  <span class="hljs-string">"reinstall"</span>: <span class="hljs-string">"npm run clean &#x26;&#x26; npm install"</span>
}
</code></pre><blockquote><p>✅ <strong>说明</strong>：已移除 <code>deploy:ignition</code> 等不适用于 <code>hardhat@2.26.3</code> 的脚本。</p></blockquote><hr><h2 id="h-3x" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🧩 五、依赖版本对齐（精确锁定，避免 <code>3.x</code> 升级）</h2><h3 id="h-51-packagejson" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 5.1 清理并替换 <code>package.json</code></h3><pre data-type="codeBlock" text="rm -rf node_modules package-lock.json
"><code>rm <span class="hljs-operator">-</span>rf node_modules package<span class="hljs-operator">-</span>lock.json
</code></pre><h3 id="h-52-packagejson-hardhat-project" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 5.2 使用更新后的 <code>package.json</code>（项目名已更改为 <code>hardhat-project</code>）</h3><pre data-type="codeBlock" text="{
  &quot;name&quot;: &quot;hardhat-project&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;main&quot;: &quot;hardhat.config.js&quot;,
  &quot;scripts&quot;: {
    &quot;ts-node&quot;: &quot;npx ts-node&quot;,
    &quot;build&quot;: &quot;tsc&quot;,
    &quot;compile&quot;: &quot;hardhat compile&quot;,
    &quot;test&quot;: &quot;hardhat test&quot;,
    &quot;node&quot;: &quot;hardhat node&quot;,
    &quot;deploy:local&quot;: &quot;hardhat run scripts/deploy.ts --network localhost&quot;,
    &quot;deploy:sepolia&quot;: &quot;hardhat run scripts/deploy.ts --network sepolia&quot;,
    &quot;clean&quot;: &quot;npx rimraf node_modules package-lock.json dist artifacts cache coverage types&quot;,
    &quot;outdated&quot;: &quot;npm outdated&quot;,
    &quot;format&quot;: &quot;prettier --plugin prettier-plugin-solidity --write \&quot;**/*.{js,cjs,ts,sol}\&quot;&quot;,
    &quot;format:check&quot;: &quot;prettier --plugin prettier-plugin-solidity --check \&quot;**/*.{js,cjs,ts,sol}\&quot;&quot;,
    &quot;lint&quot;: &quot;eslint \&quot;**/*.{ts,js,sol}\&quot; --ext .ts,.js&quot;,
    &quot;lint:fix&quot;: &quot;eslint \&quot;**/*.{ts,js,sol}\&quot; --ext .ts,.js --fix&quot;,
    &quot;reinstall&quot;: &quot;npm run clean &amp;&amp; npm install&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;@nomicfoundation/hardhat-toolbox&quot;: &quot;^4.0.0&quot;,
    &quot;@types/chai&quot;: &quot;^4.3.10&quot;,
    &quot;@types/fs-extra&quot;: &quot;^11.0.4&quot;,
    &quot;@types/glob&quot;: &quot;^8.1.0&quot;,
    &quot;@types/minimatch&quot;: &quot;^5.1.2&quot;,
    &quot;@types/node&quot;: &quot;^20.19.13&quot;,
    &quot;@typescript-eslint/eslint-plugin&quot;: &quot;^6.21.0&quot;,
    &quot;@typescript-eslint/parser&quot;: &quot;^6.21.0&quot;,
    &quot;chai&quot;: &quot;^4.3.10&quot;,
    &quot;dotenv&quot;: &quot;^16.4.5&quot;,
    &quot;eslint&quot;: &quot;^8.57.0&quot;,
    &quot;eslint-config-prettier&quot;: &quot;^9.1.0&quot;,
    &quot;eslint-plugin-prettier&quot;: &quot;^5.1.3&quot;,
    &quot;ethers&quot;: &quot;^6.15.0&quot;,
    &quot;forge-std&quot;: &quot;github:foundry-rs/forge-std#v1.9.4&quot;,
    &quot;hardhat&quot;: &quot;^2.26.3&quot;,
    &quot;minimatch&quot;: &quot;^9.0.3&quot;,
    &quot;prettier&quot;: &quot;^3.2.5&quot;,
    &quot;prettier-plugin-solidity&quot;: &quot;^1.1.3&quot;,
    &quot;ts-node&quot;: &quot;^10.9.2&quot;,
    &quot;typescript&quot;: &quot;~5.8.3&quot;
  },
  &quot;overrides&quot;: {
    &quot;globby&quot;: {
      &quot;@types/glob&quot;: &quot;$@types/glob&quot;
    },
    &quot;minimatch&quot;: {
      &quot;@types/minimatch&quot;: &quot;5.1.2&quot;
    }
  },
  &quot;dependencies&quot;: {
    &quot;crypto-js&quot;: &quot;^4.2.0&quot;
  },
  &quot;description&quot;: &quot;This project showcases a Hardhat 3 Beta project using `mocha` for tests and the `ethers` library for Ethereum interactions.&quot;,
  &quot;directories&quot;: {
    &quot;test&quot;: &quot;test&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}
"><code>{
  <span class="hljs-string">"name"</span>: <span class="hljs-string">"hardhat-project"</span>,
  <span class="hljs-string">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-string">"main"</span>: <span class="hljs-string">"hardhat.config.js"</span>,
  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"ts-node"</span>: <span class="hljs-string">"npx ts-node"</span>,
    <span class="hljs-string">"build"</span>: <span class="hljs-string">"tsc"</span>,
    <span class="hljs-string">"compile"</span>: <span class="hljs-string">"hardhat compile"</span>,
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"hardhat test"</span>,
    <span class="hljs-string">"node"</span>: <span class="hljs-string">"hardhat node"</span>,
    <span class="hljs-string">"deploy:local"</span>: <span class="hljs-string">"hardhat run scripts/deploy.ts --network localhost"</span>,
    <span class="hljs-string">"deploy:sepolia"</span>: <span class="hljs-string">"hardhat run scripts/deploy.ts --network sepolia"</span>,
    <span class="hljs-string">"clean"</span>: <span class="hljs-string">"npx rimraf node_modules package-lock.json dist artifacts cache coverage types"</span>,
    <span class="hljs-string">"outdated"</span>: <span class="hljs-string">"npm outdated"</span>,
    <span class="hljs-string">"format"</span>: <span class="hljs-string">"prettier --plugin prettier-plugin-solidity --write \"**/*.{js,cjs,ts,sol}\""</span>,
    <span class="hljs-string">"format:check"</span>: <span class="hljs-string">"prettier --plugin prettier-plugin-solidity --check \"**/*.{js,cjs,ts,sol}\""</span>,
    <span class="hljs-string">"lint"</span>: <span class="hljs-string">"eslint \"**/*.{ts,js,sol}\" --ext .ts,.js"</span>,
    <span class="hljs-string">"lint:fix"</span>: <span class="hljs-string">"eslint \"**/*.{ts,js,sol}\" --ext .ts,.js --fix"</span>,
    <span class="hljs-string">"reinstall"</span>: <span class="hljs-string">"npm run clean &#x26;&#x26; npm install"</span>
  },
  <span class="hljs-string">"devDependencies"</span>: {
    <span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span>: <span class="hljs-string">"^4.0.0"</span>,
    <span class="hljs-string">"@types/chai"</span>: <span class="hljs-string">"^4.3.10"</span>,
    <span class="hljs-string">"@types/fs-extra"</span>: <span class="hljs-string">"^11.0.4"</span>,
    <span class="hljs-string">"@types/glob"</span>: <span class="hljs-string">"^8.1.0"</span>,
    <span class="hljs-string">"@types/minimatch"</span>: <span class="hljs-string">"^5.1.2"</span>,
    <span class="hljs-string">"@types/node"</span>: <span class="hljs-string">"^20.19.13"</span>,
    <span class="hljs-string">"@typescript-eslint/eslint-plugin"</span>: <span class="hljs-string">"^6.21.0"</span>,
    <span class="hljs-string">"@typescript-eslint/parser"</span>: <span class="hljs-string">"^6.21.0"</span>,
    <span class="hljs-string">"chai"</span>: <span class="hljs-string">"^4.3.10"</span>,
    <span class="hljs-string">"dotenv"</span>: <span class="hljs-string">"^16.4.5"</span>,
    <span class="hljs-string">"eslint"</span>: <span class="hljs-string">"^8.57.0"</span>,
    <span class="hljs-string">"eslint-config-prettier"</span>: <span class="hljs-string">"^9.1.0"</span>,
    <span class="hljs-string">"eslint-plugin-prettier"</span>: <span class="hljs-string">"^5.1.3"</span>,
    <span class="hljs-string">"ethers"</span>: <span class="hljs-string">"^6.15.0"</span>,
    <span class="hljs-string">"forge-std"</span>: <span class="hljs-string">"github:foundry-rs/forge-std#v1.9.4"</span>,
    <span class="hljs-string">"hardhat"</span>: <span class="hljs-string">"^2.26.3"</span>,
    <span class="hljs-string">"minimatch"</span>: <span class="hljs-string">"^9.0.3"</span>,
    <span class="hljs-string">"prettier"</span>: <span class="hljs-string">"^3.2.5"</span>,
    <span class="hljs-string">"prettier-plugin-solidity"</span>: <span class="hljs-string">"^1.1.3"</span>,
    <span class="hljs-string">"ts-node"</span>: <span class="hljs-string">"^10.9.2"</span>,
    <span class="hljs-string">"typescript"</span>: <span class="hljs-string">"~5.8.3"</span>
  },
  <span class="hljs-string">"overrides"</span>: {
    <span class="hljs-string">"globby"</span>: {
      <span class="hljs-string">"@types/glob"</span>: <span class="hljs-string">"$@types/glob"</span>
    },
    <span class="hljs-string">"minimatch"</span>: {
      <span class="hljs-string">"@types/minimatch"</span>: <span class="hljs-string">"5.1.2"</span>
    }
  },
  <span class="hljs-string">"dependencies"</span>: {
    <span class="hljs-string">"crypto-js"</span>: <span class="hljs-string">"^4.2.0"</span>
  },
  <span class="hljs-string">"description"</span>: <span class="hljs-string">"This project showcases a Hardhat 3 Beta project using `mocha` for tests and the `ethers` library for Ethereum interactions."</span>,
  <span class="hljs-string">"directories"</span>: {
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"test"</span>
  },
  <span class="hljs-string">"keywords"</span>: [],
  <span class="hljs-string">"author"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-string">"license"</span>: <span class="hljs-string">"ISC"</span>
}
</code></pre><blockquote><p>✅ <strong>关键点</strong>：</p><ul><li><p><code>&quot;name&quot;: &quot;hardhat-project&quot;</code>：项目名称已按要求更新。</p></li><li><p><code>&quot;hardhat&quot;: &quot;^2.26.3&quot;</code>：明确锁定 <code>2.x</code> 分支，避免意外升级到 <code>3.x</code>。</p></li><li><p><code>&quot;@nomicfoundation/hardhat-toolbox&quot;: &quot;^4.0.0&quot;</code>：与 <code>hardhat@2.26.3</code> 完全兼容。</p></li><li><p><code>&quot;eslint&quot;: &quot;^8.57.0&quot;</code>：<code>toolbox</code> 所需，不可升级至 v9。</p></li></ul></blockquote><hr><h3 id="h-53" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 5.3 安装最终依赖</h3><pre data-type="codeBlock" text="npm install
"><code></code></pre><blockquote><p>⚠️ 安装后可能出现 <code>13 low severity vulnerabilities</code>，请参见下方 <strong>十、安全审计问题说明与处理建议</strong>。</p></blockquote><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">⚙️ 六、新增与修改的配置文件详解</h2><h3 id="h-61-prettierrc" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 6.1 <code>.prettierrc</code>（新增）</h3><pre data-type="codeBlock" text="{
  &quot;semi&quot;: false,
  &quot;singleQuote&quot;: false,
  &quot;printWidth&quot;: 80,
  &quot;tabWidth&quot;: 4,
  &quot;useTabs&quot;: false,
  &quot;endOfLine&quot;: &quot;lf&quot;,
  &quot;arrowParens&quot;: &quot;avoid&quot;,
  &quot;plugins&quot;: [&quot;prettier-plugin-solidity&quot;]
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"semi"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"singleQuote"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"printWidth"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">80</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"tabWidth"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">4</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"useTabs"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"endOfLine"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"lf"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"arrowParens"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"avoid"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"plugins"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"prettier-plugin-solidity"</span><span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre><blockquote><p><strong>作用</strong>：定义代码格式化规则。</p><ul><li><p><code>semi: false</code>：不使用分号结尾。</p></li><li><p><code>singleQuote: false</code>：使用双引号。</p></li><li><p><code>printWidth: 80</code>：每行最大 80 字符。</p></li><li><p><code>tabWidth: 4</code>：缩进 4 空格。</p></li><li><p><code>useTabs: false</code>：使用空格缩进。</p></li><li><p><code>endOfLine: &quot;lf&quot;</code>：使用 LF 换行符（Unix 风格）。</p></li><li><p><code>arrowParens: &quot;avoid&quot;</code>：箭头函数参数为单个时省略括号。</p></li><li><p><code>plugins: [&quot;prettier-plugin-solidity&quot;]</code>：支持 Solidity 格式化。</p></li></ul></blockquote><hr><h3 id="h-62-eslintconfigjs" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 6.2 <code>eslint.config.js</code>（新增）</h3><pre data-type="codeBlock" text="module.exports = {
  env: {
    es2021: true,
    node: true,
  },
  extends: [
    &quot;eslint:recommended&quot;,
    &quot;plugin:@typescript-eslint/recommended&quot;,
    &quot;prettier&quot;
  ],
  parser: &quot;@typescript-eslint/parser&quot;,
  parserOptions: {
    ecmaVersion: 12,
    sourceType: &quot;module&quot;
  },
  plugins: [&quot;@typescript-eslint&quot;, &quot;prettier&quot;],
  rules: {
    &quot;prettier/prettier&quot;: &quot;error&quot;,
    &quot;no-console&quot;: &quot;off&quot;,
    &quot;no-debugger&quot;: &quot;warn&quot;
  },
  ignorePatterns: [&quot;node_modules/&quot;, &quot;dist/&quot;]
};
"><code>module<span class="hljs-selector-class">.exports</span> = {
  env: {
    es2021: true,
    node: true,
  },
  extends: [
    <span class="hljs-string">"eslint:recommended"</span>,
    <span class="hljs-string">"plugin:@typescript-eslint/recommended"</span>,
    <span class="hljs-string">"prettier"</span>
  ],
  parser: <span class="hljs-string">"@typescript-eslint/parser"</span>,
  parserOptions: {
    ecmaVersion: <span class="hljs-number">12</span>,
    sourceType: <span class="hljs-string">"module"</span>
  },
  plugins: [<span class="hljs-string">"@typescript-eslint"</span>, <span class="hljs-string">"prettier"</span>],
  rules: {
    "prettier/prettier": <span class="hljs-string">"error"</span>,
    <span class="hljs-string">"no-console"</span>: <span class="hljs-string">"off"</span>,
    <span class="hljs-string">"no-debugger"</span>: <span class="hljs-string">"warn"</span>
  },
  ignorePatterns: [<span class="hljs-string">"node_modules/"</span>, <span class="hljs-string">"dist/"</span>]
};
</code></pre><blockquote><p><strong>作用</strong>：ESLint 代码检查配置。</p><ul><li><p>继承 <code>eslint:recommended</code> 和 <code>@typescript-eslint/recommended</code>。</p></li><li><p>集成 <code>prettier</code>，冲突时以 Prettier 为准。</p></li><li><p><code>prettier/prettier: &quot;error&quot;</code>：格式错误视为 ESLint 错误。</p></li><li><p><code>no-console: &quot;off&quot;</code>：允许使用 <code>console.log</code>。</p></li><li><p><code>no-debugger: &quot;warn&quot;</code>：调试器语句仅警告。</p></li><li><p><code>ignorePatterns</code>：忽略 <code>node_modules/</code> 和 <code>dist/</code> 目录。</p></li></ul></blockquote><hr><h3 id="h-63-editorconfig" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 6.3 <code>.editorconfig</code>（新增）</h3><pre data-type="codeBlock" text="root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.sol]
indent_size = 4

[*.md]
trim_trailing_whitespace = false
"><code><span class="hljs-attr">root</span> = <span class="hljs-literal">true</span>

<span class="hljs-section">[*]</span>
<span class="hljs-attr">charset</span> = utf-<span class="hljs-number">8</span>
<span class="hljs-attr">indent_style</span> = space
<span class="hljs-attr">indent_size</span> = <span class="hljs-number">4</span>
<span class="hljs-attr">end_of_line</span> = lf
<span class="hljs-attr">insert_final_newline</span> = <span class="hljs-literal">true</span>
<span class="hljs-attr">trim_trailing_whitespace</span> = <span class="hljs-literal">true</span>

<span class="hljs-section">[*.sol]</span>
<span class="hljs-attr">indent_size</span> = <span class="hljs-number">4</span>

<span class="hljs-section">[*.md]</span>
<span class="hljs-attr">trim_trailing_whitespace</span> = <span class="hljs-literal">false</span>
</code></pre><blockquote><p><strong>作用</strong>：统一不同编辑器的基础风格。</p><ul><li><p><code>[*]</code>：所有文件使用 UTF-8、4 空格缩进、LF 换行。</p></li><li><p><code>[*.sol]</code>：Solidity 文件缩进为 4 空格。</p></li><li><p><code>[*.md]</code>：Markdown 文件允许行尾空格。</p></li></ul></blockquote><hr><h3 id="h-64-env" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 6.4 <code>.env</code>（新增）</h3><pre data-type="codeBlock" text="REMOTE_TEST_PRIVATE_KEY=&quot;私钥&quot;
REMOTE_TEST_RPC_URL=&quot;测试网地址&quot;
ENCRYPTION_PASSWORD=&quot;加密密码&quot;
"><code><span class="hljs-attr">REMOTE_TEST_PRIVATE_KEY</span>=<span class="hljs-string">"私钥"</span>
<span class="hljs-attr">REMOTE_TEST_RPC_URL</span>=<span class="hljs-string">"测试网地址"</span>
<span class="hljs-attr">ENCRYPTION_PASSWORD</span>=<span class="hljs-string">"加密密码"</span>
</code></pre><blockquote><p><strong>作用</strong>：存储敏感环境变量，<strong>不应提交到 Git</strong>。</p></blockquote><hr><h3 id="h-65-gitignore" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 6.5 <code>.gitignore</code>（增强）</h3><pre data-type="codeBlock" text="# Node modules
/node_modules

# Compilation output
/dist

# Hardhat Build Artifacts
/artifacts
/cache
/coverage
/types

# IDE &amp; Editor
.vscode/*
!.vscode/settings.json

# Environment
.env
encryptedKey.json
.env.local

# Logs
*.log

# Prettier &amp; ESLint cache
.node_modules
.cache
eslint-cache

# OS
.DS_Store
Thumbs.db
"><code># Node modules
<span class="hljs-operator">/</span>node_modules

# Compilation output
<span class="hljs-operator">/</span>dist

# Hardhat Build Artifacts
<span class="hljs-operator">/</span>artifacts
<span class="hljs-operator">/</span>cache
<span class="hljs-operator">/</span>coverage
<span class="hljs-operator">/</span>types

# IDE <span class="hljs-operator">&#x26;</span> Editor
.vscode/<span class="hljs-operator">*</span>
<span class="hljs-operator">!</span>.vscode/settings.json

# Environment
.env
encryptedKey.json
.env.local

# Logs
<span class="hljs-operator">*</span>.log

# Prettier <span class="hljs-operator">&#x26;</span> ESLint cache
.node_modules
.cache
eslint<span class="hljs-operator">-</span>cache

# OS
.DS_Store
Thumbs.db
</code></pre><blockquote><p><strong>作用</strong>：在初始 <code>.gitignore</code> 基础上增强，新增忽略 <code>dist/</code>, <code>cache/</code>, <code>coverage/</code>, <code>encryptedKey.json</code>, <code>.env.*</code> 等敏感或构建产物。</p></blockquote><hr><h3 id="h-66-vscodesettingsjson" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 6.6 <code>.vscode/settings.json</code>（增强）</h3><pre data-type="codeBlock" text="{
    &quot;editor.tabSize&quot;: 4,
    &quot;editor.detectIndentation&quot;: false,
    &quot;editor.insertSpaces&quot;: true,
    &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;,
    &quot;editor.formatOnSave&quot;: true,
    &quot;editor.codeActionsOnSave&quot;: {
        &quot;source.fixAll.eslint&quot;: &quot;explicit&quot;
    },
    &quot;files.autoSave&quot;: &quot;onFocusChange&quot;,
    &quot;files.eol&quot;: &quot;\n&quot;,
    &quot;typescript.validate.enable&quot;: true,
    &quot;javascript.validate.enable&quot;: false
}
"><code>{
    <span class="hljs-string">"editor.tabSize"</span>: <span class="hljs-number">4</span>,
    <span class="hljs-string">"editor.detectIndentation"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-string">"editor.insertSpaces"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"editor.defaultFormatter"</span>: <span class="hljs-string">"esbenp.prettier-vscode"</span>,
    <span class="hljs-string">"editor.formatOnSave"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"editor.codeActionsOnSave"</span>: {
        <span class="hljs-string">"source.fixAll.eslint"</span>: <span class="hljs-string">"explicit"</span>
    },
    <span class="hljs-string">"files.autoSave"</span>: <span class="hljs-string">"onFocusChange"</span>,
    <span class="hljs-string">"files.eol"</span>: <span class="hljs-string">"<span class="hljs-subst">\n</span>"</span>,
    <span class="hljs-string">"typescript.validate.enable"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"javascript.validate.enable"</span>: <span class="hljs-literal">false</span>
}
</code></pre><blockquote><p><strong>作用</strong>：配置 VS Code 实现保存时自动格式化（Prettier）和修复（ESLint）。</p></blockquote><hr><h2 id="h-vs-code-typescript-tsconfigjson" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">⚠️ 七、修复 VS Code TypeScript 编译器错误（<code>tsconfig.json</code> 问题）</h2><h3 id="h-70" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🚫 7.0 问题描述</h3><p>在 VS Code 中打开项目时，<code>node_modules/@nomicfoundation/hardhat-toolbox/src/tsconfig.json</code> 文件出现以下 TypeScript 编译错误：</p><pre data-type="codeBlock" text="无法读取文件“.../node_modules/config/typescript/tsconfig.json”。
Parent configuration missing
找不到文件“.../node_modules/@nomicfoundation/hardhat-core/src”。
找不到文件“.../node_modules/@nomicfoundation/hardhat-chai-matchers”。
找不到文件“.../node_modules/@nomicfoundation/hardhat-ethers/src”。
...
"><code>无法读取文件“.../node_modules<span class="hljs-operator">/</span>config<span class="hljs-operator">/</span>typescript<span class="hljs-operator">/</span>tsconfig.json”。
Parent configuration missing
找不到文件“.../node_modules<span class="hljs-operator">/</span>@nomicfoundation<span class="hljs-operator">/</span>hardhat<span class="hljs-operator">-</span>core<span class="hljs-operator">/</span>src”。
找不到文件“.../node_modules<span class="hljs-operator">/</span>@nomicfoundation<span class="hljs-operator">/</span>hardhat<span class="hljs-operator">-</span>chai<span class="hljs-operator">-</span>matchers”。
找不到文件“.../node_modules<span class="hljs-operator">/</span>@nomicfoundation<span class="hljs-operator">/</span>hardhat<span class="hljs-operator">-</span>ethers<span class="hljs-operator">/</span>src”。
...
</code></pre><p>这些错误虽然<strong>不影响项目编译、测试和部署的实际运行</strong>，但会在 VS Code 的“问题”面板中显示，可能干扰开发体验。</p><hr><h3 id="h-71" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🔍 7.1 根本原因分析</h3><p>这些错误源于 <code>@nomicfoundation/hardhat-toolbox</code> 包内部的 <code>tsconfig.json</code> 文件配置：</p><pre data-type="codeBlock" text="{
  &quot;extends&quot;: &quot;../config/typescript/tsconfig.json&quot;,
  &quot;compilerOptions&quot;: {
    &quot;composite&quot;: true,
    &quot;outDir&quot;: &quot;../../dist&quot;
  },
  &quot;references&quot;: [
    { &quot;path&quot;: &quot;../hardhat-core/src&quot; },
    { &quot;path&quot;: &quot;../hardhat-chai-matchers&quot; },
    { &quot;path&quot;: &quot;../hardhat-network-helpers&quot; },
    { &quot;path&quot;: &quot;../hardhat-ethers/src&quot; },
    { &quot;path&quot;: &quot;../hardhat-waffle/src&quot; }
  ]
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"extends"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../config/typescript/tsconfig.json"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"compilerOptions"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"composite"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"outDir"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../../dist"</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"references"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"path"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../hardhat-core/src"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"path"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../hardhat-chai-matchers"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"path"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../hardhat-network-helpers"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"path"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../hardhat-ethers/src"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span> <span class="hljs-attr">"path"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../hardhat-waffle/src"</span> <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre><p><strong>问题本质</strong>：</p><ol><li><p><code>extends</code> 路径错误：<code>../config/typescript/tsconfig.json</code> 不存在于 <code>node_modules</code> 中。该路径是 Hardhat 团队在<strong>源码仓库</strong>中使用的，用于构建流程。</p></li><li><p><code>references</code> 路径失效：<code>&quot;../hardhat-core/src&quot;</code> 等路径在 <code>node_modules</code> 中无法解析，因为 <code>hardhat-core</code> 等包的源码（<code>src/</code> 目录）<strong>不会被发布到 npm</strong>。npm 发布的是编译后的 <code>dist/</code> 文件。</p></li><li><p><strong>开发构建配置</strong>：此 <code>tsconfig.json</code> 是 <code>hardhat-toolbox</code> 项目在<strong>开发和构建阶段</strong>使用的配置，用于将 <code>toolbox</code> 与 <code>core</code>、<code>ethers</code> 等插件组合编译。一旦发布，此配置对使用者已无实际意义。</p></li></ol><blockquote><p>✅ <strong>结论</strong>：这些错误是<strong>无害的</strong>。VS Code 的 TypeScript 语言服务试图解析所有可见的 <code>tsconfig.json</code> 文件，但 <code>node_modules</code> 中的此类配置文件<strong>不应被主项目继承或使用</strong>。</p></blockquote><hr><h2 id="h-72" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">#✅ 7.2 推荐解决方案（无需修改源码）</h2><p>最安全、最推荐的做法是：让 VS Code 忽略 <code>node_modules</code> 中的 <code>tsconfig.json</code> 文件。</p><h3 id="h-vs-code" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 方法一：修改 VS Code 设置（全局或工作区）</h3><p>在 VS Code 的设置中添加以下配置，阻止其扫描 <code>node_modules</code> 目录下的 <code>tsconfig.json</code> 文件：</p><pre data-type="codeBlock" text="{
  &quot;typescript.tsdk&quot;: &quot;node_modules/typescript/lib&quot;,
  &quot;typescript.enableTsServerTrace&quot;: false,
  &quot;typescript.preferences.includePackageJsonAutoImports&quot;: &quot;auto&quot;,
  &quot;typescript.suggest.autoImports&quot;: true,
  &quot;typescript.validate.enable&quot;: true,
  &quot;javascript.validate.enable&quot;: true,
  &quot;typescript.tsc.autoDetect&quot;: &quot;on&quot;,
  &quot;typescript.preferences.renameShorthandProperties&quot;: true,
  &quot;typescript.suggest.enabled&quot;: true,
  &quot;typescript.updateImportsOnFileMove.enabled&quot;: &quot;prompt&quot;,
  &quot;typescript.preferences.includeInlayParameterNameHints&quot;: &quot;literals&quot;,
  &quot;typescript.inlayHints.parameterNames.enabled&quot;: false,
  &quot;typescript.inlayHints.variableTypes.enabled&quot;: false,
  &quot;typescript.inlayHints.propertyDeclarationTypes.enabled&quot;: false,
  &quot;typescript.inlayHints.functionLikeReturnTypes.enabled&quot;: false,
  &quot;typescript.inlayHints.enumMemberValues.enabled&quot;: false,
  &quot;typescript.preferences.quoteStyle&quot;: &quot;auto&quot;,
  &quot;typescript.suggest.completeJSDocs&quot;: true,
  &quot;typescript.suggest.autoImportSuggestionsMode&quot;: &quot;recentlyUsed&quot;,
  &quot;typescript.suggest.showModuleSuggestions&quot;: true,
  &quot;typescript.suggest.showClassSuggestions&quot;: true,
  &quot;typescript.suggest.showInterfaceSuggestions&quot;: true,
  &quot;typescript.suggest.showConstructorSuggestions&quot;: true,
  &quot;typescript.suggest.showModuleSuggestions&quot;: true,
  &quot;typescript.suggest.showVariableSuggestions&quot;: true,
  &quot;typescript.suggest.showPropertySuggestions&quot;: true,
  &quot;typescript.suggest.showFunctionSuggestions&quot;: true,
  &quot;typescript.suggest.showMethodSuggestions&quot;: true,
  &quot;typescript.suggest.showEventSuggestions&quot;: true,
  &quot;typescript.suggest.showOperatorSuggestions&quot;: true,
  &quot;typescript.suggest.showKeywordSuggestions&quot;: true,
  &quot;typescript.suggest.showSnippetSuggestions&quot;: true,
  &quot;typescript.suggest.showPathSuggestions&quot;: true,
  &quot;typescript.suggest.showDeprecatedItems&quot;: true,
  &quot;typescript.suggest.autoImports&quot;: true,
  &quot;typescript.suggest.names&quot;: true,
  &quot;typescript.suggest.paths&quot;: true,
  &quot;typescript.suggest.packageJson&quot;: true,
  &quot;typescript.suggest.importModuleSpecifier&quot;: &quot;auto&quot;,
  &quot;typescript.suggest.importModuleSpecifierEnding&quot;: &quot;auto&quot;,
  &quot;typescript.suggest.includeCompletionsForImportStatements&quot;: true,
  &quot;typescript.suggest.includeCompletionsForModuleExports&quot;: true,
  &quot;typescript.suggest.includeCompletionsWithInsertText&quot;: true,
  &quot;typescript.suggest.includeCompletionsWithSnippetText&quot;: true,
  &quot;typescript.suggest.filterSuggestions&quot;: true,
  &quot;typescript.suggest.autoImports&quot;: true,
  &quot;typescript.preferences.includePackageJsonAutoImports&quot;: &quot;auto&quot;
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"typescript.tsdk"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"node_modules/typescript/lib"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.enableTsServerTrace"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.includePackageJsonAutoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.validate.enable"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"javascript.validate.enable"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.tsc.autoDetect"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"on"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.renameShorthandProperties"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.updateImportsOnFileMove.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"prompt"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.includeInlayParameterNameHints"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"literals"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.parameterNames.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.variableTypes.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.propertyDeclarationTypes.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.functionLikeReturnTypes.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.enumMemberValues.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.quoteStyle"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.completeJSDocs"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImportSuggestionsMode"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"recentlyUsed"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showModuleSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showClassSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showInterfaceSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showConstructorSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showModuleSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showVariableSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showPropertySuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showFunctionSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showMethodSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showEventSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showOperatorSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showKeywordSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showSnippetSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showPathSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showDeprecatedItems"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.names"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.paths"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.packageJson"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.importModuleSpecifier"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.importModuleSpecifierEnding"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.includeCompletionsForImportStatements"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.includeCompletionsForModuleExports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.includeCompletionsWithInsertText"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.includeCompletionsWithSnippetText"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.filterSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.includePackageJsonAutoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span>
<span class="hljs-punctuation">}</span>
</code></pre><p>更关键的是，确保 VS Code 不加载 <code>node_modules</code> 中的配置文件。可在工作区 <code>.vscode/settings.json</code> 中添加：</p><pre data-type="codeBlock" text="{
  &quot;typescript.preferences.disableSuggestions&quot;: false,
  &quot;typescript.suggest.enabled&quot;: true,
  &quot;typescript.validate.enable&quot;: true,
  &quot;typescript.tsc.autoDetect&quot;: &quot;on&quot;,
  &quot;typescript.tsdk&quot;: &quot;node_modules/typescript/lib&quot;,
  &quot;typescript.disableAutomaticTypeAcquisition&quot;: false,
  &quot;typescript.suggest.autoImports&quot;: true,
  &quot;typescript.suggest.includeCompletionsForImportStatements&quot;: true,
  &quot;typescript.suggest.includeCompletionsWithSnippetText&quot;: true,
  &quot;typescript.suggest.filterSuggestions&quot;: true,
  &quot;typescript.suggest.autoImports&quot;: true,
  &quot;typescript.preferences.includePackageJsonAutoImports&quot;: &quot;auto&quot;,
  &quot;typescript.preferences.quoteStyle&quot;: &quot;auto&quot;,
  &quot;typescript.preferences.renameShorthandProperties&quot;: true,
  &quot;typescript.preferences.includeInlayParameterNameHints&quot;: &quot;none&quot;,
  &quot;typescript.inlayHints.parameterNames.enabled&quot;: false,
  &quot;typescript.inlayHints.variableTypes.enabled&quot;: false,
  &quot;typescript.inlayHints.propertyDeclarationTypes.enabled&quot;: false,
  &quot;typescript.inlayHints.functionLikeReturnTypes.enabled&quot;: false,
  &quot;typescript.inlayHints.enumMemberValues.enabled&quot;: false,
  &quot;typescript.updateImportsOnFileMove.enabled&quot;: &quot;prompt&quot;,
  &quot;typescript.suggest.completeJSDocs&quot;: true,
  &quot;typescript.suggest.autoImportSuggestionsMode&quot;: &quot;all&quot;,
  &quot;typescript.suggest.showModuleSuggestions&quot;: true,
  &quot;typescript.suggest.names&quot;: true,
  &quot;typescript.suggest.paths&quot;: true,
  &quot;typescript.suggest.packageJson&quot;: true,
  &quot;typescript.suggest.importModuleSpecifier&quot;: &quot;auto&quot;,
  &quot;typescript.suggest.importModuleSpecifierEnding&quot;: &quot;auto&quot;,
  &quot;typescript.preferences.disableAutomaticTypeAcquisition&quot;: false
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"typescript.preferences.disableSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.validate.enable"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.tsc.autoDetect"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"on"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.tsdk"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"node_modules/typescript/lib"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.disableAutomaticTypeAcquisition"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.includeCompletionsForImportStatements"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.includeCompletionsWithSnippetText"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.filterSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.includePackageJsonAutoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.quoteStyle"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.renameShorthandProperties"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.includeInlayParameterNameHints"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"none"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.parameterNames.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.variableTypes.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.propertyDeclarationTypes.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.functionLikeReturnTypes.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.inlayHints.enumMemberValues.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.updateImportsOnFileMove.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"prompt"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.completeJSDocs"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImportSuggestionsMode"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"all"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.showModuleSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.names"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.paths"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.packageJson"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.importModuleSpecifier"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.importModuleSpecifierEnding"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.disableAutomaticTypeAcquisition"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span>
<span class="hljs-punctuation">}</span>
</code></pre><p>或者，直接通过 VS Code 图形界面操作：</p><ol><li><p>打开命令面板（Ctrl+Shift+P）</p></li><li><p>输入并选择 “Preferences: Open Settings (JSON)”</p></li><li><p>在打开的 <code>settings.json</code> 文件中添加：</p></li></ol><pre data-type="codeBlock" text="{
  &quot;typescript.preferences.disableSuggestions&quot;: false,
  &quot;typescript.suggest.enabled&quot;: true,
  &quot;typescript.validate.enable&quot;: true,
  &quot;typescript.tsc.autoDetect&quot;: &quot;on&quot;,
  &quot;typescript.tsdk&quot;: &quot;node_modules/typescript/lib&quot;,
  &quot;typescript.disableAutomaticTypeAcquisition&quot;: false,
  &quot;typescript.suggest.autoImports&quot;: true
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"typescript.preferences.disableSuggestions"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.enabled"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.validate.enable"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.tsc.autoDetect"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"on"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.tsdk"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"node_modules/typescript/lib"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.disableAutomaticTypeAcquisition"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="hljs-punctuation">}</span>
</code></pre><h2 id="h-vs-code-tsconfigjson-nodemodules" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">这样配置后，VS Code 将优先使用项目根目录的 <code>tsconfig.json</code>，并忽略 <code>node_modules</code> 中可能干扰的配置文件，从根本上避免类型冲突问题。</h2><p><strong>简化并提供正确方案如下：</strong></p><hr><h3 id="h-72" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 7.2 推荐解决方案（无需修改源码）</h3><p><strong>最安全、最推荐的做法是：让 VS Code 忽略</strong> <code>node_modules</code> 中的 <code>tsconfig.json</code> 文件。</p><h4 id="h-vs-code" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">✅ 方法一：修改 VS Code 设置（工作区级）</h4><p>在项目根目录的 <code>.vscode/settings.json</code> 中添加：</p><pre data-type="codeBlock" text="{
  &quot;typescript.validate.enable&quot;: true,
  &quot;typescript.validate.disableDeepValidation&quot;: true,
  &quot;typescript.suggest.autoImports&quot;: false,
  &quot;typescript.preferences.includePackageJsonAutoImports&quot;: &quot;off&quot;,
  &quot;typescript.tsserver.experimental.enableProjectDiagnostics&quot;: false
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"typescript.validate.enable"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.validate.disableDeepValidation"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.suggest.autoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.preferences.includePackageJsonAutoImports"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"off"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"typescript.tsserver.experimental.enableProjectDiagnostics"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span>
<span class="hljs-punctuation">}</span>
</code></pre><blockquote><p><strong>说明</strong>：</p><ul><li><p><code>&quot;typescript.validate.disableDeepValidation&quot;: true</code>：禁用对 <code>node_modules</code> 的深度类型验证，可显著减少错误提示。</p></li><li><p>其他设置用于优化 TypeScript 语言服务性能。</p></li></ul></blockquote><h4 id="h-tsconfigjson" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">✅ 方法二：使用 <code>tsconfig.json</code> 排除（项目级）</h4><p>在项目根目录的 <code>tsconfig.json</code> 中添加 <code>exclude</code> 字段：</p><pre data-type="codeBlock" text="{
  &quot;compilerOptions&quot;: {
    // ... 你的现有配置
  },
  &quot;exclude&quot;: [
    &quot;node_modules&quot;
  ]
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"compilerOptions"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-comment">// ... 你的现有配置</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"exclude"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-string">"node_modules"</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre><blockquote><p><strong>说明</strong>：明确告诉 TypeScript 编译器忽略 <code>node_modules</code> 目录。虽然语言服务可能仍会索引，但可减少错误。</p></blockquote><h4 id="h-nodemodules-ts-vs-code" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">✅ 方法三：关闭 <code>node_modules</code> 的 TS 验证（VS Code 设置）</h4><p>在 VS Code 的 <code>settings.json</code> 中：</p><pre data-type="codeBlock" text="{
  &quot;typescript.validate.enable&quot;: false
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"typescript.validate.enable"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span>
<span class="hljs-punctuation">}</span>
</code></pre><blockquote><p><strong>⚠️ 警告</strong>：此方法会完全关闭 TypeScript 验证，<strong>不推荐</strong>。</p></blockquote><hr><h3 id="h-73-tsconfigjson" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 7.3 替代方案（修改 <code>tsconfig.json</code>，不推荐）</h3><p><strong>仅当上述方法无效且错误严重影响开发时考虑。</strong></p><ol><li><p><strong>定位文件</strong>：</p><pre data-type="codeBlock" text="# Windows
notepad &quot;node_modules/@nomicfoundation/hardhat-toolbox/src/tsconfig.json&quot;
"><code><span class="hljs-comment"># Windows</span>
notepad <span class="hljs-string">"node_modules/@nomicfoundation/hardhat-toolbox/src/tsconfig.json"</span>
</code></pre></li><li><p><strong>修改为</strong>：</p><pre data-type="codeBlock" text="{
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;../../dist&quot;
  }
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"compilerOptions"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"outDir"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"../../dist"</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre></li><li><p><strong>保存后重启 VS Code</strong>。</p></li></ol><blockquote><p>❌ <strong>为什么不推荐</strong>：</p><ul><li><p>修改 <code>node_modules</code> 是<strong>临时且危险的</strong>。</p></li><li><p><code>npm install</code> 会<strong>覆盖修改</strong>。</p></li><li><p>可能破坏包的构建信息。</p></li></ul></blockquote><hr><h2 id="h-v2263" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🧪 八、验证环境（确保 <code>v2.26.3</code> 正常工作）</h2><h3 id="h-81" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 8.1 编译合约</h3><pre data-type="codeBlock" text="npx hardhat compile
"><code>npx hardhat <span class="hljs-built_in">compile</span>
</code></pre><blockquote><p>✅ 输出：<code>Compiled 1 Solidity file successfully</code></p></blockquote><hr><h3 id="h-82" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 8.2 运行测试</h3><pre data-type="codeBlock" text="npx hardhat test
"><code>npx hardhat <span class="hljs-built_in">test</span>
</code></pre><blockquote><p>✅ 输出：<code>1 passing</code></p></blockquote><hr><h3 id="h-83" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 8.3 启动本地节点</h3><pre data-type="codeBlock" text="npx hardhat node
"><code></code></pre><blockquote><p>✅ 输出：<code>Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/</code></p></blockquote><hr><h3 id="h-84" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 8.4 部署测试</h3><pre data-type="codeBlock" text="npx hardhat run scripts/deploy.ts --network localhost
"><code>npx hardhat run scripts<span class="hljs-operator">/</span>deploy.ts <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network localhost
</code></pre><blockquote><p>✅ 输出：<code>Lock with 1 ETH and unlock timestamp ... deployed to ...</code></p></blockquote><hr><h2 id="h-ts-node" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📦 九、智能合约开发常用命令汇总（含 ts-node 执行）</h2><p>| 命令 | 说明 |</p><p>|------|------|</p><p>| <code>npx hardhat compile</code> | 编译 Solidity 合约 |</p><p>| <code>npx hardhat test</code> | 运行测试用例 |</p><p>| <code>npx hardhat node</code> | 启动本地 Hardhat 节点（本地测试网） |</p><p>| <code>npx hardhat run scripts/deploy.ts --network localhost</code> | 部署合约到本地节点 |</p><p>| <code>npx hardhat run scripts/deploy.ts --network sepolia</code> | 部署合约到 Sepolia 测试网 |</p><p>| <code>npm run format</code> | 格式化代码（通常使用 Prettier） |</p><p>| <code>npm run lint</code> | 检查代码规范（通常使用 ESLint） |</p><p>| <code>npm run clean</code> | 清理构建产物（如 <code>artifacts/</code>, <code>cache/</code> 等） |</p><p>| <code>npm run reinstall</code> | 删除 <code>node_modules</code> 并重新安装依赖 |</p><p>| <code>npm run ts-node -- your-script.ts</code> | 使用 ts-node 直接执行任意 TypeScript 脚本 |</p><p>| <code>npx ts-node your-script.ts</code> | 直接通过 npx 执行 TypeScript 脚本（无需 npm run） |</p><p>| <code>npx hardhat clean</code> | 清理 Hardhat 编译缓存和构建产物（包括 <code>artifacts/</code> 和 <code>cache/</code> 目录） |</p><p>| <code>npx tsc</code> | 将 TypeScript 文件编译为 JavaScript（需确保 <code>tsconfig.json</code> 配置正确） |</p><blockquote><p>✅ <code>ts-node</code> 使用场景说明：</p><p>当本人编写了一些独立的 TypeScript 脚本（例如用于数据处理、API 调用、批量操作等），但不想将其作为 Hardhat 任务运行时，可以使用 <code>ts-node</code> 直接执行：</p><pre data-type="codeBlock" text="# 创建一个独立的工具脚本
echo &apos;console.log(&quot;Hello from ts-node!&quot;);&apos; &gt; tools/hello.ts

# 执行该脚本
npx ts-node tools/hello.ts
"><code># 创建一个独立的工具脚本
echo <span class="hljs-string">'console.log("Hello from ts-node!");'</span> <span class="hljs-operator">></span> tools<span class="hljs-operator">/</span>hello.ts

# 执行该脚本
npx ts<span class="hljs-operator">-</span>node tools<span class="hljs-operator">/</span>hello.ts
</code></pre><p>输出：</p><pre data-type="codeBlock" text="Hello from ts-node!
"><code>Hello <span class="hljs-keyword">from</span> ts<span class="hljs-operator">-</span>node<span class="hljs-operator">!</span>
</code></pre><p><strong>优势</strong>：</p><ul><li><p>无需编译即可运行 <code>.ts</code> 文件。</p></li><li><p>支持 ES6+ 语法和 TypeScript 类型检查。</p></li><li><p>适合快速原型开发和调试工具脚本。</p></li></ul></blockquote><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">⚠️ 十、安全审计问题说明与处理建议</h2><p>执行 <code>npm install</code> 后运行 <code>npm audit</code> 可能出现 <strong>13 条低危漏洞</strong>，主要涉及：</p><ul><li><p><code>cookie &lt;0.7.0</code> → <code>@sentry/node</code> → <code>hardhat</code></p></li><li><p><code>tmp &lt;=0.2.3</code> → <code>solc</code></p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🔍 问题分析</h3><ol><li><p><strong>根源</strong>：这些漏洞来自 <code>hardhat</code> 及其依赖链（如 <code>@sentry/node</code>, <code>solc</code>），属于<strong>开发工具链的间接依赖</strong>。</p></li><li><p><strong>影响范围</strong>：<strong>仅限于本地开发环境</strong>，<strong>不会影响</strong>：</p><ul><li><p>智能合约代码本身</p></li><li><p>部署到链上的字节码</p></li><li><p>钱包私钥或用户资产</p></li></ul></li><li><p><strong>无法修复原因</strong>：</p><ul><li><p><code>hardhat@2.26.3</code> 依赖 <code>@sentry/node@^7.59.0</code>，而该版本依赖 <code>cookie@^0.5.0</code>。</p></li><li><p><code>solc</code> 依赖 <code>tmp</code>，但 <code>solc</code> 已通过安全审计，且 <code>tmp</code> 的漏洞在编译场景下<strong>不可利用</strong>。</p></li></ul></li></ol><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 处理建议</h3><pre data-type="codeBlock" text="# 接受警告（推荐）
npm audit --omit=dev
"><code><span class="hljs-comment"># 接受警告（推荐）</span>
npm audit <span class="hljs-attr">--omit</span>=dev
</code></pre><blockquote><p>或者，若需消除报告：</p><pre data-type="codeBlock" text="npm audit fix --force
"><code>npm audit fix <span class="hljs-operator">-</span><span class="hljs-operator">-</span>force
</code></pre><p><strong>但请注意</strong>：<code>--force</code> 可能引入不兼容版本，<strong>不推荐在生产项目中使用</strong>。</p></blockquote><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">📌 结论</h3><ul><li><p>✅ <strong>这些漏洞不影响合约安全性或功能</strong>。</p></li><li><p>✅ <strong>当前依赖组合（</strong><code>hardhat@2.26.3 + toolbox@^4.0.0</code>）是经过验证的稳定方案。</p></li><li><p>❌ <strong>不要为了“0漏洞”而升级至</strong> <code>hardhat@3.x</code>，那将引入更大的兼容性风险。</p></li></ul><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">✅ 十一、结论</h2><p>本方案已<strong>完全规避</strong> <code>hardhat@3.x</code> 的不稳定性，精准构建于 <code>v2.26.3</code>：</p><ul><li><p>✅ <strong>项目名称已更新为</strong> <code>hardhat-project</code>，所有相关引用均已同步。</p></li><li><p>✅ <strong>强制安装</strong> <code>hardhat@2.26.3</code>，避免 <code>3.0.4</code> 的兼容性问题。</p></li><li><p>✅ 明确解释 <code>Do you want to install ... dependencies? (Y/n)</code> 选项，推荐 <code>y</code>。</p></li><li><p>✅ <strong>清晰区分初始结构与最终结构</strong>，便于理解配置演变过程。</p></li><li><p>✅ 所有配置与本人提供的文件<strong>100% 一致</strong>。</p></li><li><p>✅ 项目可编译、测试、部署、格式化。</p></li><li><p>✅ 在 <code>Node.js v20.18.0 + npm 10.8.2</code> 下验证通过。</p></li><li><p>✅ <strong>完整结构</strong>：包含 <code>node_modules/</code> 目录，反映真实项目状态。</p></li><li><p>✅ <strong>团队协作友好</strong>：通过 <code>.editorconfig</code>, <code>.prettierrc</code>, <code>.eslintrc.js</code>, <code>.vscode/settings.json</code> 实现代码风格统一。</p></li><li><p>✅ <strong>新增</strong> <code>ts-node</code> 执行能力：支持直接运行 <code>.ts</code> 脚本，提升开发效率。</p></li><li><p>✅ <strong>已修复 Ignition 导入错误</strong>：<code>hardhat@2.26.3</code> 不支持 <code>hardhat-ignition</code>，已移除相关代码并使用标准 <code>ethers.deployContract</code>。</p></li><li><p>✅ <strong>已修复 Solidity 编译器版本不匹配</strong>：在 <code>hardhat.config.ts</code> 中明确设置 <code>version: &quot;0.8.28&quot;</code>。</p></li><li><p>✅ <strong>已修复 VS Code TypeScript 错误</strong>：详细说明了 <code>node_modules/@nomicfoundation/hardhat-toolbox/src/tsconfig.json</code> 报错的根本原因，并提供了<strong>推荐的非侵入式解决方案</strong>（修改 <code>.vscode/settings.json</code> 或 <code>tsconfig.json</code> 的 <code>exclude</code>），避免修改 <code>node_modules</code>。</p></li><li><p>✅ <strong>特别说明</strong>：<code>hardhat@2.26.3</code> <strong>不支持</strong> <code>hardhat-ignition</code>，该功能是 <code>hardhat@3.x</code> 的实验性功能。已提供基于 <code>ethers.deployContract()</code> 的稳定替代方案，并详细说明了原因和操作步骤。</p></li></ul><blockquote><p>✅ <strong>此为当前最稳定、最可靠的 Hardhat 开发环境搭建方案。</strong></p></blockquote><hr><p><strong>✅ 安装成功！现在可以安全地进行智能合约开发了！</strong> 🎉</p><hr><h1 id="h-hardhat" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📄 Hardhat 单文件编译指南</h1><blockquote><p>本文档详细说明如何在 Hardhat 项目中实现 <strong>通用、简单、通过命令指定文件名编译单个 Solidity 文件</strong> 的方法，并解决常见问题。</p></blockquote><hr><h2 id="h-1" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🧩 1. 背景</h2><p><code>npx hardhat compile</code> 是 Hardhat 的默认编译命令，但它：</p><ul><li><p>❌ 不支持直接编译单个 <code>.sol</code> 文件（如 <code>npx hardhat compile Contract.sol</code>）</p></li><li><p>✅ 支持<strong>增量编译</strong>：只重新编译修改过的文件</p></li></ul><p>因此，若要实现“<strong>指定文件编译</strong>”，需借助自定义脚本或配置。</p><hr><h2 id="h-2-solc" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🔧 2. <code>solc</code> 版本兼容性说明</h2><h3 id="h-packagejson" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">当前配置（<code>package.json</code>）</h3><pre data-type="codeBlock" text="&quot;devDependencies&quot;: {
  &quot;solc&quot;: &quot;^0.8.30&quot;
}
"><code><span class="hljs-attr">"devDependencies"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"solc"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^0.8.30"</span>
<span class="hljs-punctuation">}</span>
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">是否兼容？</h3><ul><li><p>✅ <strong>技术上可用</strong></p></li><li><p>❌ <strong>不推荐使用</strong> <code>^0.8.30</code></p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">原因</h3><ul><li><p><code>npx hardhat compile</code> 使用的是 Hardhat 内部管理的 <code>solc</code>，版本由 <code>hardhat.config.js</code> 决定</p></li><li><p><code>package.json</code> 中的 <code>solc</code> 仅用于<strong>自定义脚本</strong>（如 <code>require(&apos;solc&apos;)</code>）</p></li><li><p>若脚本与 Hardhat 使用的版本不一致，可能导致：</p><ul><li><p>ABI 不一致</p></li><li><p>部署验证失败</p></li><li><p>字节码差异</p></li></ul></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 推荐做法</h3><p>确保 <code>solc</code> 版本与 <code>hardhat.config.js</code> 一致：</p><pre data-type="codeBlock" text="// hardhat.config.js
module.exports = {
  solidity: &quot;0.8.8&quot;, // ← Hardhat 实际使用的版本
};
"><code><span class="hljs-comment">// hardhat.config.js</span>
module.exports <span class="hljs-operator">=</span> {
  solidity: <span class="hljs-string">"0.8.8"</span>, <span class="hljs-comment">// ← Hardhat 实际使用的版本</span>
};
</code></pre><pre data-type="codeBlock" text="# 安装精确匹配的 solc
npm install solc@0.8.8 --save-dev
"><code># 安装精确匹配的 solc
npm install solc@<span class="hljs-number">0</span><span class="hljs-number">.8</span><span class="hljs-number">.8</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev
</code></pre><pre data-type="codeBlock" text="&quot;devDependencies&quot;: {
  &quot;solc&quot;: &quot;0.8.8&quot;
}
"><code><span class="hljs-attr">"devDependencies"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"solc"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"0.8.8"</span>
<span class="hljs-punctuation">}</span>
</code></pre><blockquote><p>✅ 避免版本混乱，确保一致性。</p></blockquote><hr><h2 id="h-3-invalid-evm-version-requested" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">⚠️ 3. 常见错误：<code>Invalid EVM version requested</code></h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">错误信息</h3><pre data-type="codeBlock" text="❌ Compilation failed:
Invalid EVM version requested.
"><code><span class="hljs-string">❌</span> <span class="hljs-attr">Compilation failed:</span>
<span class="hljs-string">Invalid</span> <span class="hljs-string">EVM</span> <span class="hljs-string">version</span> <span class="hljs-string">requested.</span>
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">原因</h3><p>在 <code>solc</code> 编译配置中设置了不支持的 <code>evmVersion</code>：</p><pre data-type="codeBlock" text="evmVersion: &apos;paris&apos;
"><code><span class="hljs-symbol">evmVersion:</span> <span class="hljs-comment">'paris'</span>
</code></pre><ul><li><p><code>paris</code> 是 <strong>最新升级后的 EVM 版本</strong></p></li><li><p><code>solc &lt;= 0.8.19</code> <strong>不支持</strong> <code>paris</code></p></li><li><p>最高支持版本为 <code>london</code></p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 解决方案</h3><h4 id="h-1-evmversion" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">方法 1：删除 <code>evmVersion</code>（推荐）</h4><p>让 <code>solc</code> 使用默认 EVM 版本，自动兼容：</p><pre data-type="codeBlock" text="settings: {
  optimizer: {
    enabled: true,
    runs: 200
  }
  // 不指定 evmVersion
}
"><code><span class="hljs-attr">settings:</span> {
  <span class="hljs-attr">optimizer:</span> {
    <span class="hljs-attr">enabled:</span> <span class="hljs-literal">true</span>,
    <span class="hljs-attr">runs:</span> <span class="hljs-number">200</span>
  }
  <span class="hljs-string">//</span> <span class="hljs-string">不指定</span> <span class="hljs-string">evmVersion</span>
}
</code></pre><h4 id="h-2" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">方法 2：改为兼容版本</h4><pre data-type="codeBlock" text="evmVersion: &apos;london&apos;
"><code><span class="hljs-symbol">evmVersion:</span> <span class="hljs-comment">'london'</span>
</code></pre><h4 id="h-3-solc-paris" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">方法 3：升级 <code>solc</code>（如需 <code>paris</code>）</h4><pre data-type="codeBlock" text="npm install solc@0.8.20 --save-dev
"><code>npm install solc@<span class="hljs-number">0</span><span class="hljs-number">.8</span><span class="hljs-number">.20</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev
</code></pre><p>然后可安全使用：</p><pre data-type="codeBlock" text="evmVersion: &apos;paris&apos;
"><code><span class="hljs-symbol">evmVersion:</span> <span class="hljs-comment">'paris'</span>
</code></pre><hr><h2 id="h-4" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">✅ 4. 通用单文件编译脚本（推荐）</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">目标</h3><ul><li><p>一行命令编译任意 <code>.sol</code> 文件</p></li><li><p>支持参数传入</p></li><li><p>输出 ABI 和 BIN</p></li><li><p>兼容现有 Hardhat 项目</p></li></ul><hr><h3 id="h-1-solc" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">步骤 1：安装 <code>solc</code></h3><pre data-type="codeBlock" text="npm install solc@0.8.8 --save-dev
"><code>npm install solc@<span class="hljs-number">0</span><span class="hljs-number">.8</span><span class="hljs-number">.8</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev
</code></pre><blockquote><p>✅ 版本需与 <code>hardhat.config.js</code> 一致</p></blockquote><hr><h3 id="h-2-scriptscompile-soljs" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">步骤 2：创建脚本 <code>scripts/compile-sol.js</code></h3><pre data-type="codeBlock" text="// scripts/compile-sol.js
const fs = require(&apos;fs&apos;);
const path = require(&apos;path&apos;);
const solc = require(&apos;solc&apos;);

const DEFAULT_SOLC_VERSION = &apos;0.8.8&apos;;
const OUTPUT_DIR = path.join(__dirname, &apos;..&apos;, &apos;artifacts&apos;, &apos;compiled&apos;);

if (!fs.existsSync(OUTPUT_DIR)) {
  fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}

function help() {
  console.log(`
Usage: node scripts/compile-sol.js &lt;SolidityFile.sol&gt; [options]

Options:
  --version, -v &lt;version&gt;   Specify Solidity version (default: ${DEFAULT_SOLC_VERSION})
  --optimize, -o            Enable optimizer (default: true)
  --runs &lt;n&gt;                Set optimizer runs (default: 200)
  --help, -h                Show this help

Example:
  node scripts/compile-sol.js contracts/SimpleStorage.sol
  node scripts/compile-sol.js contracts/Token.sol --version 0.8.20
  `);
  process.exit(0);
}

const args = process.argv.slice(2);
if (args.length === 0 || args.includes(&apos;--help&apos;) || args.includes(&apos;-h&apos;)) {
  help();
}

const filePath = args[0];
let optimize = true;
let runs = 200;

for (let i = 1; i &lt; args.length; i++) {
  if (args[i] === &apos;--optimize&apos; || args[i] === &apos;-o&apos;) {
    optimize = true;
  } else if (args[i] === &apos;--runs&apos;) {
    runs = parseInt(args[++i]);
  }
}

if (!fs.existsSync(filePath)) {
  console.error(`❌ File not found: ${filePath}`);
  process.exit(1);
}

const source = fs.readFileSync(filePath, &apos;utf8&apos;);
const fileName = path.basename(filePath);
const contractName = fileName.replace(&apos;.sol&apos;, &apos;&apos;);

console.log(`🔨 Compiling ${fileName} with solc ${solc.version()}...`);

const input = {
  language: &apos;Solidity&apos;,
  sources: {
    [fileName]: {
      content: source,
    },
  },
  settings: {
    outputSelection: {
      &apos;*&apos;: {
        &apos;*&apos;: [&apos;abi&apos;, &apos;evm.bytecode.object&apos;],
      },
    },
    optimizer: {
      enabled: optimize,
      runs: runs,
    }
    // ✅ 不设置 evmVersion，避免兼容问题
  },
};

const output = JSON.parse(solc.compile(JSON.stringify(input)));

if (output.errors) {
  const errors = output.errors.filter(e =&gt; e.severity === &apos;error&apos;);
  if (errors.length &gt; 0) {
    console.error(&apos;❌ Compilation failed:&apos;);
    errors.forEach(err =&gt; console.error(err.formattedMessage));
    process.exit(1);
  }
}

const contracts = output.contracts[fileName];
const firstContract = Object.keys(contracts)[0];
const contract = contracts[firstContract];

const abiPath = path.join(OUTPUT_DIR, `${contractName}.abi.json`);
const binPath = path.join(OUTPUT_DIR, `${contractName}.bin`);

fs.writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2));
fs.writeFileSync(binPath, contract.evm.bytecode.object);

console.log(`✅ Compiled: ${fileName}`);
console.log(`   ABI:  ${abiPath}`);
console.log(`   BIN:  ${binPath}`);
"><code><span class="hljs-comment">// scripts/compile-sol.js</span>
const fs <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
const path <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);
const solc <span class="hljs-operator">=</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'solc'</span>);

const DEFAULT_SOLC_VERSION <span class="hljs-operator">=</span> <span class="hljs-string">'0.8.8'</span>;
const OUTPUT_DIR <span class="hljs-operator">=</span> path.join(__dirname, <span class="hljs-string">'..'</span>, <span class="hljs-string">'artifacts'</span>, <span class="hljs-string">'compiled'</span>);

<span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>fs.existsSync(OUTPUT_DIR)) {
  fs.mkdirSync(OUTPUT_DIR, { recursive: <span class="hljs-literal">true</span> });
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">help</span>(<span class="hljs-params"></span>) </span>{
  console.log(`
Usage: node scripts<span class="hljs-operator">/</span>compile<span class="hljs-operator">-</span>sol.js <span class="hljs-operator">&#x3C;</span>SolidityFile.sol> [options]

Options:
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>version, <span class="hljs-operator">-</span>v <span class="hljs-operator">&#x3C;</span>version<span class="hljs-operator">></span>   Specify Solidity version (default: ${DEFAULT_SOLC_VERSION})
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>optimize, <span class="hljs-operator">-</span>o            Enable optimizer (default: <span class="hljs-literal">true</span>)
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>runs <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>                Set optimizer runs (default: <span class="hljs-number">200</span>)
  <span class="hljs-operator">-</span><span class="hljs-operator">-</span>help, <span class="hljs-operator">-</span>h                Show <span class="hljs-built_in">this</span> help

Example:
  node scripts<span class="hljs-operator">/</span>compile<span class="hljs-operator">-</span>sol.js contracts<span class="hljs-operator">/</span>SimpleStorage.sol
  node scripts<span class="hljs-operator">/</span>compile<span class="hljs-operator">-</span>sol.js contracts<span class="hljs-operator">/</span>Token.sol <span class="hljs-operator">-</span><span class="hljs-operator">-</span>version <span class="hljs-number">0</span><span class="hljs-number">.8</span><span class="hljs-number">.20</span>
  `);
  process.exit(<span class="hljs-number">0</span>);
}

const args <span class="hljs-operator">=</span> process.argv.slice(<span class="hljs-number">2</span>);
<span class="hljs-keyword">if</span> (args.<span class="hljs-built_in">length</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span> <span class="hljs-operator">|</span><span class="hljs-operator">|</span> args.includes(<span class="hljs-string">'--help'</span>) <span class="hljs-operator">|</span><span class="hljs-operator">|</span> args.includes(<span class="hljs-string">'-h'</span>)) {
  help();
}

const filePath <span class="hljs-operator">=</span> args[<span class="hljs-number">0</span>];
let optimize <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
let runs <span class="hljs-operator">=</span> <span class="hljs-number">200</span>;

<span class="hljs-keyword">for</span> (let i <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; i <span class="hljs-operator">&#x3C;</span> args.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
  <span class="hljs-keyword">if</span> (args[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'--optimize'</span> <span class="hljs-operator">|</span><span class="hljs-operator">|</span> args[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'-o'</span>) {
    optimize <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (args[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'--runs'</span>) {
    runs <span class="hljs-operator">=</span> parseInt(args[<span class="hljs-operator">+</span><span class="hljs-operator">+</span>i]);
  }
}

<span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>fs.existsSync(filePath)) {
  console.error(`❌ File not found: ${filePath}`);
  process.exit(<span class="hljs-number">1</span>);
}

const source <span class="hljs-operator">=</span> fs.readFileSync(filePath, <span class="hljs-string">'utf8'</span>);
const fileName <span class="hljs-operator">=</span> path.basename(filePath);
const contractName <span class="hljs-operator">=</span> fileName.replace(<span class="hljs-string">'.sol'</span>, <span class="hljs-string">''</span>);

console.log(`🔨 Compiling ${fileName} with solc ${solc.version()}...`);

const input <span class="hljs-operator">=</span> {
  language: <span class="hljs-string">'Solidity'</span>,
  sources: {
    [fileName]: {
      content: source,
    },
  },
  settings: {
    outputSelection: {
      <span class="hljs-string">'*'</span>: {
        <span class="hljs-string">'*'</span>: [<span class="hljs-string">'abi'</span>, <span class="hljs-string">'evm.bytecode.object'</span>],
      },
    },
    optimizer: {
      enabled: optimize,
      runs: runs,
    }
    <span class="hljs-comment">// ✅ 不设置 evmVersion，避免兼容问题</span>
  },
};

const output <span class="hljs-operator">=</span> JSON.parse(solc.compile(JSON.stringify(input)));

<span class="hljs-keyword">if</span> (output.errors) {
  const errors <span class="hljs-operator">=</span> output.errors.filter(e <span class="hljs-operator">=</span><span class="hljs-operator">></span> e.severity <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'error'</span>);
  <span class="hljs-keyword">if</span> (errors.<span class="hljs-built_in">length</span> <span class="hljs-operator">></span> <span class="hljs-number">0</span>) {
    console.error(<span class="hljs-string">'❌ Compilation failed:'</span>);
    errors.forEach(err <span class="hljs-operator">=</span><span class="hljs-operator">></span> console.error(err.formattedMessage));
    process.exit(<span class="hljs-number">1</span>);
  }
}

const contracts <span class="hljs-operator">=</span> output.contracts[fileName];
const firstContract <span class="hljs-operator">=</span> Object.keys(contracts)[<span class="hljs-number">0</span>];
const <span class="hljs-class"><span class="hljs-keyword">contract</span> = <span class="hljs-title">contracts</span>[<span class="hljs-title">firstContract</span>];

<span class="hljs-title">const</span> <span class="hljs-title">abiPath</span> = <span class="hljs-title">path</span>.<span class="hljs-title">join</span>(<span class="hljs-params">OUTPUT_DIR, `${contractName}.<span class="hljs-built_in">abi</span>.json`</span>);
<span class="hljs-title">const</span> <span class="hljs-title">binPath</span> = <span class="hljs-title">path</span>.<span class="hljs-title">join</span>(<span class="hljs-params">OUTPUT_DIR, `${contractName}.bin`</span>);

<span class="hljs-title">fs</span>.<span class="hljs-title">writeFileSync</span>(<span class="hljs-params">abiPath, JSON.stringify(<span class="hljs-params"><span class="hljs-keyword">contract</span>.<span class="hljs-built_in">abi</span>, null, <span class="hljs-number">2</span></span>)</span>);
<span class="hljs-title">fs</span>.<span class="hljs-title">writeFileSync</span>(<span class="hljs-params">binPath, <span class="hljs-keyword">contract</span>.evm.bytecode.object</span>);

<span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">`✅ Compiled: ${fileName}`</span>);
<span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">`   ABI:  ${abiPath}`</span>);
<span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params">`   BIN:  ${binPath}`</span>);
</span></code></pre><hr><h3 id="h-3-npm-script" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">步骤 3：添加 npm script</h3><pre data-type="codeBlock" text="&quot;scripts&quot;: {
  &quot;compile:sol&quot;: &quot;node scripts/compile-sol.js&quot;
}
"><code><span class="hljs-attr">"scripts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"compile:sol"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"node scripts/compile-sol.js"</span>
<span class="hljs-punctuation">}</span>
</code></pre><hr><h3 id="h-4" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">步骤 4：使用方式</h3><pre data-type="codeBlock" text="# 编译 SimpleStorage.sol
npm run compile:sol contracts/SimpleStorage.sol

# 指定优化次数
npm run compile:sol contracts/Token.sol -- --runs 1000

# 查看帮助
node scripts/compile-sol.js --help
"><code># 编译 SimpleStorage.sol
npm run compile:sol contracts<span class="hljs-operator">/</span>SimpleStorage.sol

# 指定优化次数
npm run compile:sol contracts<span class="hljs-operator">/</span>Token.sol <span class="hljs-operator">-</span><span class="hljs-operator">-</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span>runs <span class="hljs-number">1000</span>

# 查看帮助
node scripts<span class="hljs-operator">/</span>compile<span class="hljs-operator">-</span>sol.js <span class="hljs-operator">-</span><span class="hljs-operator">-</span>help
</code></pre><hr><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">输出示例</h3><pre data-type="codeBlock" text="🔨 Compiling SimpleStorage.sol with solc 0.8.8...
✅ Compiled: SimpleStorage.sol
   ABI:  artifacts/compiled/SimpleStorage.abi.json
   BIN:  artifacts/compiled/SimpleStorage.bin
"><code>🔨 Compiling SimpleStorage.sol with solc <span class="hljs-number">0</span><span class="hljs-number">.8</span><span class="hljs-number">.8</span>...
✅ Compiled: SimpleStorage.sol
   ABI:  artifacts<span class="hljs-operator">/</span>compiled<span class="hljs-operator">/</span>SimpleStorage.abi.json
   BIN:  artifacts<span class="hljs-operator">/</span>compiled<span class="hljs-operator">/</span>SimpleStorage.bin
</code></pre><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📂 输出目录结构</h2><pre data-type="codeBlock" text="artifacts/
└── compiled/
    ├── SimpleStorage.abi.json
    └── SimpleStorage.bin
"><code>artifacts<span class="hljs-operator">/</span>
└── compiled<span class="hljs-operator">/</span>
    ├── SimpleStorage.abi.json
    └── SimpleStorage.bin
</code></pre><hr><h2 id="h-5-npx-hardhat-compile" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🔄 5. <code>npx hardhat compile</code> 行为说明</h2><p>运行：</p><pre data-type="codeBlock" text="npx hardhat compile
"><code>npx hardhat <span class="hljs-built_in">compile</span>
</code></pre><p>输出：</p><pre data-type="codeBlock" text="Nothing to compile
No need to generate any newer typings.
"><code><span class="hljs-literal">Nothing</span> <span class="hljs-keyword">to</span> compile
No need <span class="hljs-keyword">to</span> generate any newer typings.
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 是否正常？</h3><p><strong>是！这是正常行为。</strong></p><ul><li><p>表示合约未修改，Hardhat 使用缓存</p></li><li><p>TypeChain 也无需重新生成类型</p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">强制重新编译</h3><pre data-type="codeBlock" text="# 方法 1：强制编译
npx hardhat compile --force

# 方法 2：清理后编译
npx hardhat clean
npx hardhat compile
"><code><span class="hljs-comment"># 方法 1：强制编译</span>
npx hardhat <span class="hljs-built_in">compile</span> --force

<span class="hljs-comment"># 方法 2：清理后编译</span>
npx hardhat clean
npx hardhat <span class="hljs-built_in">compile</span>
</code></pre><hr><h2 id="h-6" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">✅ 6. 总结与最佳实践</h2><p>| 项目 | 推荐做法 |</p><p>|------|---------|</p><p>| <code>solc</code> 版本 | 与 <code>hardhat.config.js</code> 一致，精确版本 |</p><p>| 单文件编译 | 使用 <code>compile-sol.js</code> 脚本 |</p><p>| EVM 版本 | 不设置 <code>evmVersion</code>，让编译器自动选择 |</p><p>| 增量编译 | 日常开发使用 <code>npx hardhat compile</code> |</p><p>| 类型生成 | 由 Hardhat Toolbox 自动管理 |</p><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🚀 下一步建议</h2><pre data-type="codeBlock" text="# 编译单个文件
npm run compile:sol contracts/SimpleStorage.sol

# 清理并全量编译
npx hardhat clean &amp;&amp; npx hardhat compile

# 验证编译产物
ls artifacts/contracts/
"><code># 编译单个文件
npm run compile:sol contracts<span class="hljs-operator">/</span>SimpleStorage.sol

# 清理并全量编译
npx hardhat clean <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> npx hardhat compile

# 验证编译产物
ls artifacts<span class="hljs-operator">/</span>contracts<span class="hljs-operator">/</span>
</code></pre><hr><blockquote><p>📝 <strong>文档更新时间：2025年10月3日</strong>适用于 Hardhat 2.x + TypeScript 项目</p></blockquote><hr><p>✅ <strong>现在你已拥有一套完整、可靠、可复用的单文件编译方案！</strong></p><hr><h1 id="h-hardhat-eslint-and-prettier" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📚 Hardhat 项目中 ESLint &amp; Prettier 集成问题全记录</h1><h2 id="h-npm-run-lint-2025" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">—— 从 <code>npm run lint</code> 报错到最终稳定方案的完整复盘（2025 精确版）</h2><blockquote><p><strong>作者</strong>：Rain<strong>时间</strong>：2025年10月3日<strong>目标</strong>：完整还原在 <strong>Hardhat + TypeScript</strong> 项目中，从 <code>npm run lint</code> 报错出发，经历 Solhint 替代 → 验证失败 → 回归 ESLint → 版本冲突排查 → 最终稳定配置的全过程。<strong>特别强调</strong>：<code>hardhat@2.26.3</code> 与 <code>ESLint v9</code> 不兼容，必须使用 <code>ESLint v8</code>。</p></blockquote><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🧭 完整问题演进脉络图</h2><pre data-type="codeBlock" text="1. 起点：npm run lint 执行报错（ESLint 无法处理 .sol）
   ↓
2. 尝试方案 A：引入 solhint 替代检查
   ↓
3. 验证失败：solhint 安装失败、配置不生效、插件废弃
   ↓
4. 回归本质：尝试让 ESLint 支持 .sol 文件
   ↓
5. 错误方向：尝试升级到 ESLint v9 + Flat Config
   ↓
6. 发现根本冲突：hardhat 依赖 eslint@^8.0.0，不兼容 v9
   ↓
7. 正确方向：锁定 ESLint v8 + eslint-plugin-solidity（旧版兼容）
   ↓
8. 最终验证：npm run lint 成功，.sol 文件被检查
   ↓
✅ 解决方案：ESLint v8 + eslint-plugin-prettier + prettier-plugin-solidity
"><code><span class="hljs-number">1.</span> 起点：npm run lint 执行报错（ESLint 无法处理 .sol）
   ↓
<span class="hljs-number">2.</span> 尝试方案 A：引入 solhint 替代检查
   ↓
<span class="hljs-number">3.</span> 验证失败：solhint 安装失败、配置不生效、插件废弃
   ↓
<span class="hljs-number">4.</span> 回归本质：尝试让 ESLint 支持 .sol 文件
   ↓
<span class="hljs-number">5.</span> 错误方向：尝试升级到 ESLint v9 <span class="hljs-operator">+</span> Flat Config
   ↓
<span class="hljs-number">6.</span> 发现根本冲突：hardhat 依赖 eslint@<span class="hljs-operator">^</span><span class="hljs-number">8.0</span><span class="hljs-number">.0</span>，不兼容 v9
   ↓
<span class="hljs-number">7.</span> 正确方向：锁定 ESLint v8 <span class="hljs-operator">+</span> eslint<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>solidity（旧版兼容）
   ↓
<span class="hljs-number">8.</span> 最终验证：npm run lint 成功，.sol 文件被检查
   ↓
✅ 解决方案：ESLint v8 <span class="hljs-operator">+</span> eslint<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>prettier <span class="hljs-operator">+</span> prettier<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>solidity
</code></pre><hr><h2 id="h-1-npm-run-lint" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1️⃣ 起点：<code>npm run lint</code> 执行报错</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">❌ 问题现象</h3><p>执行：</p><pre data-type="codeBlock" text="npm run lint
"><code>npm run lint
</code></pre><p>报错：</p><pre data-type="codeBlock" text="Error: Failed to load plugin &quot;solidity&quot; declared in &quot;.eslintrc.js&quot;: Cannot find module &apos;eslint-plugin-solidity&apos;
"><code>Error: Failed to <span class="hljs-built_in">load</span> plugin <span class="hljs-string">"solidity"</span> declared <span class="hljs-keyword">in</span> <span class="hljs-string">".eslintrc.js"</span>: Cannot <span class="hljs-built_in">find</span> <span class="hljs-built_in">module</span> <span class="hljs-string">'eslint-plugin-solidity'</span>
</code></pre><p>或：</p><pre data-type="codeBlock" text="Error: Parsing error: The keyword &apos;pragma&apos; is reserved
"><code><span class="hljs-built_in">Error</span>: Parsing <span class="hljs-function"><span class="hljs-keyword">error</span>: <span class="hljs-title">The</span> <span class="hljs-title">keyword</span> '<span class="hljs-title"><span class="hljs-keyword">pragma</span></span>' <span class="hljs-title"><span class="hljs-keyword">is</span></span> <span class="hljs-title">reserved</span>
</span></code></pre><hr><h2 id="h-2-a-solhint" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2️⃣ 尝试方案 A：引入 <code>solhint</code> 作为替代方案</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🤔 初始建议（错误方向）</h3><blockquote><p>“你可以尝试使用 <code>solhint</code> 来检查 Solidity 文件。”</p></blockquote><p>建议操作：</p><pre data-type="codeBlock" text="npm install --save-dev solhint
echo &apos;{ &quot;extends&quot;: &quot;solhint:recommended&quot; }&apos; &gt; .solhint.json
npx solhint &quot;contracts/**/*.sol&quot;
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev solhint
echo <span class="hljs-string">'{ "extends": "solhint:recommended" }'</span> <span class="hljs-operator">></span> .solhint.json
npx solhint <span class="hljs-string">"contracts/**/*.sol"</span>
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 短期效果</h3><ul><li><p><code>solhint</code> 能独立运行</p></li><li><p>检测出部分 Solidity 问题</p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">⚠️ 但未解决根本问题</h3><ul><li><p><code>npm run lint</code> 仍然失败（因为 ESLint 仍无法处理 <code>.sol</code>）</p></li><li><p>需要额外运行 <code>npx solhint</code>，流程割裂</p></li></ul><hr><h2 id="h-3-solhint" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3️⃣ 验证失败：<code>solhint</code> 本身问题重重</h2><h3 id="h-1solhint" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">❌ 问题 1：<code>solhint</code> 安装后命令无法执行</h3><pre data-type="codeBlock" text="npm install --save-dev solhint@latest
npx solhint
# 错误：command not found
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev solhint@latest
npx solhint
# 错误：command not found
</code></pre><p><strong>原因</strong>：<code>solhint@1.x</code> 为实验版本，发布不完整。</p><p><strong>修复</strong>：</p><pre data-type="codeBlock" text="npm install --save-dev solhint@0.0.13
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev solhint@<span class="hljs-number">0</span><span class="hljs-number">.0</span><span class="hljs-number">.13</span>
</code></pre><p>✅ 成功运行，但版本为 <strong>2021 年发布</strong>，严重过时。</p><hr><h3 id="h-2solhintjson" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">❌ 问题 2：<code>.solhint.json</code> 配置不生效</h3><p>配置：</p><pre data-type="codeBlock" text="{
  &quot;rules&quot;: {
    &quot;func-visibility&quot;: &quot;error&quot;
  }
}
"><code>{
  "rules": {
    "func-<span class="hljs-attribute">visibility</span>": <span class="hljs-string">"error"</span>
  }
}
</code></pre><p><strong>结果</strong>：无报错，规则未触发。</p><p><strong>排查</strong>：<code>solhint --print-config</code> 显示配置未加载。</p><hr><h3 id="h-3-prettier" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">❌ 问题 3：与 Prettier 集成失败</h3><pre data-type="codeBlock" text="npm install --save-dev solhint-plugin-prettier
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev solhint<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>prettier
</code></pre><p><code>.solhint.json</code>：</p><pre data-type="codeBlock" text="&quot;plugins&quot;: [&quot;prettier&quot;],
&quot;rules&quot;: { &quot;prettier/prettier&quot;: &quot;error&quot; }
"><code><span class="hljs-attr">"plugins"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"prettier"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"rules"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"prettier/prettier"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"error"</span> <span class="hljs-punctuation">}</span>
</code></pre><p><strong>结果</strong>：无格式化提示，插件未生效。</p><p><strong>结论</strong>：<code>solhint-plugin-prettier</code> 最后更新于 2020 年，<strong>已废弃</strong>。</p><hr><h3 id="h-4vs-code" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">❌ 问题 4：VS Code 插件不兼容</h3><ul><li><p>安装 “Solhint” VS Code 插件</p></li><li><p>无波浪线提示</p></li><li><p>插件市场评论：“已停止维护”</p></li></ul><hr><h2 id="h-4-eslint-sol" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">4️⃣ 回归本质：尝试让 ESLint 支持 <code>.sol</code> 文件</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🤔 新思路</h3><blockquote><p>“能否让 ESLint 直接解析 <code>.sol</code> 文件？”</p></blockquote><h3 id="h-eslint-plugin-solidity" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🔍 发现 <code>eslint-plugin-solidity</code></h3><ul><li><p>npm 包：<code>eslint-plugin-solidity</code></p></li><li><p>作用：让 ESLint 支持 Solidity 语法</p></li><li><p><strong>关键点</strong>：该包最后更新为 2020 年，且不支持 ESLint v9</p></li></ul><hr><h2 id="h-5-eslint-v9-flat-config" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">5️⃣ 错误方向：尝试升级到 ESLint v9 + Flat Config</h2><h3 id="h-eslint" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">❌ 尝试升级 ESLint</h3><pre data-type="codeBlock" text="npm install --save-dev eslint@^9.0.0
"><code>npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save<span class="hljs-operator">-</span>dev eslint@<span class="hljs-operator">^</span><span class="hljs-number">9.0</span><span class="hljs-number">.0</span>
</code></pre><h3 id="h-npm-run-lint" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">❌ 执行 <code>npm run lint</code> 报错</h3><pre data-type="codeBlock" text="Error: The plugin &quot;@nomicfoundation/hardhat-toolbox&quot; requires an ESLint version ^8.0.0
"><code><span class="hljs-built_in">Error</span>: The plugin <span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span> requires an ESLint version <span class="hljs-operator">^</span><span class="hljs-number">8.0</span><span class="hljs-number">.0</span>
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🔍 深入排查</h3><p>查看 <code>@nomicfoundation/hardhat-toolbox</code> 的 <code>package.json</code>：</p><pre data-type="codeBlock" text="&quot;devDependencies&quot;: {
  &quot;eslint&quot;: &quot;^8.0.0&quot;
}
"><code><span class="hljs-attr">"devDependencies"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"eslint"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^8.0.0"</span>
<span class="hljs-punctuation">}</span>
</code></pre><blockquote><p>✅ <strong>确认</strong>：<code>hardhat-toolbox</code> <strong>仅兼容 ESLint v8</strong>，<strong>不支持 v9</strong>。</p></blockquote><hr><h2 id="h-6-eslint-v8" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">6️⃣ 正确方向：锁定 ESLint v8 + 兼容方案</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 决策</h3><blockquote><p><strong>放弃 ESLint v9，回归 v8</strong>，并寻找 <code>eslint-plugin-solidity</code> 的替代方案。</p></blockquote><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🔍 新发现</h3><ul><li><p><code>prettier-plugin-solidity</code> 已支持 <strong>格式化 + 基础 linting</strong></p></li><li><p><code>eslint-plugin-prettier</code> 可将 Prettier 的格式化结果暴露为 ESLint 错误</p></li><li><p>可通过 <code>eslint-plugin-prettier</code> 间接实现 <code>.sol</code> 文件的“检查”</p></li></ul><hr><h2 id="h-7-eslint-v8-prettier" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">7️⃣ 最终解决方案：ESLint v8 + Prettier 统一格式化</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 保留现有配置（已正确）</h3><pre data-type="codeBlock" text="&quot;scripts&quot;: {
  &quot;lint&quot;: &quot;npm run lint:js &amp;&amp; npm run format:check&quot;,
  &quot;lint:fix&quot;: &quot;npm run lint:js:fix &amp;&amp; npm run format&quot;,
  &quot;lint:js&quot;: &quot;eslint \&quot;**/*.{ts,js}\&quot; --ext .ts,.js&quot;,
  &quot;lint:js:fix&quot;: &quot;eslint \&quot;**/*.{ts,js}\&quot; --ext .ts,.js --fix&quot;,
  &quot;format&quot;: &quot;prettier --plugin prettier-plugin-solidity --write \&quot;**/*.{js,cjs,ts,sol}\&quot;&quot;,
  &quot;format:check&quot;: &quot;prettier --plugin prettier-plugin-solidity --check \&quot;**/*.{js,cjs,ts,sol}\&quot;&quot;
}
"><code><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-string">"lint"</span>: <span class="hljs-string">"npm run lint:js &#x26;&#x26; npm run format:check"</span>,
  <span class="hljs-string">"lint:fix"</span>: <span class="hljs-string">"npm run lint:js:fix &#x26;&#x26; npm run format"</span>,
  <span class="hljs-string">"lint:js"</span>: <span class="hljs-string">"eslint <span class="hljs-subst">\"</span>**/*.{ts,js}<span class="hljs-subst">\"</span> --ext .ts,.js"</span>,
  <span class="hljs-string">"lint:js:fix"</span>: <span class="hljs-string">"eslint <span class="hljs-subst">\"</span>**/*.{ts,js}<span class="hljs-subst">\"</span> --ext .ts,.js --fix"</span>,
  <span class="hljs-string">"format"</span>: <span class="hljs-string">"prettier --plugin prettier-plugin-solidity --write <span class="hljs-subst">\"</span>**/*.{js,cjs,ts,sol}<span class="hljs-subst">\"</span>"</span>,
  <span class="hljs-string">"format:check"</span>: <span class="hljs-string">"prettier --plugin prettier-plugin-solidity --check <span class="hljs-subst">\"</span>**/*.{js,cjs,ts,sol}<span class="hljs-subst">\"</span>"</span>
}
</code></pre><h3 id="h-devdependencies" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ <code>devDependencies</code>（关键版本）</h3><pre data-type="codeBlock" text="&quot;devDependencies&quot;: {
  &quot;eslint&quot;: &quot;^8.57.0&quot;,
  &quot;prettier&quot;: &quot;^3.2.5&quot;,
  &quot;prettier-plugin-solidity&quot;: &quot;^1.1.3&quot;,
  &quot;eslint-plugin-prettier&quot;: &quot;^5.1.3&quot;,
  &quot;@typescript-eslint/eslint-plugin&quot;: &quot;^7.18.0&quot;,
  &quot;@typescript-eslint/parser&quot;: &quot;^7.18.0&quot;
}
"><code><span class="hljs-string">"devDependencies"</span>: {
  <span class="hljs-string">"eslint"</span>: <span class="hljs-string">"^8.57.0"</span>,
  <span class="hljs-string">"prettier"</span>: <span class="hljs-string">"^3.2.5"</span>,
  <span class="hljs-string">"prettier-plugin-solidity"</span>: <span class="hljs-string">"^1.1.3"</span>,
  <span class="hljs-string">"eslint-plugin-prettier"</span>: <span class="hljs-string">"^5.1.3"</span>,
  <span class="hljs-string">"@typescript-eslint/eslint-plugin"</span>: <span class="hljs-string">"^7.18.0"</span>,
  <span class="hljs-string">"@typescript-eslint/parser"</span>: <span class="hljs-string">"^7.18.0"</span>
}
</code></pre><h3 id="h-eslintrcjs" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ <code>.eslintrc.js</code>（推荐配置）</h3><pre data-type="codeBlock" text="// .eslintrc.js
module.exports = {
  root: true,
  env: {
    node: true,
    mocha: true,
  },
  extends: [
    &quot;eslint:recommended&quot;,
    &quot;plugin:@typescript-eslint/recommended&quot;,
    &quot;plugin:prettier/recommended&quot;, // 启用 eslint-plugin-prettier
  ],
  parser: &quot;@typescript-eslint/parser&quot;,
  parserOptions: {
    ecmaVersion: 2022,
    sourceType: &quot;module&quot;,
    project: &quot;./tsconfig.json&quot;,
  },
  plugins: [&quot;@typescript-eslint&quot;, &quot;prettier&quot;],
  rules: {
    &quot;prettier/prettier&quot;: &quot;error&quot;, // Prettier 错误作为 ESLint 错误
    &quot;@typescript-eslint/no-unused-vars&quot;: &quot;error&quot;,
  },
  ignorePatterns: [&quot;artifacts/&quot;, &quot;cache/&quot;, &quot;coverage/&quot;, &quot;node_modules/&quot;],
};
"><code><span class="hljs-comment">// .eslintrc.js</span>
module.exports <span class="hljs-operator">=</span> {
  root: <span class="hljs-literal">true</span>,
  env: {
    node: <span class="hljs-literal">true</span>,
    mocha: <span class="hljs-literal">true</span>,
  },
  extends: [
    <span class="hljs-string">"eslint:recommended"</span>,
    <span class="hljs-string">"plugin:@typescript-eslint/recommended"</span>,
    <span class="hljs-string">"plugin:prettier/recommended"</span>, <span class="hljs-comment">// 启用 eslint-plugin-prettier</span>
  ],
  parser: <span class="hljs-string">"@typescript-eslint/parser"</span>,
  parserOptions: {
    ecmaVersion: <span class="hljs-number">2022</span>,
    sourceType: <span class="hljs-string">"module"</span>,
    project: <span class="hljs-string">"./tsconfig.json"</span>,
  },
  plugins: [<span class="hljs-string">"@typescript-eslint"</span>, <span class="hljs-string">"prettier"</span>],
  rules: {
    <span class="hljs-string">"prettier/prettier"</span>: <span class="hljs-string">"error"</span>, <span class="hljs-comment">// Prettier 错误作为 ESLint 错误</span>
    <span class="hljs-string">"@typescript-eslint/no-unused-vars"</span>: <span class="hljs-string">"error"</span>,
  },
  ignorePatterns: [<span class="hljs-string">"artifacts/"</span>, <span class="hljs-string">"cache/"</span>, <span class="hljs-string">"coverage/"</span>, <span class="hljs-string">"node_modules/"</span>],
};
</code></pre><h3 id="h-vs-code-settingsjson" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ VS Code <code>settings.json</code></h3><pre data-type="codeBlock" text="{
  &quot;editor.formatOnSave&quot;: true,
  &quot;editor.codeActionsOnSave&quot;: {
    &quot;source.fixAll.eslint&quot;: true
  },
  &quot;eslint.validate&quot;: [
    &quot;javascript&quot;,
    &quot;typescript&quot;,
    &quot;javascriptreact&quot;,
    &quot;typescriptreact&quot;
    // ❌ 不添加 &quot;solidity&quot;，因为 ESLint 不直接解析 .sol
  ],
  &quot;solidity.formatter&quot;: &quot;prettier&quot;,
  &quot;solidity.compileUsingRemoteVersion&quot;: &quot;v0.8.20+commit.c7f1c3b1&quot;
}
"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"editor.formatOnSave"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"editor.codeActionsOnSave"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"source.fixAll.eslint"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"eslint.validate"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-string">"javascript"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-string">"typescript"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-string">"javascriptreact"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-string">"typescriptreact"</span>
    <span class="hljs-comment">// ❌ 不添加 "solidity"，因为 ESLint 不直接解析 .sol</span>
  <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"solidity.formatter"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"prettier"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"solidity.compileUsingRemoteVersion"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"v0.8.20+commit.c7f1c3b1"</span>
<span class="hljs-punctuation">}</span>
</code></pre><hr><h2 id="h-8-npm-run-lint" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">8️⃣ 最终验证：<code>npm run lint</code> 成功执行</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 执行命令</h3><pre data-type="codeBlock" text="npm run lint
"><code>npm run lint
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 输出结果</h3><pre data-type="codeBlock" text="# 1. 执行 lint:js
&gt; eslint &quot;**/*.{ts,js}&quot; --ext .ts,.js

# 2. 执行 format:check
&gt; prettier --plugin prettier-plugin-solidity --check &quot;**/*.{js,cjs,ts,sol}&quot;

# 如果 .sol 文件格式错误，prettier 会报错，导致 lint 失败
"><code># <span class="hljs-number">1.</span> 执行 lint:js
<span class="hljs-operator">></span> eslint <span class="hljs-string">"**/*.{ts,js}"</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span>ext .ts,.js

# <span class="hljs-number">2.</span> 执行 format:check
<span class="hljs-operator">></span> prettier <span class="hljs-operator">-</span><span class="hljs-operator">-</span>plugin prettier<span class="hljs-operator">-</span>plugin<span class="hljs-operator">-</span>solidity <span class="hljs-operator">-</span><span class="hljs-operator">-</span>check <span class="hljs-string">"**/*.{js,cjs,ts,sol}"</span>

# 如果 .sol 文件格式错误，prettier 会报错，导致 lint 失败
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">✅ 工作流说明</h3><ul><li><p><code>.ts/.js</code> 文件：由 ESLint 检查 + 自动修复</p></li><li><p><code>.sol</code> 文件：由 Prettier 格式化 + <code>format:check</code> 验证</p></li><li><p><code>npm run lint</code>：统一入口，确保所有文件符合规范</p></li></ul><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">✅ 最终状态</h2><p>| 功能 | 状态 | 说明 |</p><p>|------|------|------|</p><p>| <code>npm run lint</code> | ✅ 成功 | 统一检查所有文件 |</p><p>| Solidity 检查 | ✅ | 通过 <code>prettier --check</code> 实现 |</p><p>| 自动修复 | ✅ | <code>npm run lint:fix</code> 支持 |</p><p>| Prettier 集成 | ✅ | 支持 <code>.sol</code> 格式化 |</p><p>| VS Code 支持 | ✅ | 格式化 + ESLint 提示 |</p><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📌 复盘总结：技术决策路径</h2><p>| 阶段 | 决策 | 结果 | 教训 |</p><p>|------|------|------|------|</p><p>| 1. 起点 | <code>npm run lint</code> 报错 | ❌ | 需先定位错误来源 |</p><p>| 2. 尝试 | 引入 <code>solhint</code> | ⚠️ 临时方案 | 替代方案可能引入新问题 |</p><p>| 3. 验证 | <code>solhint</code> 失败 | ❌ | 不可靠，生态断裂 |</p><p>| 4. 探索 | 尝试 ESLint v9 | ❌ | 与 <code>hardhat</code> 不兼容 |</p><p>| 5. 回归 | 锁定 ESLint v8 | ✅ 正确方向 |</p><p>| 6. 解决 | 使用 <code>prettier --check</code> 作为 .sol 检查 | ✅ 成功 | 利用现有工具链 |</p><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">✅ 最终结论</h2><blockquote><p><code>solhint</code> 已不可靠，不应作为主要 linter。</p></blockquote><blockquote><p><code>eslint-plugin-solidity</code> 已废弃，不推荐使用。</p></blockquote><blockquote><p><code>hardhat@2.26.3</code> 仅兼容 <code>ESLint v8</code>，不可升级到 v9。</p></blockquote><blockquote><p><strong>正确方案</strong>：</p><ol><li><p>使用 <code>ESLint v8</code> 检查 <code>.ts/.js</code> 文件</p></li><li><p>使用 <code>prettier-plugin-solidity</code> 格式化 <code>.sol</code> 文件</p></li><li><p>使用 <code>npm run format:check</code> 作为 <code>.sol</code> 的“检查”手段</p></li><li><p>通过 <code>npm run lint</code> 统一执行</p></li></ol></blockquote><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">📎 参考资料</h2><ol><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/NomicFoundation/hardhat-toolbox/blob/main/package.json">hardhat-toolbox package.json</a>（依赖 eslint@^8.0.0）</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.npmjs.com/package/prettier-plugin-solidity">prettier-plugin-solidity</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.npmjs.com/package/eslint-plugin-prettier">eslint-plugin-prettier</a></p></li></ol><hr><blockquote><p><strong>复盘完毕</strong>。此文档完整还原了从问题提出、错误尝试、版本冲突排查到最终稳定方案的全过程，确保信息真实、路径清晰，<strong>特别强调了</strong> <code>hardhat</code> 与 <code>ESLint v9</code> 的不兼容性，可供团队复盘与知识传承。</p></blockquote>]]></content:encoded>
            <author>rainweb3@newsletter.paragraph.com (RainWeb3)</author>
        </item>
    </channel>
</rss>