🧱 Solidity 合约开发全流程(Foundry 版)

✅ 适合对象:已经能写合约但不清楚如何测试、部署、交互的开发者
✅ 工具链:Foundry(forge, anvil, cast)


📌 开发流程总览

1️⃣ 初始化项目
2️⃣ 编写合约
3️⃣ 编译合约
4️⃣ 编写测试文件
5️⃣ 运行测试
6️⃣ 编写部署脚本
7️⃣ 在本地链部署
8️⃣ 部署到测试网(如 Sepolia)
9️⃣ 编写交互脚本


1️⃣ 初始化 Foundry 项目

forge init my-foundry-project
cd my-foundry-project

结构自动生成:

my-foundry-project/
├── src/                    # 合约代码
│   └── MyContract.sol
├── script/                 # 部署脚本
│   └── DeployMyContract.s.sol
├── test/                   # 测试文件
│   └── MyContract.t.sol
├── foundry.toml           # 配置文件
└── lib/                   # 依赖


2️⃣ 编写合约(src/ 目录)

src/SimpleStorage.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;contract SimpleStorage {uint256 private favoriteNumber;function store(uint256 _number) public {favoriteNumber = _number;}function retrieve() public view returns (uint256) {return favoriteNumber;}
}


3️⃣ 编译合约

forge build        # 推荐
# 或者
forge compile

输出生成在 /out 和 /artifacts 中。


4️⃣ 编写测试文件(test/)

test/SimpleStorage.t.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;import "forge-std/Test.sol";
import "../src/SimpleStorage.sol";contract SimpleStorageTest is Test {SimpleStorage public simpleStorage;function setUp() public {simpleStorage = new SimpleStorage();}function testStoreAndRetrieve() public {simpleStorage.store(42);uint256 value = simpleStorage.retrieve();assertEq(value, 42);}
}


5️⃣ 运行测试

forge test

可加参数:

forge test -vvv     # 输出更详细日志(v越多越详细)


6️⃣ 编写部署脚本(script/)

script/DeploySimpleStorage.s.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;import "../src/SimpleStorage.sol";
import "forge-std/Script.sol";contract DeploySimpleStorage is Script {function run() external returns (SimpleStorage) {vm.startBroadcast();SimpleStorage deployed = new SimpleStorage();vm.stopBroadcast();return deployed;}
}


7️⃣ 部署到本地链(Anvil)

启动本地链:

anvil

新窗口运行部署脚本:

forge script script/DeploySimpleStorage.s.sol:DeploySimpleStorage \--rpc-url http://127.0.0.1:8545 \--broadcast


8️⃣ 部署到测试网(Sepolia)

先获取测试 ETH:

  • 🛠 Faucet: https://cloud.google.com/application/web3/faucet/ethereum/sepolia

准备 

.env

 文件:

.env(不要上传 GitHub)

PRIVATE_KEY=你的私钥(0x开头)
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/你的API密钥

执行部署脚本:

source .envforge script script/DeploySimpleStorage.s.sol:DeploySimpleStorage \--rpc-url $SEPOLIA_RPC_URL \--private-key $PRIVATE_KEY \--broadcast \--verify  # 如果配置了 Etherscan 验证


9️⃣ 编写交互脚本(如调用函数)

script/InteractSimpleStorage.s.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;import "../src/SimpleStorage.sol";
import "forge-std/Script.sol";contract InteractSimpleStorage is Script {function run() external {address contractAddr = vm.envAddress("CONTRACT_ADDRESS");vm.startBroadcast();SimpleStorage instance = SimpleStorage(contractAddr);instance.store(777);vm.stopBroadcast();}
}

执行:

CONTRACT_ADDRESS=0xabc... forge script script/InteractSimpleStorage.s.sol:InteractSimpleStorage \--rpc-url $SEPOLIA_RPC_URL \--private-key $PRIVATE_KEY \--broadcast


📦 常用命令汇总

操作

命令

初始化项目

forge init

编译

forge build 或 forge compile

测试

forge test -vvv

启动本地链

anvil

部署本地

forge script ... --rpc-url http://127.0.0.1:8545 --broadcast

