安全与风控
用 OpenZeppelin 库开发安全智能合约时…
在现有或新建合约中集成 OpenZeppelin 组件(代币标准、访问控制、安全原语、治理、账户)时,通过读源码发现集成模式并最小化改动地应用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
用 OpenZeppelin 库开发安全特定
解决思路
- 先判断请求类型:概念性问题(如“Ownable 如何工作”)只解释不生成代码;实现类请求才进入工作流。
- 生成代码或建议改动前,先用 Glob 搜索用户项目中的合约文件(如 **/*.sol、**/*.cairo、**/*.rs、**/*.move),并读取相关合约文件了解已有内容。
- 默认做集成而非替换:用户说“加暂停功能”或“改成可升级”时,是修改现有代码,不是重新生成;只有明确要求“从头开始”“替换这个”时才替换。
- 若文件读取失败,明确报告尝试的路径和失败原因,询问路径是否正确,绝不静默退回到通用回答。
- 写任何逻辑前先在 OpenZeppelin 库中搜索现成组件:完全匹配就直接 import 使用(继承、实现 trait、组合);接近匹配就 import 并扩展,只覆盖库标记为可覆盖的部分(virtual、hooks、可配置参数);都不匹配才写自定义逻辑,并先浏览库目录结构确认。
- 绝不把库源码复制或内嵌进用户合约,始终从依赖 import,以便获得安全更新;不要手写库已提供的东西(如已有 Pausable/ERC20Pausable 就不要自写 paused 修饰符,已有 Ownable 就不要写 require(msg.sender == owner),基类已处理 ERC165 就不要自己实现)。
- 采用“从库源码发现模式”的方法:查看项目已 import 的内容,读取已安装依赖的源码和文档,识别依赖要求的函数、修饰符、hooks 和存储,再应用到用户合约。
- 用 npx @openzeppelin/contracts-cli 生成参考实现辅助发现模式:生成基线到文件、生成启用某特性的版本到另一文件、diff 两者,再把差异应用到用户代码;CLI 输出是正确集成的权威来源。
- 若没有对应 CLI 命令,使用通用模式发现方法;没有 CLI 命令不代表库不支持,只代表没有生成器。
- 步骤1:搜索项目合约文件,读取现有合约的 import/use 语句识别已用的 OpenZeppelin 组件,在依赖树中定位已安装依赖(Solidity 在 node_modules/@openzeppelin/contracts/ 或 lib/openzeppelin-contracts/;Cairo 从 Scarb.toml 解析;Stylus/Stellar 从 Cargo.toml 解析,源码在 target/ 或 ~/.cargo/registry/src/;Sui Move 从 Move.toml 解析,构建后缓存在 ~/.move/ 及 build/<project_package>/sources/dependencies/<move_package_name>/)。
- 步骤1续:用 Glob 浏览依赖目录列表发现可用组件(如 node_modules/@openzeppelin/contracts/**/*.sol),不要凭记忆假设库内容,始终列目录验证;依赖未本地安装时克隆或浏览规范仓库。
- 步骤2:读取相关组件源码,查找源码内文档(Solidity 的 NatSpec /// 和 /** */、Rust 和 Cairo 的 /// 文档注释、组件目录的 README),用决策树确定集成策略,识别公开 API(暴露的函数/方法、事件、错误)。
- 步骤2续:识别集成要求——必须实现的函数(抽象函数、trait 方法、hooks)、必须加到集成方函数上的修饰符/装饰器/守卫、必须传入的构造函数或初始化参数、必须声明的存储变量或状态、必须的继承或 trait 实现(始终通过 import 而非复制);并在同仓库的 test/、tests/、examples/、mocks/ 目录搜索正确用法示例。
- 步骤3:提取最小集成模式——要加的 import/use 语句、要加的继承/trait 实现(始终从依赖 import)、要声明的存储、构造函数/初始化改动(新参数、初始化调用)、要加的新函数(必需的覆盖、hooks、公开 API)、要修改的现有函数(加修饰符、调用 hooks、发事件);若合约可升级,上述改动可能影响存储兼容性,应用前先查阅相关升级技能;不要包含依赖要求之外的任何东西。
- 步骤4:读取用户现有合约文件,用 Edit 工具应用步骤3的改动,不要替换整个文件而是集成进现有代码;检查冲突(重复的访问控制系统、冲突的函数覆盖、不兼容的继承)并在完成前解决;不要让用户自己改,直接应用。
- 按查找表定位各生态的仓库、文档、文件扩展名和依赖位置:Solidity 用 openzeppelin-contracts 仓库、docs.openzeppelin.com/contracts、.sol;Cairo 用 cairo-contracts、docs.openzeppelin.com/contracts-cairo、.cairo;Stylus 用 rust-contracts-stylus、docs.openzeppelin.com/contracts-stylus、.rs;Stellar 用 stellar-contracts、docs.openzeppelin.com/stellar-contracts、.rs;Sui Move 用 contracts-sui、docs.openzeppelin.com/contracts-sui、.move。
- 按目录结构约定先浏览对应路径找组件:代币在 Solidity contracts/token/{ERC20,ERC721,ERC1155}/、Cairo packages/token/、Stylus contracts/src/token/、Stellar packages/tokens/;访问控制在 contracts/access/、packages/access/、contracts/src/access/、packages/access/;治理在 contracts/governance/、packages/governance/、Stellar packages/governance/;代理/升级在 contracts/proxy/、packages/upgrades/、contracts/src/proxy/、packages/contract-utils/;工具/安全在 contracts/utils/、packages/utils/ 和 packages/security/、contracts/src/utils/、packages/contract-utils/;账户在 contracts/account/、packages/account/、Stellar packages/accounts/。
- Sui Move 不在固定网格中且没有 @openzeppelin/contracts-cli 生成器,始终用模式发现方法:以包的 examples/ 作为规范集成配方,通过 MVR import 而非复制源码;从库自身元数据(起点为 llms.txt)发现包集合、组合与风格约定、确切 API 和工具链;完整安装、依赖、--build-env 构建和质量门流程见 setup-sui-contracts 技能。
- 不要凭旧知识假设覆盖点,始终读已安装源码验证:旧版本中 virtual 的函数在当前版本可能不再可覆盖,源码 NatSpec 会指出正确覆盖点(如 NOTE: This function is not virtual, {X} should be overridden instead);已知例子是 Solidity ERC-20 转账 hook 在 v4 和 v5 之间变化,推荐覆盖前先读已安装的 ERC20.sol 确认哪个函数是 virtual。
- 用 CLI 生成器时先运行 npx @openzeppelin/contracts-cli --help 列出可用命令(每个命令对应一种合约类型,如 solidity-erc20、cairo-erc721、stellar-fungible),再运行 npx @openzeppelin/contracts-cli <command> --help 查看选项;不要依赖旧知识,对话开始时先查 --help,因为 CLI 可能已更新。
- 用生成-比较-应用流程把生成的合约代码挡在对话上下文之外:1)只带必需选项、关闭所有特性生成基线并管道到文件(npx @openzeppelin/contracts-cli solidity-erc20 --name MyToken --symbol MTK > /tmp/oz-baseline.sol);2)启用特性再生成到第二个文件(npx @openzeppelin/contracts-cli solidity-erc20 --name MyToken --symbol MTK --pausable > /tmp/oz-variant.sol);3)diff 两个文件找出确切变化(imports、继承、状态、构造函数、函数、修饰符)(diff /tmp/oz-baseline.sol /tmp/oz-variant.sol);4)编辑用户现有合约加入发现的改动;对相互影响的特性(如访问控制+可升级性)也生成组合变体。
- 当 CLI 命令存在但未暴露某特性的选项时不要止步,对该特性回退到模式发现:读已安装库源码找到相关组件,提取集成要求并应用到用户合约。
- 若合约可升级,应用任何改动前先查阅相关升级技能以评估存储兼容性影响。
适用边界 · 注意事项
- 概念性提问(如“Ownable 如何工作”)不需要生成代码,只做解释。
- 用户明确要求“从头开始”或“替换这个”时才替换现有合约,否则默认集成而非替换。
- 没有对应 CLI 命令或 CLI 未暴露某特性选项时,不要认为库不支持,应回退到模式发现方法而非放弃。