├── .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 |

4 | 5 | # Smashing Smart Contracts: Automated Vulnerability Detection and Exploitation 6 | 7 | In this workshop we'll practice hacking & exploitation of Solidity/EVM smart contracts. During the workshop we'll solve challenges from [CaptureTheEther](https://capturetheether.com) and [OpenZeppelin Ethernaut](https://ethernaut.openzeppelin.com) usign [Mythril](https://github.com/ConsenSys/mythril) and [Scrooge McEtherface](https://github.com/b-mueller/scrooge-mcetherface/) and do a little frontrunning exercise. The flattened source code for all challenges is available in the [code directory](./code). 8 | 9 | Check out the [DEF CON 27 writeup](https://github.com/b-mueller/smashing-smart-contracts/blob/master/DEFCON27-EVM-Smart-Contracts-Mueller-Luca.pdf) for some background. 10 | 11 | ## Preparation 12 | 13 | Here's how to get set up for the workshop. It should be super easy except if you're using Windows (you need Node.js and a Python 3 environment). 14 | 15 | If you run into insurmountable problems ask the instructors for help. There's also a dedicated [Discord channel](https://discord.gg/AQZu4jN) that we created exclusively for you, the valued workshop participant. 16 | 17 | ### Installing Ganache 18 | 19 | [Ganache](https://www.trufflesuite.com/ganache) is a local Ethereum development server. Install it with npm: 20 | 21 | ```console 22 | $ npm i -g ganache-cli 23 | ``` 24 | 25 | ### Installing Mythril (Vulnerability Detection) 26 | 27 | Install [Mythril](https://github.com/ConsenSys/mythril) from Pypi: 28 | 29 | ```bash 30 | $ pip3 install mythril 31 | ``` 32 | 33 | Make sure you have Mythril v0.21.15 or higher installed. 34 | 35 | ```bash 36 | $ myth version 37 | Mythril version v0.21.15 38 | ``` 39 | 40 | If you can't get this to work you can use the Docker image instead (see [docs](https://mythril-classic.readthedocs.io/en/master/installation.html), note however that the below tools won't work then. 41 | 42 | Mythril uses solc to compile Solidity files, so you'll need to [install that as well](https://solidity.readthedocs.io/en/latest/installing-solidity.html#binary-packages). 43 | 44 | ### Installing Scrooge McEtherface (Exploit Automation) 45 | 46 | To install Scrooge, clone the [Github repo](https://github.com/b-mueller/scrooge-mcetherface/) to install the required packages into a Python 3 environment: 47 | 48 | ``` 49 | $ git clone https://github.com/b-mueller/scrooge-mcetherface 50 | $ cd scrooge-mcetherface 51 | $ pip3 install -r requirements.txt 52 | ``` 53 | 54 | Setup `config.ini` for Ganache: 55 | 56 | ``` 57 | [settings] 58 | rpc = http://localhost:7545 59 | sender = 0xf4a60CbD6C43418c71389d8a0D98a9A356609761 60 | symbolic_tx_count = 3 61 | timeout = 300 62 | gasprice = 3000000000 63 | ``` 64 | 65 | ### Installing Theo (Frontrunning) 66 | 67 | Theo has a PyPI package: 68 | ```console 69 | $ pip install --user theo --upgrade 70 | ``` 71 | 72 | Or you can just clone the repo and install it: 73 | ```console 74 | $ git clone https://github.com/cleanunicorn/theo 75 | $ cd theo 76 | $ pip install -e . 77 | ``` 78 | 79 | ## Workshop Content and Exercises 80 | 81 | ### Level 1: Capturing the Ether 82 | 83 | In the first example we'll focus on killing smart contracts as well as draining Ether from them. Here are a few hints: 84 | 85 | ``` 86 | $ myth analyze 87 | ``` 88 | 89 | For analysis of on-chain contracts use the `--rpc` and `-a` options. 90 | 91 | ``` 92 | $ myth analyze --rpc localhost:8545 -a
93 | $ myth analyze --rpc infura-ropsten -a
94 | ``` 95 | 96 | To run Scrooge McEtherface, set up Scrooge's `config.ini`, then run: 97 | 98 | ``` 99 | $ ./scrooge
100 | ``` 101 | 102 | **Target Contracts:** 103 | 104 | - [Guess the Random Number](https://github.com/ConsenSys/mythx-playground/blob/master/01_weak_random/RandomNumber.sol) - [Challenge on CTE](https://capturetheether.com/challenges/lotteries/guess-the-random-number/) 105 | - [Ethernaut Fallout](https://github.com/ConsenSys/mythx-playground/blob/master/02_capturing_ether/ethernaut-fallout.sol) - [Challenge on Ethernaut](https://ethernaut.openzeppelin.com/level/0x220beee334f1c1f8078352d88bcc4e6165b792f6) 106 | - [Ethernaut Fallback](https://github.com/ConsenSys/mythx-playground/blob/master/02_capturing_ether/ethernaut-fallback.sol) - [Challenge on Ethernaut](https://ethernaut.openzeppelin.com/level/0x234094aac85628444a82dae0396c680974260be7) 107 | 108 | ### Level 2: Integer Arithmetics 109 | 110 | In the second example we'll again steal tokens and Ether, but this time with an integer arithmetics flavor. 111 | 112 | - [Ethernaut Token](https://github.com/ConsenSys/mythx-playground/blob/master/03_integer_arithmetics/ethernaut-token.sol) - [Challenge on Ethernaut](https://ethernaut.openzeppelin.com/level/0x6545df87f57d21cb096a0bfcc53a70464d062512) 113 | - [Tokensale on CaptureTheEther](https://github.com/ConsenSys/mythx-playground/blob/master/03_integer_arithmetics/cte-tokensale.sol) - [Challenge on CTE](https://capturetheether.com/challenges/math/token-sale/) 114 | 115 | ### Level 3: Honeypot 116 | 117 | This time, we'll set up a honeypot for others to tap into ([VulnerableTwoStep](https://github.com/ConsenSys/mythx-playground/blob/master/06_frontrunning_honeypot/VulnerableTwoStep.sol)). 118 | 119 | To run Theo, start it with available arguments: 120 | ```console 121 | $ theo 122 | The account's private key (input hidden) 123 | > 124 | Contract to interact with 125 | > 0x1df62f291b2e969fb0849d99d9ce41e2f137006e 126 | Scanning for exploits in contract: 0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e 127 | Received an empty response from eth_getCode. Check the contract address and verify that you are on the correct chain. 128 | No exploits found. You're going to need to load some exploits. 129 | 130 | Tools available in the console: 131 | - `exploits` is an array of loaded exploits found by Mythril or read from a file 132 | - `w3` an initialized instance of web3py for the provided HTTP RPC endpoint 133 | - `dump()` writing a json representation of an object to a local file 134 | 135 | Check the readme for more info: 136 | https://github.com/cleanunicorn/theo 137 | 138 | Theo version v0.8.1. 139 | 140 | >>> 141 | 142 | ``` 143 | **Protip:** 144 | 145 | To be safe from frontrunning and errors, wrap your exploit into a wrapper that reverts the transaction if the attack fails: 146 | 147 | ``` 148 | contract Wrapper { 149 | 150 | _target = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa 151 | 152 | constructor(bytes memory _data) public payable { 153 | address proxy = address(this); 154 | uint256 start_balance = msg.sender.balance + proxy.balance; 155 | 156 | address(_target).call.value(msg.value)(_data); 157 | 158 | assert(msg.sender.balance + proxy.balance > start_balance); 159 | selfdestruct(msg.sender); 160 | } 161 | 162 | function() external payable {} 163 | } 164 | ``` 165 | 166 | ## CTF Challenges 167 | 168 | *Mainnet addresses will be announced at the workshop*. 169 | 170 | - 1. Long Range Replay - [ABI](https://github.com/ConsenSys/mythx-playground/blob/master/07_CTF/LongRageReplay.abi) 171 | - 2. YouToken - [ABI](https://github.com/ConsenSys/mythx-playground/blob/master/07_CTF/YouToken.abi) 172 | - 3. Rev Eng -[ABI](https://github.com/ConsenSys/mythx-playground/blob/master/07_CTF/RevEng.abi) 173 | 174 | ## Advanced Setup 175 | 176 | ### Running a Geth Light Client 177 | 178 | Most of the examples work with [Infura](https://www.infura.io), but if you want to use Scrooge McEtherface and do things in a block-chainy way you should run your own node. Syncing a full node can take a couple of days but you can set up a light client instead. Install [go-ethereum](https://github.com/ethereum/go-ethereum/wiki/Installing-Geth) and run: 179 | 180 | ``` 181 | geth --testnet --syncmode light --rpc 182 | ``` 183 | 184 | This should sync with the Ropsten network pretty quickly. You can now point Metamask and Scrooge to `Localhost 8545`. 185 | 186 | 187 | ### Getting Testnet ETH 188 | 189 | First, you need a web3 capable browser and some testnet ETH. You probably also have both, but if not, get [Metamask](https://metamask.io) and grab some ETH from the Ropsten faucets: 190 | 191 | - https://faucet.metamask.io/ 192 | - https://faucet.ropsten.be/ 193 | 194 | ## Troubleshooting 195 | 196 | ### openssl/aes.h: No such file or directory 197 | 198 | If you get this error, you need the libssl source libraries: 199 | 200 | ``` 201 | scrypt-1.2.1/libcperciva/crypto/crypto_aes.c:6:10: fatal error: openssl/aes.h: No such file or directory 202 | #include 203 | ^~~~~~~~~~~~~~~ 204 | compilation terminated. 205 | error: command 'x86_64-linux-gnu-gcc' failed with exit status 1 206 | 207 | ---------------------------------------- 208 | Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-5rl4ep94/scrypt/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-mnbzx9qe-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-5rl4ep94/scrypt/ 209 | ``` 210 | 211 | On Ubuntu you can install them with: 212 | ```console 213 | $ sudo apt install libssl-dev 214 | ``` 215 | 216 | ### mythril - Solc has experienced a fatal error (code 1). 217 | 218 | This error may occur if the solidity compiler `solc` installed in path is incompatible with the provided source code (e.g. installed version is `0.5.x` but smart contract requires `<=0.4.x`) 219 | ``` 220 | $ myth analyze 221 | mythril.interfaces.cli [ERROR]: Solc has experienced a fatal error (code 1). 222 | code/RandomNumber.sol:8:1: Error: Source file requires different compiler version (current compiler is 0.5.3+commit.10d17f24.Darwin.appleclang - note that nightly builds are considered to be strictly less than the released version 223 | contract GuessTheRandomNumberChallenge { 224 | ^------^ 225 | SolidityVersionMismatch: Try adding the option "--solv " 226 | ``` 227 | 228 | There's a few options how to resolve this: 229 | 230 | * Either try using `--solv ` as suggested by mythrils error message 231 | * Or force mythril to use a user-provide `solc` binary to comiple the code as follows: 232 | 233 | ```console 234 | $ export SOLC=/usr/local/bin/solc-0.4.26 235 | $ myth analyze 236 | ``` 237 | 238 | [Solc releases](https://github.com/ethereum/solidity/releases) 239 | 240 | ## What to Do Next 241 | 242 | A great way to continue learning is playing challenges like [Capture the Ether](https://capturetheether.com), [Security Innovation CTF](https://blockchain-ctf.securityinnovation.com) and [Ethernaut](https://ethernaut.zeppelin.solutions). 243 | 244 | ## Credit 245 | 246 | Created by [ConsenSys Diligence](https://consensys.net/diligence/) and the [Mythril](https://mythril.ai) team. Special thanks to Mick Ayzenberg ([Security Innovation](https://www.securityinnovation.com)), [Trail of Bits](https://www.trailofbits.com), Steve Marx of [CaptureTheEther](https://capturetheether.com) and ConsenSys fame and [Zeppelin Solutions](https://zeppelin.solutions) for vulnerable contract samples and challenges. Also, kudos to the [Truffle](https://truffleframework.com) and [Guardrails](https://www.guardrails.io) teams for working with us on Mythril Platform integration. 247 | 248 | --------------------------------------------------------------------------------