部署测试网

forge script ... --rpc-url $RPC --private-key $PK --broadcast

调用合约

cast send / 编写交互脚本

查看 ABI

cast interface


🧪 标准测试方法模板

function testXXXX() public {// Arrange(准备测试环境)...// Act(调用函数)...// Assert(断言检查)...
}


✅ 总结建议

阶段

建议工具

重点

写合约

VSCode + Hardhat 插件

注释清晰,分层设计

测试

forge-std/Test.sol

覆盖所有函数逻辑、边界条件

部署

.s.sol + broadcast

本地验证 OK 再上测试网

交互

cast or 脚本

统一管理地址、密钥、网络

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/88714.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88714.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/88714.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式 - 面向对象原则:SOLID最佳实践

文章目录深入理解 SOLID:用对原则,别把简单问题搞复杂SOLID 原则概览1. 单一职责原则(SRP)2. 开闭原则(OCP)3. 里氏替换原则(LSP)4. 接口隔离原则(ISP)5. 依赖…

Vue 3 中父组件内两个子组件相互传参的几种方法

方法一&#xff1a;通过父组件中转&#xff08;Props Emits&#xff09;<!-- ParentComponent.vue --> <template><ChildA :message-from-b"messageFromB" send-to-b"handleSendToB" /><ChildB :message-from-a"messageFromA&q…

三子棋游戏设计与实现(C 语言版)

一、需求分析目标&#xff1a;实现一个简单的人机对战三子棋&#xff0c;支持以下功能&#xff1a;初始化空棋盘&#xff0c;清晰展示落子状态。玩家通过坐标落子&#xff08;X 代表玩家&#xff09;&#xff0c;电脑随机落子&#xff08;O 代表电脑&#xff09;。实时判断胜负…

GD32 CAN1和TIMER0同时开启问题

背景&#xff1a;今天在一个项目调试的时候发现了一些问题&#xff0c;由此贴记录一下问题解决的过程。使用的芯片是GD32F305VE。使用到了CAN1和TIMER0。在使用这连个外设的时候发送了一些问题。单独使用CAN1。功能正常。单独使用TIMER0。配置为输出模式。功能正常。但是当两个…

剑指offer56_数组中唯一只出现一次的数字

数组中唯一只出现一次的数字在一个数组中除了一个数字只出现一次之外&#xff0c;其他数字都出现了三次。 请找出那个只出现一次的数字。 你可以假设满足条件的数字一定存在。 思考题&#xff1a; 如果要求只使用 O(n) 的时间和额外 O(1) 的空间&#xff0c;该怎么做呢&#xf…

从语音识别到智能助手:Voice Agent 的技术进化与交互变革丨Voice Agent 学习笔记

From Research AI&#xff1a; 最近看到 Andrew Ng 的一句话让我印象深刻&#xff1a;“While some things in AI are overhyped, voice applications seem underhyped right now.”&#xff08;尽管 AI 中有些领域被过度炒作&#xff0c;语音应用却似乎被低估了&#xff09;。…

什么是Jaccard 相似度(Jaccard Similarity)

文章目录✅ 定义&#xff1a;&#x1f4cc; 取值范围&#xff1a;&#x1f50d; 举例说明&#xff1a;&#x1f9e0; 应用场景&#xff1a;⚠️ 局限性&#xff1a;&#x1f4a1; 扩展概念&#xff1a;Jaccard 相似度&#xff08;Jaccard Similarity&#xff09; 是一种用于衡量…

ragflow_多模态文档解析与正文提取策略

多模态文档解析与正文提取策略 RAGflow的文档解析系统位于deepdoc/parser/目录下,实现了对多种文档格式的统一解析处理。该系统采用模块化设计,针对不同文档格式提供专门的解析器,并通过视觉识别技术增强解析能力。本文将深入探讨RAGflow的文档解析系统的设计原理、实现细节…

数据结构栈的实现(C语言)

栈的基本概念栈是一种特殊的线性存储结构&#xff0c;是一种操作受到限制的线性表&#xff0c;特殊体现在两个地方&#xff1a;1、元素进栈出栈的操作只能从同一端完成&#xff0c;另一端是封闭的&#xff0c;通常将数据进栈叫做入栈&#xff0c;压栈等&#xff0c;出栈叫做弹栈…

【springboot】IDEA手动创建SpringBoot简单工程(无插件)

大致步骤 创建Maven工程 引入依赖 提供启动类 详细教程 创建Maven工程 修改pom.xml文件 添加父节点 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.5.3</…

独立开发第二周:构建、执行、规划

一 第二周的独立开发旅程落下帷幕。相较于第一周的适应&#xff0c;本周的核心词是“聚焦”与“执行”。 目标非常明确&#xff1a;在产品开发上取得进展&#xff1b;在个人工作节奏上&#xff0c;将上周初步形成的框架进行实践与固化。 同时&#xff0c;为至关重要的自媒体运营…

在YOLO-World中集成DeformConv、CBAM和Cross-Modal Attention模块的技术报告

在YOLO-World中集成DeformConv、CBAM和Cross-Modal Attention模块的技术报告 1. 引言 1.1 项目背景 目标检测是计算机视觉领域的核心任务之一,而YOLO(You Only Look Once)系列算法因其出色的速度和精度平衡而广受欢迎。YOLO-World是YOLO系列的最新发展,专注于开放词汇目标…

从UI设计到数字孪生实战应用:构建智慧金融的风险评估与预警平台

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;传统金融风控的 “滞后困境” 与数字孪生的破局之道金融风险的隐蔽性、突…

【Linux】权限相关指令

前言&#xff1a; 上两篇文章我们讲到了&#xff0c;关于Linux中的基础指令。 【Linux】初见&#xff0c;基础指令-CSDN博客【Linux】初见&#xff0c;基础指令&#xff08;续&#xff09;-CSDN博客 本文我们来讲Linux中关于权限中的一些指令 shell命令 Linux严格来说是一个操…

前端学习3--position定位(relative+absolute+sticky)

继上一篇&#xff0c;做下拉菜单的时候&#xff0c;涉及到了position&#xff0c;这篇就来学习下~先看下position在下拉菜单中的应用&#xff1a;一、关键代码回顾&#xff1a;/* 下拉菜单容器 */ .dropdown {position: relative; /* ➊ 关键父级 */ }/* 下拉内容&#xff08;默…

APP Inventor使用指南

APP Inventor使用指南一、组件介绍二、逻辑设计设计方法&#xff1a;设计实例&#xff08;参考嘉立创教程&#xff09;点击跳转 &#xff1a; app inventor&#xff08;点不开的话需要&#x1fa84;&#x1fa84;&#x1fa84;&#x1fa84;&#x1fa84;&#xff09; 一、组…

SpringAI实现保存聊天记录到redis中

redis相关准备添加依赖我利用redission来实现<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.37.0</version> </dependency>添加配置文件spring:redis:database: 5host: 127.0.0.1…

Unity中使用EzySlice实现模型切割与UV控制完全指南

引言 在Unity中实现3D模型的动态切割是一个常见的需求&#xff0c;无论是用于游戏特效、建筑可视化还是医疗模拟。本文将全面介绍如何使用EzySlice插件实现高效的模型切割&#xff0c;并深入探讨如何通过Shader Graph精确控制切割面的UV映射。 第一部分&#xff1a;EzySlice基…

【c++学习记录】状态模式,实现一个登陆功能

状态模式建议为对象的所有可能状态新建一个类&#xff0c; 然后将所有状态的对应行为抽取到这些类中。 原始对象被称为上下文 &#xff08;context&#xff09;&#xff0c; 它并不会自行实现所有行为&#xff0c; 而是会保存一个指向表示当前状态的状态对象的引用&#xff0c;…

Docker 搭建 Harbor 私有仓库

1 部署 Harbor 注意&#xff1a;docker、docker-compose、Harbor的版本是否适配&#xff0c;这里使用的版本如下表&#xff1a; Docker版本Docker Compose版本Harbor版本v19.09.8v1.29.2v2.8.2 1.1 安装 docker-compose # 下载 docker-compose 1.29.2 版本 curl -L "h…