Foundry 入门实战
前言
首先庆祝一下我给 Solidity 提的关于 CFG 的 PR 他们合并了,以后也是 Solidity 贡献者啦🎉🎉🎉 – https://github.com/ethereum/solidity/pull/13709
回到正题,Foundry 是测试部署合约的套件,但是对于安全工程师来讲,我们主要看中其测试功能。关于 Foundry 的基本资料我已不用赘述,但是最香的一点就是用 Solidity 来写攻击合约。比如 hardhat 这种合约+脚本的模式:

很显然 Foundry 的测试更精炼:

浅浅对比一下攻击脚本的文件数和文件树。
在本文中,我总结了上手 Foundry 的最小化知识点。以下进入正文。
官方文档
计算函数签名
(base) ➜ ~ cast 4byte 0xa9059cbb
transfer(address,uint256)
(base) ➜ ~ cast keccak “transfer(address,uint256)”
0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b
(base) ➜ ~ cast sig “transfer(address,uint256)”
0xa9059cbb
十六进制数转十进制
(base) ➜ ~ cast –to-dec 0x00000000000000000000000000000000000000000000bdb51a04b5aa8eb6431e
895868000762793410577182
复现
- 创建空文件夹,无法在非空文件夹初始化
- forge init –no-commit
- test 文件夹里写测试;🌟
src写合约(一般用于部署);
scrip一般写一些执行脚本,比如部署的时候,写多个调用
注:大部分复现都不用管src,test里面都能做
写 EXP 的一些技巧
已知地址来实例化合约
不管合约是否开源,如果确定合约里面的方法,直接创建一个 interface 来定义需要的方法。如:
interface A{};
A a=A(address)
调用直接 a.方法名()
参考 – https://solidity-by-example.org/interface/
使用接口中的结构体
直接接口引用,而非实例化之后引用。方法需要实例化后引用,而结构体不是。如:
interface IUniswapV3Router {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
}
}
使用时候:
contract AttackTest is Test {
function swapUSDC() public{
IUniswapV3Router.ExactInputSingleParams memory s = IUniswapV3Router.ExactInputSingleParams({
tokenIn:UERII_address,
tokenOut:USDC_address,
});
UniswapV3Router.exactInputSingle(s);
}
}
实战:20221017 Uerii Token – Access Control
此次攻击的相关资料
- 相关推特分析 – https://twitter.com/peckshield/status/1581988895142526976
- 攻击交易 – https://etherscan.io/tx/0xf4a3d0e01bbca6c114954d4a49503fc94dfdbc864bded5530b51a207640d86b5
- DeFiHackLab 链接 – https://github.com/SunWeb3Sec/DeFiHackLabs#20221017-uerii-token—access-control
是我专门找的一个比较简单的复现,最后根据官方文档和上面的一些最小化知识点就应该没问题。主要是还原根据 access control 有问题的 mint() 函数去 mint 两次,最终通过 Uniswap V3 swap 成 $USDC,然后又 swap 成 $WETH 的过程。
我自己写的 POC如下,供参考:
https://github.com/ChrisXXXXXXX/test/tree/main/20221017%20Uerii%20Token%20-%20Access%20Control