Rug Pull 识别器
粘一段合约源码,检查 18 条典型跑路项目的写法。 它给的不是一个分数,而是带行号的证据—— 每条命中都指向源码里的具体位置,未命中的规则也全部列出来。 这样你既能知道「发现了什么」,也能知道「这次排除了什么」。
粘贴合约源码
只做静态模式匹配,不会执行代码、不会联网扫描在服务端完成,源码不出网、不入库,请求结束即丢弃。
这里检查的 18 类模式
全部规则都是从「历史上真实发生过损失的写法」里总结出来的。 下面这份目录在未扫描时也列出来,是为了让你知道:结论里的「没命中」 具体排除了什么,而不是一个笼统的「安全」。
- 严重任何人都能调用 mint 增发代币
- 高危Owner 保留增发权限
- 高危存在黑名单机制
- 中危~严重税率可以在部署后修改
- 中危交易由开关控制
- 中危存在单笔 / 单钱包限额
- 中危合约可以被暂停
- 高危没有 renounceOwnership,权限无法放弃
- 高危Owner 可以提取合约资金或改写关键地址
- 中危~严重tx.origin 被用于权限校验
- 高危~严重存在 selfdestruct
- 严重用区块变量生成随机数
- 高危存在外部调用且全合约没有重入锁
- 中危部分含外部调用的函数没有加 nonReentrant
- 中危底层调用的返回值没有被检查
- 提示合约逻辑可以升级
- 中危使用了内联汇编
- 严重转账逻辑对买卖方向做了区别对待
先说清它做不到的三件事
引擎是怎么判定的
三层结构。写在这里是因为「为什么有的规则我说它可能误报」这个问题, 答案就在第一层。
用等长空格而不是直接删掉,是为了保持行号不变——证据里那个行号要能对得上你编辑器里看到的那一行。 这一步不做的话,文档里写一句「这是个假 mint」就会被当成真实调用。
有了函数边界,规则才能问出「这个 mint 上面有没有权限修饰器」这种问题。 只在全文上做正则的话,一个合约里有 mint、另一个没有,是没法区分的。
判定权限用的是「修饰器定义体里有没有针对调用者身份的 require」, 而不是一份修饰器名字白名单—— 修饰器名是用户自定义的,onlyGovernor、governanceOnly、authGuard 全都合法, 白名单永远追不上,而漏认一个的代价是凭空造出一条严重级假警报。
规则库与前端目录共用同一份 id。如果引擎命中了目录里没有的规则, 结果区会显式提示「已检查 N 类这句话是不准的」, 而不是悄悄丢掉——前端说明落后于引擎时,这件事本身应该被看见。
为什么给 4 份样本,其中还有一份是「好」的
让人自己去找一段合约来粘,门槛太高,结果就是没人用。 所以给了可一键载入的样本。但只放反面教材会被理解成「有权限 = 恶意」—— 这是错的,于是第二份样本是同样拥有增发能力、但写法规范的对照。
每份样本的预期命中列表都是拿真实引擎跑出来校对过的, 不是手写的猜测;后端还有一份固定样本的回归测试, 断言每条证据的行号都大于 0。