前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >使用 Foundry 开发环境

使用 Foundry 开发环境

作者头像
Tiny熊
发布于 2022-11-07 02:00:47
发布于 2022-11-07 02:00:47
1.2K00
代码可运行
举报
运行总次数:0
代码可运行

本文作者:Tiny 熊[1]

Foundry 是一个全新的 EVM 开发环境。有了 Solidity-native 测试能力(使用原生的 Solidity 编写测试),强大的命令行工具和高性能的 Rust 工具,Foundry 更值得大家学习,翻译一篇 Foundry 的使用指南文章。

安装

官方安装指南可以在这里[2]找到。不过我自己在用foundryup获得anvil时遇到了麻烦,所以如果你想在 bash/zsh shell 上从源码构建,请使用以下方法。注意你需要先安装有gitcargo才能进行源代码构建。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git clone https://github.com/foundry-rs/foundry && \
    cd foundry && \
    cargo install --path ./cli --bins --locked --force && \
    cargo install --path ./anvil --locked --force

如果你选择了从源码构建,那么就需要花费给你一些精力,编译器有很多事情要做。

Foundry 包含的组件

Foundry 由三个不同的命令行工具(CLI)组成,包括forgecast,和anvil。首先,我们先了解下这些工具,然后用他们来构建和测试一个智能合约

Cast

Cast 是一个 CLI 工具,用于对兼容以太坊虚拟机(EVM)的区块链进行 RPC 调用。使用cast,我们可以进行合约调用,查询数据,并处理编码和解码。cast有很多的子命令,所以要想获得完整的参考,请看 Foundry 书中的cast[3]一节!

要执行合约调用而不发布交易,我们可以使用call子命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast call 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 \
    "balanceOf(address)(uint256)" \
    0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \
    --rpc-url https://rpc.flashbots.net

这对0xC0...c2(WETH)地址执行balanceOf(address)查询,传递0xf3...66地址作为参数,并将返回数据解码为uint256类型的值。在这个和下面的cast子命令中,我们明确地使用了 Flashbots RPC,因为默认是http://localhost:8545

要查询一个地址的以太余额,我们可以使用balance子命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast balance 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \
    --rpc-url https://rpc.flashbots.net

我们也可以用 ENS 名称查询余额。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast balance yourmom.eth --rpc-url https://rpc.flashbots.net

要提取合约上的合约状态槽内容,我们可以使用storage子命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast storage 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 0 \
    --rpc-url https://rpc.flashbots.net

这将从0xC0...c2(WETH)地址中获得存储槽0内容。

Forge

Forge 是一个 CLI 工具,用于构建、测试、模糊测试、部署和验证 Solidity 合约。Forge 同样有很多的子命令,所以这里是参考文档[4]! 顺便说一下,如果你是来学习教程的,不需要运行这些命令,所有东西都包含在后面 创建 Foundry 仓库部分。

一个常用的子命令是 init,它可以初始化一个新的版本库:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge init my_gigabrain_protocol

install子命令允许你安装指定版本的依赖项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge install Rari-Capital/solmate@v6

这将安装由Rari-Capital拥有的solmate软件库,特别是v6。注意,@v6是可选的。

为了运行测试,我们可以使用以下方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge test

Anvil

Anvil 是一个 CLI 工具,用于运行本地 EVM 区块链。它可以与 ganache 和 hardhat 节点相媲美,但好像更快。

要启动 Anvil,只需使用 avil 命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
anvil

你也可以指定一些参数, 用-v来显示详细日志,如果用-fork-url <FORK_URL>指定 URL 来分叉一个公共网络,等等。要查看 anvil选项的完整列表,可以使用以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
anvil -h

创建 Foundry 仓库

初始化

为了开始工作,如上所述,我们将使用以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge init my_token && cd my_token

这将创建一个my_token目录,初始化一个 git 仓库,添加一个 GitHub 工作流目录,安装forge-std包,生成一个foundry.toml文件,一个test目录,一个src目录,最后进入到my_token目录。

让我们继续,通过运行下面的程序删除现有的合约:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
rm src/Contract.sol

现在,首先让我们看看foundry.toml文件,自动生成的文件应该是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[default]
src = 'src'
out = 'out'
libs = ['lib']

这将合约源代码目录设置为src,编译器输出目录设置为out,库的重新映射设置为lib

安装依赖

现在我们将安装一个依赖关系。我们可以使用<所有者>/<存储库>模式来安装Rari-Capitalsolmate

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge install Rari-Capital/solmate

这样就把solmate安装到了lib目录。现在让我们在src/MyToken.sol中创建一个 ERC20 合约。

我们可以导入并使用solmate的 ERC20 实现,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// SPDX-License-Identifier: AGPLv3
pragma solidity ^0.8.13;

import {ERC20} from "solmate/tokens/ERC20.sol";

error NotMinter();

contract MyToken is ERC20 {
    address public immutable minter;

    // ERC20(name, symbol, decimals)
    contructor() ERC20("MyToken", "MyT", 18) {
        minter == msg.sender;
    }

    function mint(uint256 amount) external {
        if (msg.sender != minter) revert NotMinter();
        _mint(minter, amount);
    }
}

所以这是一个符合 ERC20 标准的代币,有一个简单的访问控制功能,用于铸币控制。

注意solmate/tokens/ERC20.sol导入是根据foundry.toml文件中指定的libs/目录重新映射的。

如果你使用 VSCode 并得到错误信息,可以尝试在项目根目录下创建一个remappings.txt文件并添加以下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
solmate/=lib/solmate/src/
forge-std/=lib/forge-std/src

编译

让我们继续编译合约:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
foundry build

测试

现在我们需要写一些测试,因为一个掌管着不可忽视的价值的智能合约实际上是一个非自愿的 bug 赏金。不要让自己成为一个教训。:)

为了写测试,在test中创建一个文件。让我们创建一个名为test/MyToken.t.sol的文件。.t.sol表示这将是一个测试文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// SPDX-License-Identifier: AGPLv3
pragma solidity ^0.8.13;

import {Test} from "forge-std/Test.sol";
import {MyToken} from "../MyToken.sol";

contract MyTokenTest {
    MyToken internal myToken;
    address internal constant alice = address(1);
    address internal constant bob = address(2);

    function setUp() external {
        vm.prank(alice);
        myToken = new MyToken();
    }

    function testMint() external {
        vm.prank(alice);

        myToken.mint(1);

        assertEq(myToken.balanceOf(alice), 1);
    }

    function testFailMint() external {
        vm.prank(bob);

        myToken.mint(1);
    }
}

这里有一些代码需要解释:

forge-std导入的 Test默认是在 forge 创建 repo 时一起的生成的。它包括一个内部的vm变量,这是一个 cheat-code运行器。

vm包括一系列强大的“作弊代码”,例如:时间戳操纵 、将字节码刻在地址上、存储槽读写等。要查看所有这些代码,请看参考这里的介绍[5]。在这个例子中,我们使用vm.prank(address),其中的address参数将是下一个外部合约调用的msg.sender

要测试一个函数,在运行测试的函数的名称前加上test。在本例中,我们正在测试mint,所以我们可以叫它testMint。如果它不是以test开头,它将不会在forge test上运行。assertEq函数用来断言两个值是相等的。在Test合约中还声明了其他断言,可以在这里[6]找到参考。

要测试还原(revert),在函数名前加上testFail。在本例中,我们期望vm.prank(bob)失败,因为在setUp中,MyTokenmintervm.prank(alice)设置成了alice

现在我们来运行测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge test

一切都应该通过。如果你需要调试函数调用,请在测试命令中加入 -vvvv (verbosity 4)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge test -vvvv

如果你需要从测试内部记录变量,你可以在Test中声明的事件。使用emit log_uint(uint)记录数字,你可以用emit log_named_uint(string,uint)来进行标记。要显示事件日志,在运行forge test时使用-vv(verbosity 2)。

本地部署

为了在本地部署合约,我们需要首先启动一个 anvil 实例。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
anvil

当本地 devnet 开始运行时,这应该会打印出一些账户。让 anvil 运行实例单独使用一个终端窗口。

现在让我们从 anvil的输出中获取第一个账户的私钥,并将其设置为$PRIV_KEY环境变量。这不是必须的,它只是保持事情清晰。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export \
PRIV_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

注意这些私钥是确定的,并且是公开的,所以在公共网络上投入资金之前要三思而后行。

现在验证私钥是否可以访问:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
echo $PRIV_KEY

如果它打印出私钥,你就可以了。

现在把合约部署到本地 devnet 上:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge create src/MyToken.sol:MyToken --private-key=$PRIV_KEY

这将加载到环境中的私钥,使用src/MyToken.sol文件中MyToken创建合约。请注意语法使用了明确指定的文件名称和合约名称:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge create <filename>:<contractname> ...

在这种情况下,我们不需要构造器参数,但如果需要,则在最后传递--constructor-args标志,并写出构造器参数,用空格隔开:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge create Filename.sol:Contractname \
    --private-key $PRIV \
    --constructor-args arg0 arg1 arg2

运行后,你应该在终端上打印出类似这样的东西。注意,你的合约地址和交易哈希值可能不同。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Deployer: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
Deployed to: 0x5fbdb2315678afecb367f032d93f642f64180aa3

Transaction hash: 0x3f849ddc766b4851fed8798a26aa6fe527c74cd9d6f2639ec289f5e11ceaa3b5

很好,现在我们可以使用 cast 来试用我们新创建的代币了。

同样,为了保持整洁,在终端环境中把你的合约地址导出为$CON_ADDRESS。如果你的地址不同,只需在下面的命令中替换它。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export CON_ADDRESS=0x5fbdb2315678afecb367f032d93f642f64180aa3

现在我们来查询 token 的.name()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast call $CON_ADDRESS "name():(string)"

注意我们在函数签名中包括:(string)。这是为了帮助cast解码返回的数据,否则我们会得到一个巨大的十六进制字符串。

现在让我们使用部署该函数的同一私钥来调用 mint 函数。如果你使用任何其他的私钥则会失败,因为这是mint函数中的逻辑。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast send --private-key $PRIV_KEY $CON_ADDRESS "mint(uint256)" 1

这会给我们的账户铸造 1 个代币,你也会注意到交易数据已经打印到屏幕上。真不错。

作为本地部署的最后验证,检查你账户的余额。如果你使用的私钥不是由 anvil 提供的,你可以随时使用以下方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast wallet address --private-key $PRIV_KEY

再一次,为了方便,只需将钱包地址添加到环境中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export WALLET=0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266

现在进行余额查询。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cast call $CON_ADDRESS "balanceOf(address):uint256" $WALLET

这应该返回 1。

公共网络部署

部署在公共网络的工作原理与上述相同,当然是使用你自己的私钥、RPC 端点、链 ID。

合约代码验证

要用 Etherscan 验证你公开部署的合约,请使用以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
forge verify-contract \
    --chain $CHAIN_ID \
    --compiler-version $COMPILER_VERSION \
    $CON_ADDRESS src/MyToken.sol:MyToken $ETHERSCAN_API_KEY

总结

Foundry 很强大,而且我们还只是从表面上看到了代工厂的兔子洞有多深。我希望这篇文章对你的编程和智能合约之旅有所帮助,并一如既往地做好黑客工作 🤘。


原文:https://medium.com/@jtriley15/the-foundry-evm-development-environment-f198f2e4c372

本翻译由 Duet Protocol[7] 赞助支持。

参考资料

[1]

Tiny熊: https://learnblockchain.cn/people/15

[2]

这里: https://book.getfoundry.sh/getting-started/installation.html

[3]

cast: https://book.getfoundry.sh/reference/cast/

[4]

参考文档: https://book.getfoundry.sh/reference/forge/forge.html

[5]

这里的介绍: https://book.getfoundry.sh/cheatcodes/

[6]

这里: https://book.getfoundry.sh/reference/ds-test.html#asserting

[7]

Duet Protocol: https://duet.finance/?utm_souce=learnblockchain

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
使用深度学习进行疟疾检测 | PyTorch版
蚊子看起来很小,很脆弱,但是是非常危险的。众所周知,疟疾对所有年龄段的人来说都是一种威胁生命的疾病,它通过蚊子传播。更重要的是,在最初的阶段,这些症状很容易被误认为是发烧、流感或普通感冒。但是,在晚期,它可以通过感染和破坏细胞结构造成严重破坏,这可能危及生命。如果不及时治疗,甚至可能导致死亡。
小白学视觉
2020/11/13
8350
使用深度学习进行疟疾检测 | PyTorch版
使用深度学习进行音频分类的端到端示例和解释
声音分类是音频深度学习中应用最广泛的方法之一。它包括学习对声音进行分类并预测声音的类别。这类问题可以应用到许多实际场景中,例如,对音乐片段进行分类以识别音乐类型,或通过一组扬声器对短话语进行分类以根据声音识别说话人。
deephub
2021/03/25
1.3K0
使用深度学习进行音频分类的端到端示例和解释
VGG卷积神经网络实现Cifar10图片分类-Pytorch实战
当涉足深度学习,选择合适的框架是至关重要的一步。PyTorch作为三大主流框架之一,以其简单易用的特点,成为初学者们的首选。相比其他框架,PyTorch更像是一门易学的编程语言,让我们专注于实现项目的功能,而无需深陷于底层原理的细节。
fanstuck
2025/01/16
2911
VGG卷积神经网络实现Cifar10图片分类-Pytorch实战
PyTorch-24h 02_分类问题
loss:loss函数用于衡量模型预测和实际值的差距。不同的问题需要不同的loss函数。例如,回归问题可能用MAE,二分类问题可能用binary cross entropy。 优化器:优化器用来更新模型参数,一般使用SGD(torch.optim.SGD())或Adam(torch.optim.Adam())。
一只大鸽子
2023/02/24
3560
PyTorch-24h  02_分类问题
基于Pytorch构建AlexNet网络对cifar-10进行分类
AlexNet网络是CV领域最经典的网络结构之一了,在2012年横空出世,并在当年夺下了不少比赛的冠军。也是在那年之后,更多的更深的神经网络被提出,比如优秀的vgg,GoogLeNet。AlexNet和LeNet的设计非常类似,但AlexNet的结构比LeNet规模更大。
python与大数据分析
2023/09/03
7540
基于Pytorch构建AlexNet网络对cifar-10进行分类
CNN实战(二):pytorch搭建CNN对猫狗图片进行分类
在上一篇文章:CNN实战(一):pytorch处理图像数据(Dataset和Dataloader)里,大致介绍了怎么利用pytorch把猫狗图片处理成CNN需要的数据,本篇文章主要用该数据对自己定义的CNN模型进行训练及测试。
Cyril-KI
2022/09/16
2.7K0
CNN实战(二):pytorch搭建CNN对猫狗图片进行分类
我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)!
详细介绍了卷积神经网络 LeNet-5 的理论部分。今天我们将使用 Pytorch 来实现 LeNet-5 模型,并用它来解决 MNIST数据集的识别。
红色石头
2022/01/10
2.3K0
我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)!
基于卷积神经网络的垃圾分类
自今年7月1日起,上海市将正式实施 《上海市生活垃圾管理条例》。垃圾分类,看似是微不足道的“小事”,实则关系到13亿多人生活环境的改善,理应大力提倡。
云微
2023/02/11
9210
基于卷积神经网络的垃圾分类
我用 PyTorch 复现了 LeNet-5 神经网络(CIFAR10 数据集篇)!
我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)!
红色石头
2022/01/10
1.3K0
我用 PyTorch 复现了 LeNet-5 神经网络(CIFAR10 数据集篇)!
基于Pytorch构建LeNet网络对cifar-10进行分类
LeNet5诞生于1994年,是最早的卷积神经网络之一,是Yann LeCun等人在多次研究后提出的最终卷积神经网络结构,是一种用于手写体字符识别非常高效的网络。一般LeNet即指代LeNet5。LeNet5 这个网络虽然很小,但是它包含了深度学习的基本模块:卷积层,池化层,全连接层,是其他深度学习模型的基础。
python与大数据分析
2023/09/03
4880
基于Pytorch构建LeNet网络对cifar-10进行分类
PyTorch-24h 03_图像分类
torchvision.datasets 包含许多示例数据集,可用于练习编写计算机视觉代码。FashionMNIST 就是其中之一。它有 10 个不同的图像类别(不同类型的服装),用于多分类问题。torchvision已经内置了该数据集,可以通过torchvision.datasets加载。
一只大鸽子
2023/02/24
7840
PyTorch-24h  03_图像分类
Fashion_minst 图像识别 by PyTorch CNN
Fashion_minst 是之前介绍 Tensorflow 时用过的数据集。下面用 PyTorch 再跑它一遍 ,用作 PyTorch 的入门示例。
用户6021899
2022/03/04
4670
Fashion_minst 图像识别 by PyTorch CNN
PyTorch与深度学习
PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序。PyTorch既可以看作加入了GPU支持的numpy,同时也可以看成一个拥有自动求导功能的强大的深度神经网络。除了Facebook外,它已经被Twitter、CMU和Salesforce等机构采用。
正在走向自律
2024/12/18
1040
PyTorch与深度学习
手撕 CNN 之 AlexNet(PyTorch 实战篇)
详细介绍了 AlexNet 的网络结构,今天我们将使用 PyTorch 来复现AlexNet网络,并用AlexNet模型来解决一个经典的Kaggle图像识别比赛问题。
红色石头
2022/04/14
1.9K0
手撕 CNN 之 AlexNet(PyTorch 实战篇)
PyTorch入门,快速上手案例
PyTorch是一种开源的深度学习框架,主要用于自然语言处理和图像识别等机器学习任务,由Facebook(Meta)人工智能研究院(FAIR)开发。它提供了强大的GPU加速张量计算能力,并内置了自动微分系统。
皮大大
2024/12/06
2140
最新翻译的官方 PyTorch 简易入门教程
https://github.com/fengdu78/machine_learning_beginner/tree/master/PyTorch_beginner
用户1737318
2019/11/19
1.5K0
最新翻译的官方 PyTorch 简易入门教程
小白学PyTorch | 8 实战之MNIST小试牛刀
在这个文章中,主要是来做一下MNIST手写数字集的分类任务。这是一个基础的、经典的分类任务。建议大家一定要跟着代码做一做,源码和数据已经上传到公众号。回复【pytorch】获取数据和源码哦~
机器学习炼丹术
2020/09/14
7960
小白学PyTorch | 8 实战之MNIST小试牛刀
PyTorch ImageNet 基于预训练六大常用图片分类模型的实战
在本教程中,我们将深入探讨如何对 torchvision 模型进行微调和特征提取,所有这些模型都已经预先在1000类的Imagenet数据集上训练完成。 本教程将深入介绍如何使用几个现代的CNN架构,并将直观展示如何微调任意的PyTorch模型。由于每个模型架构是有差异的,因此没有 可以在所有场景中使用的微调代码样板。然而,研究人员必须查看现有架构并对每个模型进行自定义调整。
磐创AI
2019/09/19
5.1K0
PyTorch ImageNet 基于预训练六大常用图片分类模型的实战
PyTorch nn.Module
本节将介绍在pytorch中非常重要的类:nn.Module。在实现自己设计的网络时,必须要继承这个类,示例写法如下
mathor
2020/02/14
1.1K0
03-使用PyTorch处理最简单的神经网络分类任务(笔记+代码)
分类和回归是最常见的机器学习问题类型之一。在本笔记中,我们将使用 PyTorch 解决几个不同的分类问题(二元分类,多类分类,多标签分类)。换句话说,我们通过获取一组输入并预测这些输入集属于哪个类别。
renhai
2023/11/24
4.9K0
03-使用PyTorch处理最简单的神经网络分类任务(笔记+代码)
推荐阅读
相关推荐
使用深度学习进行疟疾检测 | PyTorch版
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档