Found a mainnet re-entrancy flaw and I exploited it.
Been sitting on this secret like a hen on her egg; it's time for the reveal!
Watch the exploit in action, bending the chain to its will.
Time for you to conquer this technique too! π§π§
A quick shout-out to the Peanut team (@0xkkonrad and @uwwgo). Had a decent chat about the ramifications of the issue and future safeguards. They were cooperative and responsive. ππ
Many links in this thread will take you away from the thread itself.
π Make sure to like this (and retweet) if you find it useful to help others like you learn these techniques.
π΅οΈββοΈ Fancy testing your hacking skills?
Dive in, roll up your sleeves, and try to spot the problem in this contract:
etherscan.io/address/0xdb60c736a30c41d9df0081057eae73c3eb119895#code
Otherwise, follow along!
I will explain what the problem is and how to exploit it.
First I have to explain what the system does.
It allows one person to deposit some tokens in the contract and another to withdraw them.
Pretty straightforward. There are other details about how the system works, but this is only what we are interested in right now.
The problem lies in the `withdrawDeposit` method.
I also fed the method to GPT4, and it missed the problem. π
When we look at the code, we see the deposit is NOT deleted before transferring the tokens.
It's literally the last thing done before returning `true`.
So how do we exploit this?
Let's have a look at the supported asset types.
1οΈβ£ Ether
Sending ether does not forward all of the gas because `.transfer` is used. Thus, only 2300 gas is forwarded to the call.
This isn't enough to re-enter the contract.
2οΈβ£ ERC20
The system supports ERC20 tokens, but they don't allow for re-entrancy.
A challenger appears!
You thought your system was safe?
Well, here to create more problems is ERC-777. It's like an ERC-20, but it allows you to re-enter on transfers.
This works by creating hooks on transfer methods. Literally allowing you to add code while a transfer is on.
For re-entrancy to work, you always need another contract.
In our case the contract is named `ExploiterERC777` and it's initialized with PeanutV3's address.
The very next thing this contract does is put itself on the line to kick into action when a transfer event occurs.
Let's see what happens when a transfer occurs, and our method is executed.
It counts up the re-entrancy times and calls back into `withdrawDeposit` to receive more tokens once again.
Make sure to check out the repository and run the exploit yourself.
It forks the chain, deploys the exploiter contract, deposits tokens and runs the exploit.
It will help you understand how to exploit a similar system yourself or even find some vulnerabilities in the future.