foundry常用
我们先看看安装了foundry后各个目录的作用,下面是一张图片,我们挨个讲解
我们安装的库都会在这里面。
编写合约的目录
部署合约的脚本目录
forge script script/Counter.s.sol --rpc-url <write> --broadcast --private -key <write>
forge script script/Counter.s.sol:CounterScript --rpc-url http://localhost:8545 --broadcast --account defaultKey --sender 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266<公钥地址>
forge script script/DeploySimpleStorage.s.sol:DeploySimpleStorage --rpc-url $OP_SEPOLIA_RPC_URL --broadcast --account defaultKey --sender
RPC_URL 可以在 Alchemy - the web3 development platform 注册得到
script/Counter.s.sol:CounterScript :script目录下的合约的合约函数
一般都是部署合约的函数
--broadcast :在链上进行广播,没有这个参数的话,合约是不会部署在链上的
--account : 跟 私钥
专门用于测试的目录。
forge test -v
-vv
参数
-vv
是一个选项,用于增加输出的详细程度。在 Foundry 中,-v
表示“verbose”(详细的),每增加一个 v
就会进一步增加详细程度。
-v
:显示基本的详细信息。-vv
:显示更多详细信息,包括每个测试的日志输出。-vvv
:显示更详细的信息,可能包括内部调试信息。-vvvv
:显示最详细的信息,通常用于调试。-vvv
或 -vvvv
:用于需要更详细的调试信息时。--gas-report
:生成 Gas 使用报告。--mt
: 指定函数进行测试forge test --mt testConvert -vvvv --fork-url $OP_SEPOLIA_RPC_URL
forge coverage --fork-url $OP_SEPOLIA_RPC_URL
这个是自己创建的隐藏敏感信息的文件,像上面跟个 “$" ,就是引用里面的变量,其实框架自己也有工具可以,只是为了平时测试的方便这么做。所以进行测试的钱包不要有真实资金在里面。
先加载环境变量
source .env
再引用里面定义好的变量
部分变量
RPC_URL=http://localhost:8545
使用
forge coverage --fork-url $OP_SEPOLIA_RPC_URL
特殊功能后面跟个参数名即可
可以方便我们导入文件的时候,不用再去修改文件路径。
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
remappings = ["@chainlink/contracts/=lib/forge-std/chainlink-brownie-contracts/contracts/"]
将 @chainlink/contracts/
替换成 lib/forge-std/chainlink-brownie-contracts/contracts/
配合这个命令我们可以看到我们替换的内容是啥
## remappings.txt 文件
forge remapping > remapping.txt
//显示依赖库导入到该txt文件里面
这个文件非常重要,当我们push代码到GitHub的时候,可以避免敏感文件被上传上去
文件内容,我们的 .env 就在里面
# Compiler files
cache/
out/
# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/
# Docs
docs/
# Dotenv file
.env
forge install < > --no-commit
如果存在无法获取github代码的情况,一般是你的WSL网络配置没配好,针对具体问题询问GPT可以解决 我们也可以不使用这个命令,我们前面是配置过 GitHub信息的,可以通过 git 命令来获取远程库。
git clone <github库的https链接 or ssh的链接>
forge compile
本地链,这个是foundry框架自带的功能,可以显示对应的虚拟用户公钥和私钥
anvil
cast call <公钥> "retrieve()<函数名>"
调用函数
cast send <合约地址> "函数名(参数)" 参数 --rpc-url --broadcast http://localhost:8545 --account defaultKey
cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "store(uint256)" 123 --rpc-url http://localhost:8545 --account defaultKey
cast call <合约地址> "retrieve()<函数名>"
cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "retrieve()"
将bytecode 编码转化 十进制
cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "retrieve()"
0x000000000000000000000000000000000000000000000000000000000000007b //调用该函数的返回值
cast --to-base 0x000000000000000000000000000000000000000000000000000000000000007b dec //dec 表示目标进制是 十进制
函数选择器查看是否跟我们要调用的函数匹配
cast sig "fund() <函数名称>"
指定函数测试预估gas
forge snapshot --mt testWithdrawWithOwner <函数名>
之后会在 .gas-snapshot.txt 文件里面看到
FundMeTest:testWithdrawWithOwner() (gas: 104736)
gas预估流程
uint256 gas_start = gasleft();
vm.prank(fundMe.getOwner());
fundMe.withdraw();
uint256 gas_end = gasleft();
uint256 gas_used = (gas_start - gas_end) * tx.gasprice; //数量 * 当前gas价格
console.log(gas_used);
下面就列举一些常用的
下面操作由上面的用户执行 -- vm.prank(USER);
modifier funded() {
//避免代码重复
vm.prank(USER);
fundMe.fund{ value: SEND_VALUE }();
_;
}
这里使用的修饰器,便携写代码
用户通过makeAddr定义
address USER = makeAddr("user"); //用作弊码创建的一个用户
给用户铸造一些代币
uint256 constant STARTING_BALANCE = 10 ether;
vm.deal(USER, STARTING_BALANCE) //前面是用户,后面是代币数量
操作期望回退
vm.expectRevert(); //预期下面的操作会回退,来测试判断条件
vm.startBroadcast(); vm.stopBroadcast(); 这个常用于我们部署合约的时候
pragma solidity ^0.8.18;
import {Script,console} from "forge-std/Script.sol";
import {FundMe} from "../src/FundMe.sol";
contract DeployFundMe is Script{
function run() public{ //run函数是默认进行合约部署的
vm.startBroadcast();
new FundMe();
vm.stopBroadcast();
}
}
注意!:vm.prank(user) 不能和 vm.startbroadcast vm.stopbroadcast 合用
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!