WEB3-Day8—Foundry框架[part1]

WEB3-Day8—Foundry框架[part1]

简介

Foundry Fundamentals

Foundry 是一个相对较新但发展迅猛的智能合约开发框架,以高效性和模块化设计著称。关于这个强大工具的最佳简介可查阅 《Foundry 官方手册》
Foundry 可管理项目依赖、编译工程、运行测试、部署合约,并支持通过命令行及 Solidity 脚本与区块链交互。

请务必收藏 《Foundry 官方手册》—— 它是最全面的资源,可解答您的所有疑问,在学习过程中会持续提供帮助。

Foundry 的核心优势包括:

  • 借助 Rust 进行编译,相比 Hardhat 或 Brownie 等框架,构建速度显著提升;
  • 完全基于 Solidity 开发,无需学习其他编程语言;
  • 文档体系极为完善

推荐代码编辑器:Visual Studio Code

在本课程中,我们将使用 Visual Studio Code 完成智能合约的 编写测试部署交互。这款轻量级代码编辑器功能强大,支持 Windows、macOS 和 Linux 系统,其丰富的扩展生态系统使其成为智能合约开发的首选工具之一。

安装Foundry

curl -L https://foundry.paradigm.xyz | bash
source /Users/tinachan/.zshenv
foundryup

创建文件夹和初始化

创建文件夹

mkdir foundry-f23  
cd foundry-f23  

现在输入以下命令:

mkdir foundry-simple-storage-f23  
cd foundry-simple-storage-f23  

技巧:输入目标路径的前几个字母后按 Tab 键可快速补全 cd 命令——Tab 键能自动补全大部分命令/路径。

若输入 code .,将打开新的 VS Code 实例,并默认以 foundry-simple-storage-f23 为工作路径。

可通过左侧边栏查看该文件夹内容。尝试执行以下命令:

touch randomFile.txt  

这将创建一个 randomFile.txt 文件。

若需删除该文件,输入:

rm randomFile.txt  

终端在移动/打开/创建目录/文件、切换路径及运行程序方面非常便捷。若想提升操作效率,推荐阅读 此教程

创建新项目

创建新Foundry项目 的方式是执行 forge init 命令,这将在当前工作目录生成一个新的Foundry项目。

若希望Foundry在新文件夹中创建项目,输入:forge init 新文件夹名称

注意forge init 默认要求目标文件夹为空。若文件夹非空,需执行 forge init --force .

若遇到Git配置相关错误,需先配置用户名和邮箱:

git config --global user.email "你的邮箱@提供商.com"  
git config --global user.name "你的用户名"  

完成后,文件夹结构应如下所示:
Image1

各文件夹含义说明:

  • lib:存放所有依赖项,例如:

    • forge-std(用于测试和脚本的forge库)
    • openzeppelin-contracts(经过大量实践验证的智能合约库)
    • 其他按需安装的依赖
  • scripts:存放所有脚本文件

  • src:存放所有智能合约源文件

  • test:存放所有测试文件

  • foundry.toml:Foundry的配置参数文件

后续将详细介绍这些文件夹和文件。

现在请右键点击 src 文件夹,选择 New File 并命名为 SimpleStorage.sol。将 此链接 中的代码复制到该文件中。

最后一步:请删除 Counter.s.solCounter.solCounter.t.sol。这些是Foundry创建新项目时默认提供的基础智能合约文件。

VSCode插件

刚开始编写代码时,界面可能只是一片单调、缺乏格式的白色文本。

通过安装 Solidity 扩展可轻松解决这个问题。在扩展选项卡(按 CTRL/CMD + SHIFT + X)中,以下几个 Solidity 扩展值得关注:

  1. Solidity by Juan Blanco —— 最常用的 Solidity 扩展。
  2. Solidity by Nomic Foundation —— Patrick 最推荐的 Solidity 扩展,本课程将使用此扩展演示。
  3. Solidity Visual Developer —— 另一款热门选择。

注意:若安装扩展后代码仍无高亮,可按以下步骤解决:
按下 Command + Shift + P(macOS)或 Control + Shift + P(Windows)打开命令面板,输入“Settings”并选择 “Preferences: Open User Settings (JSON)”

