danogurtsov/dandelion
GitHub: danogurtsov/dandelion
dandelion 从链上地址出发,自动爬取并重建区块链协议的完整架构拓扑图,无需依赖源码仓库。
Stars: 0 | Forks: 0
dandelion
从地址重建协议的链上架构——而非从代码库。
研究一个协议通常从 GitHub repo 开始。但往往你手上只有**活动链上的一组 地址**——一次部署、一个未知的 fork,或者一个你想要了解的系统。 dandelion 直接从链上工作:给它一组地址,它就能解析其代码, 读取其**真实状态**,追踪其关联链接,对角色和资金流向进行分类,衡量合约的**实际使用情况**, 并生成一张有类型的 **architecture graph**——一份可用于构建你链上研究的机器可读协议拓扑图。 ``` addresses + chain ─▶ dandelion ─▶ ArchitectureGraph (JSON) nodes · proxies↔impl · roles & authorities · reserves & own tokens · clone-classes · cross-chain mirrors & peers · activity ``` 仅凭**单个 Aave v3 Pool 地址**,dandelion 就能自主爬取整个协议: addresses provider、configurator、oracle、ACL manager、rewards、treasury——以及每个 特定储备的 aToken / debt token / rate strategy,并将它们折叠为 clone-classes。无需提示,无需 repo。 ## 为什么优先从链上获取 - **无需 repo。**反编译的、Vyper 或未验证的 fork 都是第一等公民。 - **真实状态是答案的一部分。** *现在*谁是 admin、当前的参数、资金 存放在哪里——这通常是问题的核心,且在源码中是缺失的。 - **真实使用情况很重要。**近期的 transactions 和 traces 能将活跃组件与废弃 组件区分开来,并揭示实际的调用者和 admin 操作。 - **设计上追求广度包容。**只要一个合约可能属于该项目,它就会被爬取。 其扩张受限于真实结构(clone-collapse,浅层的外部边界),而从不 受限于任意的节点数量上限。 ## 安装 ``` git clone https://github.com/danogurtsov/dandelion cd dandelion pip install -e ".[dev]" ``` ## 用法 ``` # 从一个或多个 seed 地址映射 protocol dandelion map 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2 \ --chain 1 --rpc https://eth.drpc.org --out aave.graph.json # 强制关闭 Etherscan source 步骤(无 key:仅 Sourcify + Blockscout) dandelion map 0xADDR --chain 1 --rpc $RPC --no-etherscan # 添加 LLM reasoning loop(propose reads → probe deterministically → expand) dandelion map 0xADDR --chain 1 --rpc $RPC --enrich --llm anthropic:claude-sonnet-5 ``` 或从 Python 调用: ``` import asyncio from dandelion.adapters.rpc.jsonrpc import JsonRpcClient from dandelion.adapters.sources.ladder import default_ladder from dandelion.services.reconstruct import reconstruct async def main(): rpc = JsonRpcClient(rpc_urls={1: "https://eth.drpc.org"}) graph = await reconstruct([(1, "0x8787...4E2")], rpc, source=default_ladder()) print(graph.summary()) graph.to_json() # the machine-readable map your research builds on asyncio.run(main()) ``` ## 你将得到什么:architecture graph - **nodes** —— 每个合约都包含代码、source tier、proxy kind、implementation、admin、 codehash、类型(token / pool / vault / router / factory / oracle / governance / timelock / multisig)、roles、关键状态,以及一个 **membership** 判定(member / candidate / external)。 - **token roles** —— 每个 token 都会被分类:`own`(项目发行的:aTokens、debt tokens、 governance / LP),`reserved`(协议托管的资产——接受的存款列表),或 `transient`(仅在流向中被观测到)。 - **edges** —— `is_proxy_for`、`holds_role_over`、`depends_on`、`created_by`、`calls`、 `mirrors_deployment`(跨链)、`peer_of`(LayerZero)。 - **clone_classes** —— 数以千计的相同实例被折叠为一个类(logic identity + 样本上限),绝不进行全量爬取。 - **logical entities** —— 无地址的市场状态(例如 Morpho Blue markets)被捕获 为其真实依赖项的 hyperedges。 ## 工作原理 一个确定性 ↔ LLM 循环,广度优先,完全异步: 1. **Resolve** —— 获取代码,检测 proxy 模式(EIP-1967 / 1822 / 1167 / beacon / diamond / ZeppelinOS),通过 bytecode selectors 进行类型分类,并通过 source ladder 解析 name/ABI(**Etherscan V2 → Sourcify → Blockscout → Heimdall decompile**)。 2. **Expand** —— 确定性地遵循项目自身的结构: - **按目的进行 getter 扩展** —— 结构性 getter(`ADDRESSES_PROVIDER()`, `getACLManager()`)进行深度爬取并赋予 membership;资产 getter(`getReservesList()`) 将预留的外部资产进行标记,而不会递归进入它们的领域; - **推测性探测** —— 即使没有 ABI 也能读取 struct getter(适用于 仅包含 bytecode 的链和异构链); - **基于 reserve-keyed 的扩展** —— 对储备列表执行 `getReserveData(asset)` 会提取出每个 aToken / debt token / rate strategy(可推广至 Compound、Euler、Morpho); - **factory 与 singleton 事件** —— `Create*` 日志枚举实例;hot singletons 通过 topic 过滤的日志读取; - **diamond facets、role hubs、deployer siblings、cross-chain mirrors & LayerZero peers。** 3. **基于控制的 Membership** —— 项目的权限机构(admins、role holders、timelocks、 multisigs)和部署者构成了一个迭代闭包的集合:member 自身的权限机构会 拉取下一个合约。单纯的引用(pool 读取的外部 oracle)将保持为 external。 4. **Reason(可选)** —— LLM 查看图谱,提议接下来执行的读取操作,随后 确定性层执行这些操作并合并结果——直到最终收敛。 图谱结构始终是**确定性事实**;LLM 仅负责提议探索方向。它是 **model-agnostic** 的——任何兼容 OpenAI 的密钥(DeepSeek、OpenAI、OpenRouter、Groq)或 Anthropic 密钥 / Claude 订阅都可以接入同一个端口。 ## 架构 六边形架构(ports & adapters)。一个纯 `domain/` 核心——包含 graph model、proxy detection、membership、 clone collapsing、token taxonomy——仅依赖标准库,且无需网络即可进行单元测试。所有 外部交互都位于 `ports/` 之后,配有可替换的 `adapters/`(RPC、source resolvers、activity/trace providers、LLM)。 ``` src/dandelion/ ├── domain/ pure logic: models · proxies · classify · membership · clones · getters · tokens · … ├── ports/ protocols: RpcPort · SourceResolverPort · ActivityPort · LlmPort ├── adapters/ rpc (JSON-RPC) · sources (etherscan/sourcify/blockscout/heimdall) · activity · llm ├── services/ reconstruct (the crawl) · probes · enrich (the reasoning loop) └── cli.py `dandelion map …` ``` ## 开发 ``` pytest # 106 unit tests, no network required ruff check . # lint mypy src # types ``` `evals/` 测试工具包会针对活动的 RPC 重放 golden fixtures,并对 proxy resolution、 naming、node recall、mirror coverage 和 clone collapse 在一组真实协议 (Aave、Fluid、Morpho、Velodrome、deBridge、Liquity、GMX、mETH)上进行评分。 ## 许可证 [MIT](LICENSE)标签:Petitpotam, Python, Web3, 区块链, 无后门, 智能合约, 架构分析, 逆向工具