Boilerplate.sol
Foundry Boilerplate for Smart Contract Security Auditors and Devs
Intro
I often found myself rewriting the same boilerplate code when auditing new DeFi protocols. You always need multiple users and interact with the target contracts a certain way.
Switch User
contract MyTest is Boilerplate {
function setUp() public {
makeAddr(); // this initializes addresses
}
function testFoo() public asUser(ATTACKER){
// pwn things here
}
}
Boilerplate.sol makeAddr() creates 5 users with labels.
ATTACKER: 0x1337
USER1: 0x1001
USER2: 0x1002
USER3: 0x1003
USER4: 0x1004
When you write your test functions, simply use the Boilerplate.sol modifier asUser()
function testApprove() public asUser(USER1) {
usdc.approve(ATTACKER, 100);
}
json Boilerplate
Spin up a foundry deployment and tests that point to already deployed contracts. This can be useful to test against prod or auditing hardhat projects.
Define Protocol Addresses
create a .json
file with your target addresses:
{
"permit2": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"weth9": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
}
Adopt MyParameters
to match the needs of your target.
// src/Parameters.sol
// @dev add whatever addresses you have in your .json
struct MyParameters {
address permit2;
address weth9;
}
contract MyImmutables {
address internal immutable PERMIT2;
address internal immutable WETH9;
constructor(MyParameters memory params) {
PERMIT2 = params.permit2;
WETH9 = params.weth9;
}
}
Follow the DeployWithParams.sol
example to either deploy with foundry or point to deployed contracts and start interacting wit them.
Run deployments with:
forge script --broadcast \
--rpc-url $RPC_URL
--private-key $DEPLOYER_KEY
--sig 'run(string)' \ # neat trick to pass CLI params to foundry function
script/DeployWithParams.sol:DeployWithParams \
src/deploy/network.json \ # your .json
Tipp: Make sure you add file read access to your foundry.toml
fs_permissions = [{ access = "read", path = "./src/deploy"}]