{"id":13621158,"url":"https://github.com/tintinweb/solgrep","last_synced_at":"2026-04-01T20:43:07.862Z","repository":{"id":43338997,"uuid":"429887734","full_name":"tintinweb/solgrep","owner":"tintinweb","description":"🧠 A scriptable semantic grep utility for solidity","archived":false,"fork":false,"pushed_at":"2024-08-08T10:53:54.000Z","size":2101,"stargazers_count":144,"open_issues_count":3,"forks_count":15,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-02-15T16:40:32.562Z","etag":null,"topics":["grep","search","solidity"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/solgrep","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tintinweb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-19T17:51:25.000Z","updated_at":"2025-12-11T08:47:54.000Z","dependencies_parsed_at":"2024-10-23T02:50:50.118Z","dependency_job_id":null,"html_url":"https://github.com/tintinweb/solgrep","commit_stats":{"total_commits":54,"total_committers":2,"mean_commits":27.0,"dds":0.01851851851851849,"last_synced_commit":"0453d142a34c1467f3210c4fc3c650dcc65df7f9"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/tintinweb/solgrep","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tintinweb%2Fsolgrep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tintinweb%2Fsolgrep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tintinweb%2Fsolgrep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tintinweb%2Fsolgrep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tintinweb","download_url":"https://codeload.github.com/tintinweb/solgrep/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tintinweb%2Fsolgrep/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291777,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["grep","search","solidity"],"created_at":"2024-08-01T21:01:03.065Z","updated_at":"2026-04-01T20:43:07.841Z","avatar_url":"https://github.com/tintinweb.png","language":"JavaScript","funding_links":[],"categories":["Tools"],"sub_categories":[],"readme":"[\u003cimg width=\"200\" alt=\"get in touch with Consensys Diligence\" src=\"https://user-images.githubusercontent.com/2865694/56826101-91dcf380-685b-11e9-937c-af49c2510aa0.png\"\u003e](https://diligence.consensys.net)\u003cbr/\u003e\n\u003csup\u003e\n[[  🌐  ](https://diligence.consensys.net)  [  📩  ](https://github.com/ConsenSys/vscode-solidity-doppelganger/blob/master/mailto:diligence@consensys.net)  [  🔥  ](https://consensys.github.io/diligence/)]\n\u003c/sup\u003e\u003cbr/\u003e\u003cbr/\u003e\n\n\n## 🧠 SolGrep - A scriptable semantic grep utility for solidity\n\nSo you have a set of smart contracts and want to find all contracts that have a `public` method named `withdrawEth` but lexical grep yields a lot of false-positives? Here's where [solgrep](https://github.com/tintinweb/solgrep) can help! 🙌\n\n[💾](https://www.npmjs.com/package/solgrep) `npm install -g solgrep` \n\nSolgrep recursively finds smart contracts in a target directory, parses the source units to understand the language semantics, and makes this information available to a powerful javascript-based filter function. This way, you can:\n\n* extract semantic information from solidity source code based on custom filter functions\n* find target contracts based on a custom filter script you define\n* create \u0026 run your own or built-in rules (e.g. for CI checks)\n* crunch numbers and generate statistics from a code base\n* find doppelgangers! i.e. duplicate contracts sharing the same code structure (`AST_EXACT` and `AST_FUZZY` matching)\n\nProbably the most common way to use this tool is to run it with the `--find=\u003cjs-filter-statement\u003e` option, where `js-filter-statement` is a javascript one-liner that tells the engine what you are interested in. You either provide a statement that returns `boolean` (\"find mode\") or return information you want to extract (\"extract mode\").\n\n![solgrep2](https://user-images.githubusercontent.com/2865694/142903238-af9d2d11-81bb-430c-96dc-4118da89c90b.gif)\n\n⚠️ Make sure to only allow trusted inputs to `--find=\u003cjs-filter-statement\u003e` as this argument is being evaluated as javascript!\n\n⚠️ Check out the proper order for arguments when using `--find`, `--rule`. See [Usage](#usage).\n\n### Examples\n\nRun the default rules and display some stats?\n\n```javascript\n⇒  solgrep \u003cfolder\u003e \n```\n\nRun a specific or multiple built-in rules (`solgrep -l` to list available rules)? 👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --rule=IsInitializable --rule=Stats\n```\n\nYou want to find all source-units with a contract that has a function named `withdrawEth`? 👉 \n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"function.name=='withdrawEth'\" \n```\n\nDo the same thing but case-insensitive? 👉 \n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"function.name.toLowerCase()=='withdraweth'\" \n```\n\nFind all functions that call `selfdestruct`?  👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"function.callsTo('selfdestruct')\"\n```\n\nExctract all function names from all contracts? 👉 \n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"function.name\" \n```\n\nGet a list of all `external` functions? 👉 \n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"function.visibility.includes('external')\"  \n```\n\nFind `ERC777` contracts? 👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"contract.name=='ERC777'\" \n```\n\nExtract all Contract names? 👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"contract.name\"\n```\n\nExtract all Interface names? 👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"contract.name \u0026\u0026 contract.kind=='interface'\"\n```\n\nMatch against something in the `AST`? 👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"Object.keys(function.modifiers).includes('nonReentrant')\"\n```\n\nLexial match a functions source code?  👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --find=\"function.getSource().includes('hi')\"\n```\n\nFind duplicate contracts? (AST exact and fuzzy matching) 👉\n\n```javascript\n⇒  solgrep \u003cfolder\u003e --rule DupeFinder\n```\n\nUse option `--output=\u003coutput.json\u003e` to write all results to a file.\n\n### Built-In Keywords for `--find`\n\n* The `sourceUnit` object matches the source-file the engine is currently processing.\n* The `contract` object matches the contract the engine is currently processing.\n* The `function` object matches the function the engine is currently processing.\n\n#### Available Methos\n\nThe following methods are available:\n\n* `\u003csourceUnit|contract|function\u003e.getSource()` - provides access to the units source code\n* `\u003csourceUnit|contract|function\u003e.ast` - provides direct access to the [solidity-parser](https://github.com/solidity-parser/parser) AST\n* `function.callsTo('withdrawEth')` - find all functions in all contracts that call a method named `withdrawEth`\n* There's even more information easily available (functions/events/pragmas/etc.). Go check out the Solidity SourceUnit/Contract/Function [Wrapper Classes](https://github.com/tintinweb/solgrep/blob/master/src/solidity.js#L18) functionality (attribs/functions).\n\n\n#### Special Functions\n\nSpecial contract functions can be references as:\n\n*  `function.name == '__fallback__'`\n*  `function.name == '__receiveEther__'`\n*  `function.name == '__constructor__'`\n\n\n### Built-In Rules\n\n* `Stats` - collects stats about how many files, contracts, unique names, etc. were processed\n* `GenericGrep` - is the engine behind the `--find` feature\n* ...\n\n**SHARING IS CARING** - [submit your rules!](https://github.com/tintinweb/solgrep/pulls)\n\n\n## Usage\n\n```javascript\n\n⇒  solgrep --help\nUsage: solgrep \u003cfolder|...\u003e [options]\n\nOptions:\n  -r, --rule        Enable rules                           [array] [default: []]\n  -l, --list-rules  List available rules              [boolean] [default: false]\n  -f, --find        Find/Extract information using custom pattern\n                                                           [array] [default: []]\n  -o, --output      Write \"results\" as JSON to output file path.        [string]\n  -h, --help        Show help                                          [boolean]\n  -v, --version     Show version number                                [boolean]\n\n  ```\n\n⚠️ when using multi-options (`--find`, `--rule`) make sure to use this format:\n\n```\n⇒  solgrep \u003cfolder|...\u003e [options]\n```\n\nor\n\n```\n⇒  solgrep [options] -- \u003cfolder|...\u003e \n```\n\nor else additional options might be interpreted as additional `--find` options!\n\n## Library \n\n```javascript\nconst solgrep = require('solgrep');\n\nlet sg = new SolGrep('::memory::', rules, callbacks);\nsg.analyzeDir(\"/path/to/smart/contracts\").then(() =\u003e {\n    console.log(\"   ──────────────────────────── Results\")\n    console.log(sg.results)\n    console.log(\"   ────────────────────────────\")\n    sgrep.close();\n})\n\n\n```\n\n## Demo\n\nHere's an example that illustrates how to extract all function names from all `sourceUnits` and `contracts`.\n\n\n```javascript\n⇒  solgrep ../d0  --find='function.name' \n🧠 SolGrep v0.0.3 ready!\n\n  Enabled Modules:\n    ✔️ GenericGrep          _function.name\n\n[████████████████████████████████████████] 100% | 🕙 ETA: 0s | 5/5 | 🌲 389 | 🔥 0 | 🗂️  ../d0\n\n   ────────────────────────────\n{\n  '../d0/D0788Af7a613b81F437a51b96594A6387c7329b1_PendleLiquidityMiningBaseV2Multi.sol': [\n    {\n      rule: 'GenericGrep',\n      tag: 'match-function: PendleLiquidityMiningBaseV2Multi.__constructor__',\n      info: '__constructor__',\n      loc: [Object]\n    },\n    {\n      rule: 'GenericGrep',\n      tag: 'match-function: PendleLiquidityMiningBaseV2Multi.setUpEmergencyMode',\n      info: 'setUpEmergencyMode',\n      loc: [Object]\n    },\n...\n```\n\n#### Run default Rulesets\n\nIf you provide no configuration options it will take the default built-in grep rules and crunch numbers using the `stats` module.\n\n\n```javascript\n⇒  solgrep ../d6 \n🧠 SolGrep v0.0.1 starting ...\n\n\n  📁 ../d6\n ████████████████████████████████████████ 100% | ETA: 0s | 5/5\n\n   ──────────────────────────── Results\n{\n  '../d6/d60a598998ed27a7C54315F2675908B628E434B1_LiquidityPool.sol': [\n    {\n      rule: 'IsInitializable',\n      tag: 'INITIALIZEABLE',\n      info: 'initialize - public initialize function; likely proxy'\n    },\n    {\n      rule: 'IsInitializable',\n      tag: 'INITIALIZEABLE',\n      info: 'initialize - public initialize function; likely proxy'\n    }\n  ],\n  '../d6/d64E77C7C6A1dcC7e302F8fe31A22745e223c39c_MyStrategy.sol': [\n    {\n      rule: 'IsInitializable',\n      tag: 'INITIALIZEABLE',\n      info: 'initialize - public initialize function; likely proxy'\n    }\n  ],\n  undefined: [ { rule: 'Stats', tag: 'STATS', info: [Object] } ]\n}\n   ────────────────────────────\n{\n  sourceUnits: 4,\n  contracts: {\n    total: 13,\n    names: {\n      ERC20: 1,\n      StrategySushiEthMimLp: 1,\n      LiquidityPool: 1,\n      Getter: 1,\n      Governance: 1,\n      LibraryEvents: 1,\n      Perpetual: 1,\n      Storage: 1,\n      ArbiBoneman: 1,\n      ERC721: 1,\n      MyStrategy: 1,\n      PausableUpgradeable: 1,\n      SettAccessControl: 1\n    }\n  },\n  interfaces: {\n    total: 39,\n    names: {\n      IERC20: 1,\n      IJar: 1,\n      IStakingRewards: 1,\n      IStakingRewardsFactory: 1,\n      IMasterchef: 1,\n      UniswapRouterV2: 1,\n      IUniswapV2Pair: 1,\n      IUniswapV2Factory: 1,\n      IRewarder: 1,\n      IMiniChefV2: 1,\n      ILiquidityPool: 1,\n      IOracle: 1,\n      IAccessControl: 1,\n      IGovernor: 1,\n      IPoolCreatorFull: 1,\n      ISymbolService: 1,\n      IPoolCreator: 1,\n      ITracer: 1,\n      IVersionControl: 1,\n      IVariables: 1,\n      IKeeperWhitelist: 1,\n      IProxyAdmin: 1,\n      IDecimals: 1,\n      ILiquidityPoolGetter: 1,\n      ILiquidityPoolGovernance: 1,\n      IPerpetual: 1,\n      IERC721Enumerable: 1,\n      IERC721: 1,\n      IERC721Receiver: 1,\n      IERC721Metadata: 1,\n      IERC165: 1,\n      ICurveGauge: 1,\n      ICurveStableSwapREN: 1,\n      IUniswapRouterV2: 1,\n      IStrategy: 1,\n      IController: 2,\n      IERC20Upgradeable: 2\n    }\n  },\n  libraries: {\n    total: 31,\n    names: {\n      SafeMath: 1,\n      SafeERC20: 1,\n      BoringERC20: 1,\n      EnumerableSetUpgradeable: 1,\n      SafeCastUpgradeable: 1,\n      AMMModule: 1,\n      LiquidityPoolModule: 1,\n      PerpetualModule: 1,\n      SignedSafeMathUpgradeable: 1,\n      Constant: 1,\n      Math: 1,\n      SafeMathExt: 1,\n      Utils: 1,\n      MarginAccountModule: 1,\n      EnumerableSet: 1,\n      OrderData: 1,\n      CollateralModule: 1,\n      TradeModule: 1,\n      OrderModule: 1,\n      Signature: 1,\n      ECDSAUpgradeable: 1,\n      Strings: 1,\n      MathUpgradeable: 1,\n      Address: 2,\n      SafeMathUpgradeable: 2,\n      AddressUpgradeable: 2,\n      SafeERC20Upgradeable: 2\n    }\n  },\n  abstract: {\n    total: 13,\n    names: {\n      StrategyBase: 1,\n      StrategySushiFarmBase: 1,\n      ReentrancyGuardUpgradeable: 1,\n      ERC721Enumerable: 1,\n      Ownable: 1,\n      ERC165: 1,\n      BaseStrategy: 1,\n      Context: 2,\n      ContextUpgradeable: 2,\n      Initializable: 2\n    }\n  }\n}\nTOTAL FILES: 5\nERRORS: 1\n   ────────────────────────────\n\n\n\ncheers 🙌 \n    @tintinweb \n    ConsenSys Diligence @ https://consensys.net/diligence/\n    https://github.com/tintinweb/solgrep/ \n\n```\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftintinweb%2Fsolgrep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftintinweb%2Fsolgrep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftintinweb%2Fsolgrep/lists"}