本文深入探讨了EIP-2535(Diamond标准)在区块链上创建模块化智能合约的原理与实践,介绍了其核心组件和特性,重点强调了智能合约的可升级性和模块化设计。通过一个实际操作示例,展示了如何使用Hardhat创建和部署基于Diamond标准的智能合约。
模块化智能合约系统允许在像以太坊这样的区块链平台上创建灵活且可扩展的去中心化应用 (DApps)。ERC-2535 支持创建模块化智能合约,使开发人员能够在部署后扩展和升级功能。
在本教程中,我们将深入探讨这个 Diamond 标准,解释其核心智能合约及其实际应用。让我们开始吧!
Nick Mudge 提出了 EIP-2535,引入了函数选择器、面和钻石合约的概念。该标准通过将合约细分为称为 Facets 的较小组件,彻底改变了智能合约架构,实现了模块化和可升级性。这些 Facets 为一个单一的智能合约实体(称为 Diamond)提供了专业化功能。使用 Solidity 的 delegateCall 函数,Diamond 合约可以从其 Facets 执行逻辑,允许开发人员轻松地添加、替换或移除功能,而不会影响整体合约。
对于那些对委托调用感到好奇的人,委托调用是 Solidity 中的一项特性,它允许一个合约从另一个合约调用函数,同时保持调用合约的数据存储。
现在,你可能在想,为什么叫“Diamond”?我们知道,Diamond 不仅仅是一块宝石,而是一种由许多面组成的复杂结构,每个面都对它的整体美丽和强度做出了贡献。同样,在智能合约的世界中,diamond 是一个由多个较小的合约(称为 facets)组成的单一合约。每个 facet 都有特定的目的或功能,就像钻石的每个面在其外观中发挥作用一样。
那么,Diamond 标准如何与传统的代理标准不同呢?与传统的代理标准不同,Diamond 标准提供无与伦比的模块化和灵活性,使智能合约开发能够无缝适应不断变化的需求,并简化管理流程。
此接口设定了对 facets 进行修改的规则。简单来说,它概述了如何在钻石合约中添加、替换或移除功能,确保修改过程中的一致性和清晰性。

interface IDiamond {
enum FacetCutAction {Add, Replace, Remove}
// Add=0, Replace=1, Remove=2
struct FacetCut {
address facetAddress;
FacetCutAction action;
bytes4[] functionSelectors;
}
event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
通过实现此接口,合约确保可以通过灵活和可升级的方式添加、替换或移除函数,来修改其功能。

interface IDiamondCut is IDiamond {
function diamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata
) external;
}
这是一个提供查看和检索钻石合约方面信息的方法的接口。它提供了一种探索和查询钻石合约的 facets 的方法,使开发人员能够理解其结构和可用功能。

interface IDiamondLoupe {
struct Facet {
address facetAddress;
bytes4[] functionSelectors;
}
function facets() external view returns (Facet[] memory facets_);
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
function facetAddresses() external view returns (address[] memory facetAddresses_);
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}
该库实现了遵循 Diamond 标准的钻石合约的存储管理,使开发人员能够轻松访问和操纵特定于钻石的存储变量。

library LibDiamond {
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");struct FacetAddressAndSelectorPosition {
address facetAddress;
uint16 selectorPosition;
}struct DiamondStorage {
// 函数选择器 => facet 地址和选择器在选择器数组中的位置
mapping(bytes4 => FacetAddressAndSelectorPosition) facetAddressAndSelectorPosition;
bytes4[] selectors;
mapping(bytes4 => bool) supportedInterfaces;
// 合约的所有者
address contractOwner;
}function diamondStorage() internal pure returns (DiamondStorage storage ds) {
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
}
}
以下是使用 Hardhat x BuildBear 创建简单的实现 Diamond 标准的逐步过程,它允许你创建自己的以主网为基础的私有测试网,并设置自己的原生和 ERC20 代币水龙头及区块链浏览器。

git clone https://github.com/sanamummer/diamond.git

cd diamond
npm install
npm run createTestnet
一旦测试网上线,RPC、浏览器和水龙头的详细信息将添加到 testnet.json
文件中。
我们将创建一个示例存储 facet,用于更新和返回消息字符串,这将帮助我们理解钻石的工作原理以及状态变量如何在钻石和其 facet 之间共享。
现在,在 facet 文件夹中创建一个新文件,命名为 Storage.sol,并将以下代码添加到其中。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Storage {
function getMessage() public view returns (string memory) {
return libStorage.getMessage();
}
function setMessage(string memory _newMsg) public {
libStorage.setMessage(_newMsg);
}
}
library libStorage {
bytes32 constant STORAGE_POSITION = keccak256("diamond.standard.storage");
struct MStorage {
string message;
}
function getMessage() internal view returns (string memory) {
return diamondStorage().message;
}
function setMessage(string memory _newMsg) internal {
diamondStorage().message = _newMsg;
}
function diamondStorage() internal pure returns (MStorage storage ds) {
bytes32 position = STORAGE_POSITION;
assembly {
ds.slot := position
}
}
}
npx hardhat run scripts/deploy.js
耶!我们的钻石合约已部署并在 etherscan 上验证,成功部署后你将获得如下输出。
现在请转到 testnet.json 获取重要的 URL,比如水龙头,或者直接通过浏览器 URL 进行导航。使用 BuildBear 水龙头为你的账户添加资金,并使用读写功能与合约进行交互。
Diamond 标准通过实现模块化和可升级性彻底改变了智能合约开发。它帮助开发人员在合约部署后添加新功能和修复错误。这在构建更加动态和适应性强的区块链解决方案方面迈出了重要的一步。
BuildBear 是一个专为 DApp 开发和测试而定制的平台。开发人员可以自由创建一个个性化的私有测试网沙箱,跨多个区块链网络。铸造无限的原生和 ERC20 代币的自由,加上 BuildBear 上快速的交易时间(不足 3 秒!),大大增强了 DApp 开发生命周期。该平台配备了旨在实时测试和调试的工具,确保开发人员能够毫不费力地跟踪复杂的区块链交易。
在以下平台与我们联系 Twitter | LinkedIn | Telegram | GitHub
作者:Sana
- 原文链接: medium.com/buildbear/a-h...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!