// an early withdrawal occurred require(withdrawn > 0);
// penalty is what's left msg.sender.transfer(address(this).balance); } }
analyse
our goal is to make address(this).balance == 0, at first address(this) == 1 ETH
The design of this level is not very good. There are two ways to complete this task
solution 1
1.beneficiary calls withdraw()
2.beneficiary calls collectPenalty()
3.call isComplete()
of course, this is not the thing that designer wants us to do
solution 2
Anyone can steal all the money in th contract! Let’s look at the following code: it checks withdrawn > 0, while withdrawn = startBalance - address(this).balance. startBalance = 1 ETH, initial address(this).balance = 1 ETH. But what if we send some money to this contract? It would cause an integer overflow bacause address(this).balance > 1 ETH and withdrawn will be very large so it can easily pass the require.
But how to send some money to this contract? It doesn’t contain an function that can receive money or even a fallback() or receive() to receive money. But we know, we can destroy a contract to force ETH to an address: selfdestruct()
1 2 3 4 5 6 7 8 9 10 11
function collectPenalty() public { require(msg.sender == beneficiary);