├── .gitattributes ├── static └── smashing.png ├── code ├── VulnerableTwoStep.sol ├── RevEng.abi ├── Token.sol ├── RandomNumber.sol ├── LongRageReplay.abi ├── TokenSale.sol ├── YouToken.abi ├── Fallout.sol └── Fallback.sol └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity -------------------------------------------------------------------------------- /static/smashing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConsenSysDiligence/smashing-smart-contracts-workshop/HEAD/static/smashing.png -------------------------------------------------------------------------------- /code/VulnerableTwoStep.sol: -------------------------------------------------------------------------------- 1 | contract VulnerableTwoStep { 2 | address public player; 3 | address public owner; 4 | bool public claimed; 5 | 6 | constructor() public payable { 7 | owner = msg.sender; 8 | } 9 | 10 | function claimOwnership() public payable { 11 | require(msg.value == 0.1 ether); 12 | 13 | if (claimed == false) { 14 | player = msg.sender; 15 | claimed = true; 16 | } 17 | } 18 | 19 | function retrieve() public { 20 | require(msg.sender == player); 21 | 22 | msg.sender.transfer(address(this).balance); 23 | 24 | player = address(0); 25 | claimed = false; 26 | } 27 | } -------------------------------------------------------------------------------- /code/RevEng.abi: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "x", 7 | "type": "uint256" 8 | }, 9 | { 10 | "name": "y", 11 | "type": "int256" 12 | }, 13 | { 14 | "name": "z", 15 | "type": "bytes32" 16 | } 17 | ], 18 | "name": "die", 19 | "outputs": [], 20 | "payable": false, 21 | "stateMutability": "nonpayable", 22 | "type": "function" 23 | }, 24 | { 25 | "payable": true, 26 | "stateMutability": "payable", 27 | "type": "fallback" 28 | }, 29 | { 30 | "inputs": [ 31 | { 32 | "name": "secret", 33 | "type": "uint256" 34 | } 35 | ], 36 | "payable": true, 37 | "stateMutability": "payable", 38 | "type": "constructor" 39 | } 40 | ] 41 | -------------------------------------------------------------------------------- /code/Token.sol: -------------------------------------------------------------------------------- 1 | /* 2 | * @source: https://ethernaut.openzeppelin.com/level/0x6545df87f57d21cb096a0bfcc53a70464d062512 3 | * @author: Alejandro Santander (OpenZeppelin) 4 | */ 5 | 6 | pragma solidity ^0.5.0; 7 | 8 | contract Token { 9 | 10 | mapping(address => uint) balances; 11 | uint public totalSupply; 12 | 13 | constructor() public { 14 | balances[msg.sender] = totalSupply = 1000000000000; 15 | } 16 | 17 | function transfer(address _to, uint _value) public returns (bool) { 18 | require(balances[msg.sender] - _value >= 0); 19 | balances[msg.sender] -= _value; 20 | balances[_to] += _value; 21 | return true; 22 | } 23 | 24 | function balanceOf(address _owner) public view returns (uint balance) { 25 | return balances[_owner]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /code/RandomNumber.sol: -------------------------------------------------------------------------------- 1 | /* 2 | * @source: https://capturetheether.com/challenges/lotteries/guess-the-random-number/ 3 | * @author: Steve Marx 4 | */ 5 | 6 | pragma solidity ^0.4.21; 7 | 8 | contract GuessTheRandomNumberChallenge { 9 | uint8 private answer; 10 | 11 | function GuessTheRandomNumberChallenge() public payable { 12 | require(msg.value == 1 ether); 13 | answer = uint8(keccak256(block.blockhash(block.number - 1), now)); 14 | } 15 | 16 | function isComplete() public view returns (bool) { 17 | return address(this).balance == 0; 18 | } 19 | 20 | function guess(uint8 n) public payable { 21 | require(msg.value == 1 ether); 22 | 23 | if (n == answer) { 24 | msg.sender.transfer(2 ether); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /code/LongRageReplay.abi: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "guess", 7 | "type": "bytes" 8 | } 9 | ], 10 | "name": "guessHash", 11 | "outputs": [ 12 | { 13 | "name": "", 14 | "type": "bool" 15 | } 16 | ], 17 | "payable": false, 18 | "stateMutability": "nonpayable", 19 | "type": "function" 20 | }, 21 | { 22 | "constant": false, 23 | "inputs": [], 24 | "name": "myTurn", 25 | "outputs": [ 26 | { 27 | "name": "", 28 | "type": "bool" 29 | } 30 | ], 31 | "payable": true, 32 | "stateMutability": "payable", 33 | "type": "function" 34 | }, 35 | { 36 | "payable": true, 37 | "stateMutability": "payable", 38 | "type": "fallback" 39 | }, 40 | { 41 | "inputs": [], 42 | "payable": true, 43 | "stateMutability": "payable", 44 | "type": "constructor" 45 | } 46 | ] 47 | -------------------------------------------------------------------------------- /code/TokenSale.sol: -------------------------------------------------------------------------------- 1 | /* 2 | * @source: https://capturetheether.com/challenges/math/token-sale/ 3 | * @author: Steve Marx 4 | */ 5 | 6 | pragma solidity ^0.5.0; 7 | 8 | contract TokenSale { 9 | mapping(address => uint256) public balanceOf; 10 | uint256 constant PRICE_PER_TOKEN = 1 ether; 11 | 12 | constructor() public payable { 13 | require(msg.value == 1 ether); 14 | } 15 | 16 | function isComplete() public view returns (bool) { 17 | return address(this).balance < 1 ether; 18 | } 19 | 20 | function buy(uint256 numTokens) public payable { 21 | require(msg.value == numTokens * PRICE_PER_TOKEN); 22 | 23 | balanceOf[msg.sender] += numTokens; 24 | } 25 | 26 | function sell(uint256 numTokens) public { 27 | require(balanceOf[msg.sender] >= numTokens); 28 | 29 | balanceOf[msg.sender] -= numTokens; 30 | msg.sender.transfer(numTokens * PRICE_PER_TOKEN); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /code/YouToken.abi: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant": false, 4 | "inputs": [], 5 | "name": "createToken", 6 | "outputs": [ 7 | { 8 | "name": "newTokenContract", 9 | "type": "address" 10 | } 11 | ], 12 | "payable": false, 13 | "stateMutability": "nonpayable", 14 | "type": "function" 15 | }, 16 | { 17 | "constant": false, 18 | "inputs": [], 19 | "name": "deleteToken", 20 | "outputs": [], 21 | "payable": false, 22 | "stateMutability": "nonpayable", 23 | "type": "function" 24 | }, 25 | { 26 | "constant": false, 27 | "inputs": [ 28 | { 29 | "name": "recepient", 30 | "type": "address" 31 | } 32 | ], 33 | "name": "giveToken", 34 | "outputs": [], 35 | "payable": true, 36 | "stateMutability": "payable", 37 | "type": "function" 38 | }, 39 | { 40 | "constant": false, 41 | "inputs": [], 42 | "name": "loadFunds", 43 | "outputs": [], 44 | "payable": true, 45 | "stateMutability": "payable", 46 | "type": "function" 47 | }, 48 | { 49 | "constant": false, 50 | "inputs": [ 51 | { 52 | "name": "token", 53 | "type": "address" 54 | } 55 | ], 56 | "name": "registerToken", 57 | "outputs": [], 58 | "payable": false, 59 | "stateMutability": "nonpayable", 60 | "type": "function" 61 | }, 62 | { 63 | "constant": false, 64 | "inputs": [ 65 | { 66 | "name": "to", 67 | "type": "address" 68 | } 69 | ], 70 | "name": "transferToken", 71 | "outputs": [], 72 | "payable": false, 73 | "stateMutability": "nonpayable", 74 | "type": "function" 75 | }, 76 | { 77 | "inputs": [], 78 | "payable": true, 79 | "stateMutability": "payable", 80 | "type": "constructor" 81 | }, 82 | { 83 | "payable": true, 84 | "stateMutability": "payable", 85 | "type": "fallback" 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /code/Fallout.sol: -------------------------------------------------------------------------------- 1 | /* 2 | * @source: https://ethernaut.openzeppelin.com/level/0x234094aac85628444a82dae0396c680974260be7 3 | * @author: Alejandro Santander (OpenZeppelin) 4 | */ 5 | 6 | pragma solidity ^0.4.18; 7 | 8 | contract Ownable { 9 | address public owner; 10 | 11 | 12 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 13 | 14 | 15 | /** 16 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 17 | * account. 18 | */ 19 | function Ownable() public { 20 | owner = msg.sender; 21 | } 22 | 23 | 24 | /** 25 | * @dev Throws if called by any account other than the owner. 26 | */ 27 | modifier onlyOwner() { 28 | require(msg.sender == owner); 29 | _; 30 | } 31 | 32 | 33 | /** 34 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 35 | * @param newOwner The address to transfer ownership to. 36 | */ 37 | function transferOwnership(address newOwner) public onlyOwner { 38 | require(newOwner != address(0)); 39 | OwnershipTransferred(owner, newOwner); 40 | owner = newOwner; 41 | } 42 | 43 | } 44 | 45 | /** 46 | * @title SafeMath 47 | * @dev Math operations with safety checks that throw on error 48 | */ 49 | library SafeMath { 50 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 51 | if (a == 0) { 52 | return 0; 53 | } 54 | uint256 c = a * b; 55 | assert(c / a == b); 56 | return c; 57 | } 58 | 59 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 60 | // assert(b > 0); // Solidity automatically throws when dividing by 0 61 | uint256 c = a / b; 62 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 63 | return c; 64 | } 65 | 66 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 67 | assert(b <= a); 68 | return a - b; 69 | } 70 | 71 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 72 | uint256 c = a + b; 73 | assert(c >= a); 74 | return c; 75 | } 76 | } 77 | 78 | contract Fallout is Ownable { 79 | 80 | using SafeMath for uint256; 81 | mapping (address => uint) allocations; 82 | 83 | /* constructor */ 84 | function Fal1out() public payable { 85 | owner = msg.sender; 86 | allocations[owner] = msg.value; 87 | } 88 | 89 | function allocate() public payable { 90 | allocations[msg.sender] = allocations[msg.sender].add(msg.value); 91 | } 92 | 93 | function sendAllocation(address allocator) public { 94 | require(allocations[allocator] > 0); 95 | allocator.transfer(allocations[allocator]); 96 | } 97 | 98 | function collectAllocations() public onlyOwner { 99 | msg.sender.transfer(this.balance); 100 | } 101 | 102 | function allocatorBalance(address allocator) public view returns (uint) { 103 | return allocations[allocator]; 104 | } 105 | } -------------------------------------------------------------------------------- /code/Fallback.sol: -------------------------------------------------------------------------------- 1 | /* 2 | * @source: https://ethernaut.openzeppelin.com/level/0x234094aac85628444a82dae0396c680974260be7 3 | * @author: Alejandro Santander (OpenZeppelin) 4 | */ 5 | 6 | pragma solidity ^0.4.18; 7 | 8 | contract Ownable { 9 | address public owner; 10 | 11 | 12 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 13 | 14 | 15 | /** 16 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 17 | * account. 18 | */ 19 | function Ownable() public { 20 | owner = msg.sender; 21 | } 22 | 23 | 24 | /** 25 | * @dev Throws if called by any account other than the owner. 26 | */ 27 | modifier onlyOwner() { 28 | require(msg.sender == owner); 29 | _; 30 | } 31 | 32 | 33 | /** 34 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 35 | * @param newOwner The address to transfer ownership to. 36 | */ 37 | function transferOwnership(address newOwner) public onlyOwner { 38 | require(newOwner != address(0)); 39 | OwnershipTransferred(owner, newOwner); 40 | owner = newOwner; 41 | } 42 | 43 | } 44 | 45 | /** 46 | * @title SafeMath 47 | * @dev Math operations with safety checks that throw on error 48 | */ 49 | library SafeMath { 50 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 51 | if (a == 0) { 52 | return 0; 53 | } 54 | uint256 c = a * b; 55 | assert(c / a == b); 56 | return c; 57 | } 58 | 59 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 60 | // assert(b > 0); // Solidity automatically throws when dividing by 0 61 | uint256 c = a / b; 62 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 63 | return c; 64 | } 65 | 66 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 67 | assert(b <= a); 68 | return a - b; 69 | } 70 | 71 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 72 | uint256 c = a + b; 73 | assert(c >= a); 74 | return c; 75 | } 76 | } 77 | 78 | contract Fallback is Ownable { 79 | 80 | using SafeMath for uint256; 81 | mapping(address => uint) public contributions; 82 | 83 | function Fallback() public { 84 | contributions[msg.sender] = 1000 * (1 ether); 85 | } 86 | 87 | function contribute() public payable { 88 | require(msg.value < 0.001 ether); 89 | contributions[msg.sender] = contributions[msg.sender].add(msg.value); 90 | if(contributions[msg.sender] > contributions[owner]) { 91 | owner = msg.sender; 92 | } 93 | } 94 | 95 | function getContribution() public view returns (uint) { 96 | return contributions[msg.sender]; 97 | } 98 | 99 | function withdraw() public onlyOwner { 100 | owner.transfer(this.balance); 101 | } 102 | 103 | function() payable public { 104 | require(msg.value > 0 && contributions[msg.sender] > 0); 105 | owner = msg.sender; 106 | } 107 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |