Last active
July 6, 2023 21:10
-
-
Save chongkan/68c8b630d36b77f936c4687effcb97eb to your computer and use it in GitHub Desktop.
Smart Contract - Solidity - 7 Vulnerabilities.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Top 8 Scary Smart Contract Hacks They Use to Exploit Your DApp [+Video] | |
// https://blog.finxter.com/top-8-scary-smart-contract-hacks-that-exploit-your-dapp-video/ | |
/* | |
Ownership Exploit | |
Private Variable Exploit | |
Reentrancy Attack | |
tx.origin Phishing Attack | |
Denial of Service Attack | |
Storage Collision Attack | |
Randomness Attack | |
Replay Attack | |
*/ | |
// SPDX-License-Identifier: MIT | |
pragma solidity 0.8.9; | |
contract RealEstatePrice { | |
uint256 private apartmentPrice; // Changed visibility to private | |
address private owner; | |
mapping(address => uint256) private balances; // Mapping to track user balances | |
constructor(uint256 _price) { | |
apartmentPrice = _price; | |
owner = msg.sender; // Set the contract deployer as the initial owner | |
} | |
modifier onlyOwner() { | |
require(msg.sender == owner, "Only the contract owner can call this function."); | |
_; | |
} | |
modifier nonReentrant() { | |
require(balances[msg.sender] == 0, "Reentrancy attack detected."); | |
balances[msg.sender] = 1; | |
_; | |
balances[msg.sender] = 0; | |
} | |
// Getter function to retrieve the apartment price, preventing the Private Variable Exploit | |
function getApartmentPrice() external view returns (uint256) { | |
return apartmentPrice; | |
} | |
// Function to update the apartment price, only callable by the contract owner | |
function updateApartmentPrice(uint256 _price) external onlyOwner { | |
apartmentPrice = _price; | |
} | |
// Function to transfer ownership of the contract, only callable by the contract owner | |
function transferOwnership(address _newOwner) external onlyOwner { | |
require(_newOwner != address(0), "Invalid new owner address."); | |
owner = _newOwner; | |
} | |
// Function to withdraw funds while preventing a Reentrancy Attack | |
function withdrawFunds(uint256 _amount) external nonReentrant { | |
require(_amount <= address(this).balance, "Insufficient contract balance."); | |
balances[msg.sender] = 1; | |
payable(msg.sender).transfer(_amount); | |
balances[msg.sender] = 0; | |
} | |
// Function to prevent a tx.origin Phishing Attack | |
function checkOwner() external view returns (bool) { | |
return (msg.sender == tx.origin && msg.sender == owner); | |
} | |
// Function to prevent a Denial of Service Attack by utilizing gas stipend | |
function calculateGas() external pure returns (uint256) { | |
uint256 gasLimit = gasleft(); | |
return gasLimit; | |
} | |
// Function to prevent a Storage Collision Attack by using a mapping instead of an array | |
function storeData(uint256 _index, uint256 _data) external onlyOwner { | |
balances[msg.sender] = _data; | |
} | |
// Function to generate randomness using block information and user input | |
function generateRandomNumber(uint256 _userInput) external view returns (uint256) { | |
uint256 randomNumber = uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, _userInput))); | |
return (randomNumber % 100) + 1; | |
} | |
// Function to prevent a Replay Attack by including a nonce | |
function executeTransaction(address _destination, uint256 _value, bytes calldata _data, uint256 _nonce, bytes calldata _signature) external { | |
bytes32 message = keccak256(abi.encodePacked(_destination, _value, _data, _nonce)); | |
require(recoverSigner(message, _signature) == owner, "Invalid signature."); | |
// Execute the transaction | |
(bool success, ) = _destination.call{value: _value}(_data); | |
require(success, "Transaction execution failed."); | |
} | |
// Helper function to recover the signer address from a message and signature | |
function recoverSigner(bytes32 _message, bytes memory _signature) internal pure returns (address) { | |
require(_signature.length == 65, "Invalid signature length."); | |
bytes32 r; | |
bytes32 s; | |
uint8 v; | |
assembly { | |
r := mload(add(_signature, 32)) | |
s := mload(add(_signature, 64)) | |
v := byte(0, mload(add(_signature, 96))) | |
} | |
if (v < 27) { | |
v += 27; | |
} | |
require(v == 27 || v == 28, "Invalid signature value."); | |
return ecrecover(_message, v, r, s); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment