{"id":19340137,"url":"https://github.com/mrluit/selfdestruct-detect","last_synced_at":"2025-04-23T02:31:18.268Z","repository":{"id":34230436,"uuid":"172272418","full_name":"MrLuit/selfdestruct-detect","owner":"MrLuit","description":"Detect SELFDESTRUCT opcodes in EVM runtime bytecode","archived":false,"fork":false,"pushed_at":"2023-01-14T00:30:11.000Z","size":580,"stargazers_count":22,"open_issues_count":18,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-14T01:07:37.606Z","etag":null,"topics":["bytecode","create2","ethereum","evm","selfdestruct","solidity","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/selfdestruct-detect","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MrLuit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-23T22:48:03.000Z","updated_at":"2023-11-30T21:03:50.000Z","dependencies_parsed_at":"2023-01-15T05:27:12.663Z","dependency_job_id":null,"html_url":"https://github.com/MrLuit/selfdestruct-detect","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrLuit%2Fselfdestruct-detect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrLuit%2Fselfdestruct-detect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrLuit%2Fselfdestruct-detect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrLuit%2Fselfdestruct-detect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MrLuit","download_url":"https://codeload.github.com/MrLuit/selfdestruct-detect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250357620,"owners_count":21417315,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bytecode","create2","ethereum","evm","selfdestruct","solidity","typescript"],"created_at":"2024-11-10T03:25:14.679Z","updated_at":"2025-04-23T02:31:18.009Z","avatar_url":"https://github.com/MrLuit.png","language":"TypeScript","readme":"# EVM Selfdestruct Detection\n[![](https://img.shields.io/travis/com/MrLuit/selfdestruct-detect.svg?style=flat-square)](https://travis-ci.com/MrLuit/selfdestruct-detect)\n[![](https://img.shields.io/npm/v/selfdestruct-detect.svg?style=flat-square)](https://www.npmjs.com/package/selfdestruct-detect)\n[![](https://img.shields.io/david/MrLuit/selfdestruct-detect.svg?style=flat-square)](https://david-dm.org/MrLuit/selfdestruct-detect)\n[![](https://img.shields.io/github/license/MrLuit/selfdestruct-detect.svg?style=flat-square)](https://github.com/MrLuit/selfdestruct-detect/blob/master/LICENSE)\n    \nDetect the possibility of a self-destruction happening during the execution of an Ethereum smart contract by determining whether the runtime bytecode ran by the [Ethereum Virtual Machine](https://medium.com/@jeff.ethereum/optimising-the-ethereum-virtual-machine-58457e61ca15) contains a (possibly) reachable `SELFDESTRUCT` instruction.\n\n## Usage\n\n\u003e npm i selfdestruct-detect\n\n## How does it work?\nFirst of all, the application breaks down bytecode into its opcodes. Secondly, it loops over the opcodes, and skips over push data (if any). If it comes across a halting opcode (`STOP`, `RETURN`, `REVERT`, `INVALID`, `SELFDESTRUCT`), it will correctly assume all following opcodes are **unreachable**, until it can find a valid jump destination (`JUMPDEST`). While this method does prevent some false positives (like the [metadata hash](https://solidity.readthedocs.io/en/latest/metadata.html), included by the Solidity compiler), it will not detect whether code is unreachable due to exceptional halting, excluding halting due to the `INVALID` (`0xfe`) opcode.\n\n**Please note that this tool is unable to determine whether a contract will *actually* self destruct at any given time, it only detects whether it *might* be possible.**\n\n## Why is this useful?\nEthereum's Constantinople fork introduces a new opcode called [CREATE2](https://eips.ethereum.org/EIPS/eip-1014), which allows contracts to deploy other contracts at address `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]` (instead of the usual `keccak256(rlp([sender, nonce]))`). Unfortunetaly, including `keccak256(init_code)` in the address formula does not prevent contracts from redeploying different code at the same address. For example, `init_code` could essentially just be *\"call contract x for runtime bytecode\"* which would allow for `keccak256(initCode)` to stay the same, even if contract x decides to return different runtime bytecode.\n\nWhile there is no way to deploy code at an address which already exists in the state, contracts can remove themselves from the state by self-destructing (using the `SELFDESTRUCT` opcode), which would allow different code to be redeployed. Since (currently) there's no way of finding out whether a contract was deployed using `CREATE2`, a possible detection method for this attack vector would be to check whether the runtime bytecode contains a `SELFDESTRUCT` opcode. Interfaces which allow users to interact with Ethereum smart contracts can (and should!) implement this check to warn users when interacting with unstable smart contracts.\n\nRead more: [Potential security implications of CREATE2? (EIP-1014)](https://ethereum-magicians.org/t/potential-security-implications-of-create2-eip-1014/2614)\n\n## Example\n\n#### Node.js\n\n```javascript\nconst { mightSelfdestruct } = require(\"selfdestruct-detect\");\nconst Web3 = require('web3');\nconst web3 = new Web3(new Web3.providers.HttpProvider(\"https://api.mycryptoapi.com/eth\"));\nconst CryptoKitties = \"0x06012c8cf97BEaD5deAe237070F9587f8E7A266d\";\n\nweb3.eth.getCode(CryptoKitties).then(code =\u003e {\n    if(mightSelfdestruct(code)) {\n        console.log(\"Warning: CryptoKitties contract possibly contains a self-destruct method!\");\n    } else {\n        console.log(\"Success: CryptoKitties contract does not contain a reachable self-destruct instruction.\");\n    }\n});\n```\n\n#### Browser\n```javascript\nconst { mightSelfdestruct } = window.SelfdestructDetect;\nconst web3 = new Web3(new Web3.providers.HttpProvider(\"https://api.mycryptoapi.com/eth\"));\nconst DAI = \"0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359\";\n\nweb3.eth.getCode(DAI, function(err, code) {\n    if(err) throw err;\n    if(mightSelfdestruct(code)) {\n        console.log(\"Warning: DAI contract possibly contains a self-destruct method!\");\n    } else {\n        console.log(\"Success: DAI contract does not contain a reachable self-destruct instruction.\");\n    }\n});\n```\n\n## References\n- [EIP 1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014)\n- [Potential security implications of CREATE2? (EIP-1014)](https://ethereum-magicians.org/t/potential-security-implications-of-create2-eip-1014/2614)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrluit%2Fselfdestruct-detect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrluit%2Fselfdestruct-detect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrluit%2Fselfdestruct-detect/lists"}