Dissecting DeFi Protocols

Share this post

Learn enough Foundry to be dangerous

0xkowloon.substack.com

Learn enough Foundry to be dangerous

Writing integration tests with Foundry

0xkowloon
Apr 29, 2022
3
3
Share this post

Learn enough Foundry to be dangerous

0xkowloon.substack.com

In the last episode of Dissecting DeFi protocols, I looked at the difference between LooksRare and Zora. This time, I am going to build a simple integration test with some happy and unhappy paths to demonstrate how Foundry works.

Yes, I am late to the party, but better late than never.

You can find the repository here.

The setup

Foundry tests are written in Solidity. To create a test, the contracts that need to be tested have to be deployed inside the test contract. They need to be stored as storage variables to be used by each test. Any reusable variables should also be defined as such.

Creating some personas

Well, what is a protocol good for if there are no users? We will need a seller and a buyer at least to test the order matching strategy.

Foundry provides a way for you to simulate different situations through the concept of cheat codes. In the code above, I first assign the special address constant HEVM_ADDRESS to a cheat codes interface, and then compute the seller/buyer addresses with the private key 1 and 2 (private keys are just numbers). Normally you don’t need to create addresses to impersonate an address this way, but because we will need the private key to sign maker orders later, we are going to use the addr method. You can find more information about cheat codes here.

Printing some ultrasound money 🔊🦇

How are we going to buy NFTs if we don’t have ETH!? Let’s give the buyer 1 ETH and also wrap it, as we want to test the buy with ERC-20 functionality.

The function deal sets the buyer balance to 1 ETH and the function startPrank sets msg.sender for all subsequent calls until stopPrank is called. If you come from hardhat, this is basically Foundry’s version of hardhat_impersonateAccount. There is another function prank that only sets msg.sender for the next call. When I used the prank function, I spent a long time debugging some tests only to realize the msg.sender was wrong because I forgot it was only valid for one call!

MINT DAT NFT

We need an NFT to sell! For test purposes I have created a TestERC721 contract and minted token ID 0 to the seller. I have also impersonated the seller to approve LooksRare’s ERC-721 transfer manager to operate on the seller’s token.

Happy path - a successful sale

All tests are functions that start with the prefix “test”. When you call forge test in the terminal, Foundry knows automatically which tests to run.

BLAZING FAST!

You can also specify a test to run.

Or a test contract.

You get the idea.

I’ve started the test with some initial assertions to make sure the seller owns the NFT and has no ETH, the buyer has 1 ETH, and the fee recipients have no ETH.

A maker order signature is required for the transaction and I’ve created 2 helper functions makerOrderStruct and signOrder to create the signature. The OrderTypes.MakerOrder comes from the protocol, I just set it as an 1 ETH ask for TestERC721’s token ID 0, valid from the current block til 1 day from now. The cheat code sign is then used to create a signature.

With the signature created, we can now match a taker bid with the maker ask and submit the transaction on-chain.

The transaction didn’t revert, and we can now test our assertions!

The buyer received his NFT, the seller and the fee recipients got paid, awesome!

A reverted test

This reverted test is very similar to the happy path test, except I’ve cancelled the maker ask before matching it with the taker bid, called expectRevert to test the revert error message and tested that no assets changed hands after the matchAskWithTakerBid call. expectRevert is similar to hardhat’s .to.be.revertedWith call.

HALP! I NEED TO DEBUG

Often you will want to log information into the terminal for debug purposes. While Foundry does not have console.log like hardhat does, there is an option to emit events with the data you want to see as arguments. The following events are available.

If you want to see the logs, you will have to run the tests with the verbose flag (-vv) turned on.

And that’s it…! You now know enough Foundry to be dangerous!

3
Share this post

Learn enough Foundry to be dangerous

0xkowloon.substack.com
3 Comments
shatin_yau
May 1, 2022

Love the code images, do you use any tool to generate those?

Expand full comment
Reply
shatin_yau
May 1, 2022

Love the code images, do you use any tools to generate those?

Expand full comment
Reply
1 reply by 0xkowloon
1 more comment…
TopNewCommunity

No posts

Ready for more?

© 2023 0xkowloon
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing