新闻详情

新闻详情

首页 / 资讯中心 / 详情

Foundry 修复 `forge bind` 对含 `$` 合约名的 panic:Solidity 与 Rust 标识符差异的工程化处理

发布时间:2026/9/16 19:40:51来源:尧图网络
Foundry 修复 `forge bind` 对含 `$` 合约名的 panic:Solidity 与 Rust 标识符差异的工程化处理
Foundry 修复forge bind对含$合约名的 panicSolidity 与 Rust 标识符差异的工程化处理【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry本篇文章围绕 Foundry 仓库中.changelog/fix-bind-dollar-sign-panic.md这条补丁记录展开深入讲解forge bind生成 Rust 绑定时的标识符清洗机制为什么 Solidity 合法的$字符会导致 panic、当前仓库中如何修复、以及如何用源码与测试验证这一行为。读完你可以掌握forge bind的完整参数用法、标识符清洗与校验的双层防线设计以及对应的回归测试写法。补丁记录原文与问题本质仓库根目录下的 .changelog/fix-bind-dollar-sign-panic.md 记录了这样一次修复Fixedforge bindpanicking on a contract name containing$, which is a legal Solidity identifier character but not a legal Rust one.问题的本质是两种语言在标识符identifier字符集上的差异Solidity 允许$在 Solidity 中$是合法的标识符字符因此合约可以命名为Foo$Bar、My$Contract等Rust 不允许$Rust 标识符只允许字母、数字、下划线以及 Unicode XID 字符$不是合法字符。forge bind的职责是把 Solidity 合约的 ABI 翻译成 Rust 绑定代码基于sol!宏合约名会直接成为 Rust 的模块名、类型名。一旦合约名含$生成的 Rust 代码就非法旧实现会直接 panic而不是给出可读的错误信息或自动清洗。修复的第一层防线入口处清洗标识符在 crates/forge/src/cmd/bind.rs 的get_json_files中forge bind枚举 artifacts 目录下的 ABI JSON 文件时会对合约名做“尽力而为的标识符清洗”let name stem.split(.).next().unwrap(); // Best effort identifier cleanup. let name name.replace(char::is_whitespace, ).replace([-, $], _);这段逻辑做了三件事stem.split(.).next()取文件主干名中第一个.之前的部分作为合约名应对Foo.sol/Foo.json这类结构replace(char::is_whitespace, )删除所有空白字符replace([-, $], _)把连字符-和美元符号$统一替换为下划线_。因此合约Foo$Bar在进入后续生成流程之前已经被改写成Foo_Bar从根源上避免了含$的名称流入代码生成器。值得注意的细节是清洗发生在读取文件名阶段这意味着即使是缓存路径、--skip-build场景下走cached_enum_definitions分支同样会经过这一清洗。修复的第二层防线代码生成器的防御性校验仅靠入口清洗并不足够稳妥——SolMacroGen可能被其他调用方直接使用。因此 crates/sol-macro-gen/src/sol_macro_gen.rs 在get_sol_input中增加了显式的合法性校验let name: syn::Ident syn::parse_str(self.name).wrap_err_with(|| { format!({} is not a valid Rust identifier for generated bindings, self.name) })?;它使用syn::parse_str::syn::Ident检查名称是否为合法 Rust 标识符若不是则返回带上下文的Err包含具体名称而不是 panic。这为修复提供了“即使有未清洗的$流入也只报错不崩溃”的兜底语义。同文件还包含一个针对此问题的单元测试 get_sol_input_rejects_invalid_identifier_instead_of_panicking#[test] fn get_sol_input_rejects_invalid_identifier_instead_of_panicking() { // $ is valid in Solidity identifiers but not Rust identifiers. let instance super::SolMacroGen::new(std::path::PathBuf::from(Foo.json), Foo$Bar.to_string()); assert!(instance.get_sol_input().is_err()); }测试名本身就点明了断言目标拒绝非法标识符而不是 panic。此外模块名的输出还有一层保护write_mod_namecrates/sol-macro-gen/src/sol_macro_gen.rs#L467-L474会先尝试把模块名解析为syn::Ident失败时自动用 Rust 原始标识符语法pub mod r#name;输出确保任何残留的非常规名称也不会生成出无法编译的lib.rs/mod.rs。回归测试端到端验证Foo$Bar修复之后crates/forge/tests/cli/bind.rs 新增了名为bind_dollar_sign_in_contract_name的回归测试完整模拟用户场景forgetest!(bind_dollar_sign_in_contract_name, |prj, cmd| { prj.add_source( Foo.sol, r# contract Foo$Bar { uint256 public value; function setValue(uint256 v) public { value v; } } #, ); cmd.args([bind]).assert_success(); let bindings_path prj.root().join(out/bindings); let binding fs::read_to_string(bindings_path.join(src/foo_bar.rs)).unwrap(); assert!(binding.contains(pub mod Foo_Bar), {binding}); assert!(!binding.contains($), {binding}); assert_bindings_compile(bindings_path); });该测试的断言链条完整覆盖了修复目标cmd.args([bind]).assert_success()命令不再 panic退出码为成功生成的绑定文件位于out/bindings/src/foo_bar.rsFoo$Bar清洗为Foo_Bar后再经to_snake_case()得到文件名foo_bar.rsbinding.contains(pub mod Foo_Bar)模块名正是清洗后的Foo_Bar!binding.contains($)生成产物中不再出现任何$字符assert_bindings_compile(bindings_path)生成的绑定可以真正通过cargo check --tests编译见 bindings_cargo证明产物是合法可用的 Rust 代码。forge bind实战参数与默认行为修复点位于forge bind的入口管线中理解该命令的参数有助于复现与验证。BindArgs定义在 crates/forge/src/cmd/bind.rs#L30-L123主要参数如下参数说明默认值--bindings-path PATH短参-b绑定产物输出目录out/bindings--select REGEX只为名称匹配该正则的合约生成绑定全部过滤默认排除项--select-all显式为所有合约生成绑定与--select/--skip冲突关--crate-name NAME生成的 Rust crate 名称foundry-contracts--crate-version VERSION生成的 crate 版本0.1.0--crate-description DESC写入package.description空--crate-license LICENSE写入package.license支持MIT、Apache-2.0等别名见 parse_license_alias空--module以模块mod.rs而非 crate 形式生成关--single-file所有绑定写入单个文件关--overwrite删除并重新生成已有绑定关默认只做一致性检查--skip-build跳过编译直接从缓存读取 ABI关--skip-cargo-toml跳过 Cargo.toml 一致性检查关--skip-extra-derives不追加额外的serde等 derive关run()方法crates/forge/src/cmd/bind.rs#L125-L166的执行流程为默认先执行项目编译除非--skip-build并收集 Solidity 枚举定义若绑定目录已存在且未传--overwrite则重新生成并做一致性检查文件内容、Cargo.toml 的 crate 名/版本/alloy 依赖见 check_consistency通过则输出OK.后退出否则删除旧目录按--module或 crate 模式调用 write_to_module / write_to_crate 生成绑定。默认的过滤规则会跳过Test/Script结尾的合约、console、Std*系列、Vm*以及IMulticall3等见 Filter::skip_default因此日常项目中测试合约不会污染绑定产物。修复的意义与验证路径该修复的价值体现在三个层面健壮性forge bind不再因合法的 Solidity 命名而崩溃。任何符合语言规范、但超出 Rust 标识符字符集的合约名都会被可靠清洗或明确报错可移植性含$的合约如链上命名风格特殊、或由代码生成器产出的合约也能被无缝集成到 Rust 工具链中产物通过cargo check验证可维护性单测与集成测试双重覆盖从 sol-macro-gen 单元测试到 CLI 回归测试任何后续改动破坏此行为都会立即被 CI 拦截。如果你在本地复现只需在任意 Foundry 项目中创建一个名为Foo$Bar的合约并运行forge bind然后检查out/bindings/src/foo_bar.rs中pub mod Foo_Bar的存在即可。同一目录下其他与forge bind相关的 changelog 条目如.changelog/parallel-forge-bind.md的并行生成优化、.changelog/forge-bind-enum-variants.md的枚举变体支持也从侧面说明标识符处理是绑定生成这一核心链路上持续演进的工程细节。【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ESP32音频abort残响根因与硬核静音方案 2026/9/16 21:05:26

ESP32音频abort残响根因与硬核静音方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
WeChatMsg:快速把微信聊天记录导出成永久文件,10分钟跑通第一次 2026/9/16 21:05:26

WeChatMsg:快速把微信聊天记录导出成永久文件,10分钟跑通第一次

WeChatMsg:快速把微信聊天记录导出成永久文件,10分钟跑通第一次 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitH…

阅读更多 →
SAP MD04库存/需求清单详解:从MRP逻辑到实操排查 2026/9/16 21:05:26

SAP MD04库存/需求清单详解:从MRP逻辑到实操排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
BBWEYY、餐宝盈、比文云选型,Codex 连上 TaoToken 后能直接出对照表 2026/9/16 21:05:26

BBWEYY、餐宝盈、比文云选型,Codex 连上 TaoToken 后能直接出对照表

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
CKEditor 5 Widget 内部机制深度剖析:type-around 功能的禁用之道与 `data-cke-ignore-events` 事件隔离 2026/9/16 21:05:25

CKEditor 5 Widget 内部机制深度剖析:type-around 功能的禁用之道与 `data-cke-ignore-events` 事件隔离

CKEditor 5 Widget 内部机制深度剖析:type-around 功能的禁用之道与 data-cke-ignore-events 事件隔离 【免费下载链接】ckeditor5 Powerful rich text editor framework with a modular architecture, modern integrations, and features like collaborative editi…

阅读更多 →
k-skill 的 hankookilbo-news 技能实战:无认证直连韩国日报官方 MCP 服务器查询新闻元数据 2026/9/16 21:02:25

k-skill 的 hankookilbo-news 技能实战:无认证直连韩国日报官方 MCP 服务器查询新闻元数据

k-skill 的 hankookilbo-news 技能实战:无认证直连韩国日报官方 MCP 服务器查询新闻元数据 【免费下载链接】k-skill 한국인을 위한 스킬 모음집 - 에이전트를 한국인으로 项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill 本指南围绕 k-skill 仓库…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