A Foundry re-write of Damn Vulnerable DeFi
This repository was created because I wanted to learn more about Solidity and Foundry, and try my hand at the Damn Vulnerable Defi challenges. I encourage you to read my code in the repo, especially the tests and how I've created them. And when you've solved a challenge, switch to the solutions branch and compare my thoughts and solution to how you did it. I am not (yet!) an expert, and there may be better or more efficient ways to do things.
My hope and intention with this repository is that you improve your Foundry knowledge as well as learn the Damn Vulnerable Defi challenges. There are no set rules. I have attempted to make getting started very easy by doing as much setup as possible, but you are free to modify the code and tests as you see fit. Whatever helps you learn is what you should do!
Please submit a pull request if you find an issue or want to add something!
- In the solutions branch, my solutions for #13 and #14 do not work, and I am having trouble determining why. If you are attempting those challenges, it is possible that your solutions may be correct but still not work if I have not written the tests or setup correctly. If you can fix them, please submit a PR to the solutions branch!! I am offering a $150 bounty paid in ether for each of those two challenges, for the first submission that fixes the solution branch and explains why my solution didn't work (or why my test was not correctly setup). I very much want this repo to be complete and work for all challenges.
- There are compilation warnings about the size of the test contract in "test/09 - PuppetV2.t.sol" and script in "script/Deployers/09 - Deploy Puppet V2.s.sol". Those warnings can be ignored.
- Sometimes I have setup tests in an odd way, or done things that may seem unnecessary. The most common example of this is deploying contracts via bytecode. Usually this is because I need a contract written in a different Solidity version than the one the test is using, because I am trying to ensure the compiler versions match whatever was used in the original challenges. But there may be other oddities as well. Please contact me or submit a PR if you find something you believe is wrong or is causing problems.
Damn Vulnerable DeFi is the wargame to learn offensive security of DeFi smart contracts in Ethereum.
Featuring flash loans, price oracles, governance, NFTs, DEXs, lending pools, smart contract wallets, timelocks, and more!
-
Basic Foundry knowledge. You should have used Foundry a little bit and be familiar with how to write a Foundry test and use
forge test
to test a contract. Also, you should be able to useanvil
to create a local chain fork. -
A Linux-like terminal environment to run
forge test
in, the Foundry tools (forge, cast, and anvil) and thejq
Linux program. Some tests require using anvil to create a fork or using cast to get information from an RPC endpoint. When this is necessary, it is noted in the readme.txt file for each challenge. However, you should also examine the contracts test files and ensure you understand what is happening before running the test. (It'sgenerallyalways a bad idea to run untrusted code, especially when that code knows you probably have crypto on your machine.)- FFI is explicitly disabled in the config, and if a test requires it, that is noted in the readme.txt file. Once again, I encourage you to read the test file before executing a test, especially if it uses FFI.
-
An RPC endpoint (with an API key if necessary) set to the environment variable
ETH_RPC_URL
. Additionally, if you have an Etherscan account, setting your Etherscan API key to the environment variableETHERSCAN_API_KEY
would be useful. Some of the tests fork or get data from the RPC endpoint, so it's useful have an endpoint already setup in your environment. I recommend having an account and API key for your endpoint, so that you are not rate-limited. A free account on Alchemy or Infura will suffice, but whatever endpoint you choose, it must be an archival node, so that historical data is available.
- Ensure that all foundry tools and necessary Linux terminal programs are installed.
- Clone the repository.
- Run
git submodule update --init --recursive && forge install OpenZeppelin/openzeppelin-contracts-upgradeable --no-commit && git submodule update --init --recursive
inside thedamn-vulnerable-defi-foundry
folder to ensure dependencies are installed and set to the correct versions. - Delete the file
damn-vulnerable-defi-foundry/test/00 - Setup Script.t.sol
since it merely causesforge build
to fail with an error telling you to run the command in step 3. - Commit the changes from steps 3 and 4 so that you can preserve them when you switch branches in the next step.
- Switch/checkout a new branch off the main branch, so that any upates or changes to the repo don't create conflicts while you are working.
- Code your solution in the
src
folder, inside thesolveChallenge()
function that is in theYOUR_SOLUTION.sol
file for each challenge. (You can ignore the contract name in theYOUR_SOLUTION.sol
file -- I named them something I thought was fun rather than just "AttackContract".) - Then just run the test using the challenge name and at least two v's (
-vv
) of verbosity. For example:forge test --mt Unstoppable -vv
orforge test --mt Side_Entrance -vv
. (Challenge names that contain multiple words can be calledLike_This
orLikeThis
. You can also use the challenge number, e.g.forge test --mt 03 -vv
. Numbers 1-9 need to be prefixed with a zero.) - If the test is executed successfully without a revert, you've passed!
- (Optional) To get a call trace that may help you debug a test failure, you can use five v's (e.g.
forge test --mt Unstoppable -vvvvv
). Alternatively, you can go through the EVM code byte-by-byte by replacing the--mt
or--match-test
argument with the--debug
argument. For example:forge test --debug Unstoppable
- To code the solutions, you may need to read about Foundry.
- In all challenges you must use the account called
player
. This is usually coded in for you inside the tests usingvm.prank(player)
, but if it is not, keep this rule in mind. - Some challenges may require you to code additional functions inside the solution contract, or even create and deploy new custom smart contracts. Feel free to modify the solution contract to fit your needs. You may also want to read and modify the test contracts that test your challenge in order to properly run any additional contracts or functionality you've created. The purpose of this repository and of the Damn Vulnerable Defi challenges is to help you learn, so you should do whatever is necessary to acheive that goal!
- Go here for troubleshooting, support and Q&A on the challenges. But keep in mind this support is for the original hardhat javascript version of Damn Vulnerable DeFi and they may be unable to help you. Feel free to start discussions or raise issues in this Foundry Edition repo.
- Please submit pull requests if you find issues or errors, or think you can make the repository better!
< version v3.0.0 >
Damn Vulnerable DeFi created by @tinchoabbate - maintained by The Red Guild
Foundry Edition created by Max Weiss