若文件为空,添加以下设置:

{
  "editor.defaultFormatter": "NomicFoundation.hardhat"
}
  • 若使用 Solidity Visual Developer,设置为:
    "editor.defaultFormatter": "tintinweb.solidity-visual-auditor"
  • 若使用 Solidity by Juan Blanco,设置为:
    "editor.defaultFormatter": "JuanBlanco.solidity"

其他实用扩展

上一课提到的 foundry.toml 配置文件也有对应的格式化扩展,推荐安装 Even Better TOML,提升 TOML 文件的可读性。

另一款必备扩展是 Inline Bookmarks,其功能如下:
该插件支持在代码中添加书签,适用于文档评审、安全审计、日志分析及记录开发笔记和待办事项。书签会随文件保存,可轻松与他人共享。

默认预设的触发标签/关键词如下:

  • @todo(蓝色):常规待办事项标记
  • @note(蓝色):常规注释
  • @remind(蓝色):提醒事项
  • @follow-up(蓝色):待跟进事项
  • @audit(红色):潜在问题标记
  • @audit-info(蓝色):待后续处理的信息标记
  • @audit-ok(绿色):标记某行代码无问题(即使看似有问题)
  • @audit-issue(紫色):标记已记录问题的代码位置

提示:这些标签的颜色可完全自定义!它们在开发尤其是项目审计中非常实用,更多细节可查阅 官方文档

编译合约

复制之前Solidity基础课程中的 SimpleStorage.sol合约

然后打开新终端。输入 forge buildforge compile 来编译项目中的智能合约。

image-20250707155154335

部署合约

Anvil

部署智能合约有多种方式和平台。使用Foundry框架开发时,最简单且现成的部署环境是Anvil。

Anvil是Foundry自带的本地测试网络节点,可用于从前端测试合约或通过RPC交互。在终端输入anvil即可运行:

Image1

此时会生成10个测试地址,每个地址预存10_000 ETH及对应的私钥。该测试节点默认监听127.0.0.1:8545,此地址将作为部署合约时的RPC_URL参数(后续会详细说明)。更多Anvil相关信息可查阅 官方文档

如需关闭Anvil,按Ctrl/CMD + C即可。本课程将全程使用Anvil部署和测试合约,在此之前先了解一个中间步骤。

Ganache

Ganache通常指糕点酱,由等量奶油和碎巧克力加热制成,先温热奶油再浇在巧克力上。

等等,这里说的不是糕点酱!另一个Ganache:
Ganache是用于快速开发以太坊和Filecoin分布式应用的个人区块链,可在整个开发生命周期中使用,支持在安全且确定的环境中开发、部署和测试dApp。

请从 此处 下载Ganache。

使用Windows WSL的用户请阅读 此文档——在该环境中配置Ganache并非易事,且后续不会使用,因此配置失败无需担心。

点击Quickstart Ethereum,即可生成全新区块链,包含带余额的地址和私钥。

配置MetaMask

若需部署到自定义网络(如本地节点),需使用MetaMask——这是一款流行的加密货币钱包和浏览器扩展,支持与以太坊区块链及其生态交互。尚未安装者可从 此处 下载。

配置步骤如下:

  1. 打开MetaMask,点击三点图标并选择Expand View
  2. 进入SettingsNetworks,查看网络列表及详情,重点关注RPC URL;
    RPC URL本质上是发送交易时调用API的端点,每次执行区块链交易都会向该地址发送API请求。

添加自定义区块链网络的步骤:

  1. 点击Add a Network,滚动至列表底部;
  2. 选择Add a Network manually,输入本地网络信息:
    • 网络名称:Localhost
    • 新RPC URL:Ganache为http://127.0.0.1:7545,Anvil为http://127.0.0.1:8545(需确保添加http://,具体URL以Ganache界面或Anvil终端显示为准)
    • 链ID:Ganache通常为5777(或1337),Anvil为31337(具体ID以工具显示为准)
    • 货币符号:ETH
    • 区块浏览器URL:留空(本地区块链无区块浏览器,关闭VS Code/Ganache后数据通常会丢失)

