向后兼容性

OpenZeppelin Contracts 使用语义化版本控制来传达其 API 和存储布局的向后兼容性。补丁和次要更新通常是向后兼容的,但以下详述的罕见情况除外。主要更新应假定与之前的版本不兼容。在此页面上,我们将提供有关这些保证的详细信息。

API

在向后兼容的版本中,所有更改都应该是内部实现细节的添加或修改。大多数代码应继续编译并按预期运行。此规则的例外情况如下所列。

安全性

极少数情况下,补丁或次要更新会以破坏性的方式删除或更改 API,但前提是之前的 API 被认为是不安全的。这些重大更改将在变更日志和发行说明中注明,并与安全公告一起发布。

草案或预定稿 ERC

非最终版本的 ERC 可能会以不兼容的方式更改。因此,我们避免在 ERC 最终确定之前发布其实现。对于已经发布了很长时间并且似乎不太可能更改的 ERC,我们做了一些例外。可能存在重大更改的 ERC 的实现在名为 draft-*.sol 的文件中发布,以明确该条件。 对于带有 draft 前缀的文件中的内容,没有向后兼容性保证。

在社区中已实现广泛采用且具有强大的向后兼容性期望的标准,可以被视为事实上的最终版本,并在不带 draft- 前缀的情况下发布,因为广泛的生态系统依赖使得重大更改极不可能发生。

虚拟和重写

这个库中的几乎所有函数都是 virtual 的,但也存在一些例外,但这并不意味着鼓励重写。有一部分函数被设计为可以重写。通过在此子集之外定义重写,您可能会依赖内部实现细节。我们努力在这种情况下保持向后兼容性,但这非常困难并且很容易意外破坏。建议谨慎。

此外,一些次要更新可能会导致新的 "两个或多个基类定义了具有相同名称和参数类型的函数" 或 "需要指定重写的合约" 之类的编译错误,这是由于 Solidity 认为继承函数存在歧义。这应该通过添加一个经由 super 调用该函数的 override 来解决。

有关 virtual 和 override 的更多信息,请参阅 扩展合约

结构体

带有下划线前缀的结构体成员应被视为“私有”,并且可能会在次要版本中中断。结构体数据应仅通过库函数访问和修改。

错误

除非另有说明,否则不应假定 revert 中包含的特定错误格式和数据是稳定的。

主要版本

主要版本应假定为不兼容。然而,如果合约的外部接口是标准化的,或者维护者认为更改它们会对生态系统造成重大压力,那么它们将保持兼容。

主要版本可能会破坏的一个重要方面是“升级兼容性”,特别是存储布局兼容性。从一个主要版本升级到另一个主要版本的活动合约永远是不安全的。

存储布局

次要和补丁更新始终保留存储布局兼容性。这意味着可以从一个次要版本升级到另一个次要版本的活动合约,而不会破坏存储布局。在某些情况下,升级时可能需要初始化新的状态变量,尽管我们预计这种情况不会频繁发生。

我们建议使用 OpenZeppelin Upgrades Plugins 或 CLI 来确保升级的存储布局安全性。

Solidity 版本

在次要和补丁更新中,编译合约所需的最低 Solidity 版本将保持不变。在次要版本中引入的新合约可能会使用较新的 Solidity 功能,并且需要更新版本的编译器。