配置完本地网络后,需将Ganache或Anvil中的账户导入MetaMask,步骤如下 点击查看详情

  1. 点击钱包顶部的账户选择器,点击Add account or hardware wallet
  2. 选择Import account,粘贴Ganache/Anvil的私钥并点击Import

重要提示:此账户仅限本地测试使用,切勿在主网或其他真实区块链中使用,所有人均可访问该账户!

接下来将进一步讲解在MetaMask中添加新网络的细节。

命令行部署

forge create SimpleStorage --interactive

image-20250707161734804

脚本部署

通过脚本部署智能合约特别实用,因为它提供了一致且可重复的可靠部署方式,其特性还能增强对部署流程和代码本身的测试。

你可能喜欢命令行方式,但脚本会丰富整个部署流程,带来无可比拟的功能扩展和易用性。

Foundry基于Solidity开发,这意味着我们的部署脚本也将使用Solidity编写。必须明确区分作为合约语言的Solidity和作为脚本语言的Solidity——Foundry还整合了扩展功能,让Solidity的应用超出智能合约范畴。现在开始创建部署简单存储合约的脚本。

在Foundry中,脚本存放在script文件夹下

  1. 创建新文件DeploySimpleStorage.s.sol
    • .s.sol是Foundry脚本的命名规范,后续编写测试时会使用.t.sol后缀。
    • 更多脚本最佳实践可查阅 此处

编写Solidity部署脚本

  1. 初始代码框架:

    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.19;
    
    contract DeploySimpleStorage {
    }
    • 前两行分别声明许可证和Solidity版本。
  2. 导入依赖并继承Script

    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.19;
    
    import {Script} from "forge-std/Script.sol";
    import {SimpleStorage} from "../src/SimpleStorage.sol";
    
    contract DeploySimpleStorage is Script {
    }
    • forge-std(Forge标准库)包含预写的Solidity合约,用于简化和增强Foundry中的脚本与测试。
  3. 添加run主函数:

    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.19;
    
    import {Script} from "forge-std/Script.sol";
    import {SimpleStorage} from "../src/SimpleStorage.sol";
    
    contract DeploySimpleStorage is Script {
        function run() external returns (SimpleStorage) {
            vm.startBroadcast();
    
            SimpleStorage simpleStorage = new SimpleStorage();
    
            vm.stopBroadcast();
            return simpleStorage;
        }
    }
    • vm是Foundry的“作弊码”(cheat codes),仅在Foundry环境中生效:
      • vm.startBroadcast()标记发送到RPC URL的交易开始;
      • vm.stopBroadcast()标记交易结束;
    • new SimpleStorage()通过Solidity的new关键字创建合约实例。

执行部署脚本

  1. 停止正在运行的Anvil(按CTRL(CMD) + C),运行:

    forge script script/DeploySimpleStorage.s.sol
    • 若遇“文件中Solidity版本不兼容”错误,确保SimpleStorage.sol和部署脚本均使用pragma solidity 0.8.19;
  2. 典型输出:

    [⠆] Compiling...
    [⠔] Compiling 2 files with 0.8.19
    [⠒] Solc 0.8.19 finished in 1.08s
    Compiler run successful!
    Script ran successfully.
    Gas used: 338569
    
    == Return ==
    0: contract SimpleStorage 0x90193C961A926261B756D1E5bb255e67ff9498A1
    • 关键问题:未指定RPC URL时,Foundry会自动启动并终止Anvil实例完成部署。
  3. 指定RPC URL模拟部署:

    # 先启动Anvil
    anvil
    # 新开终端执行
    forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545
    • 输出中的SIMULATION COMPLETE表示这是模拟部署,生成的broadcast文件夹记录脚本运行信息。
  4. 广播部署(添加私钥):

    forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
    • Anvil终端将显示成功部署的交易信息:
      Transaction: 0x73eb9fb4ef7b159e03c50d669c42e2ec4eeaa9358bea0a710cb07168e5192570
      Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3
      Gas used: 357088