当前位置:网站首页>钻石标准--Diamond Standard
钻石标准--Diamond Standard
2020-11-06 20:21:00 【怎当她临去时秋波那一转】
钻石标准主要是为了对应以太坊上智能合约大小24K字节的限制。同时也可以应用来处理智能合约的无缝升级问题。钻石合约是这样的一个合约:它将函数调用代理调用(delegatecall)到外部已经部署的合约。这样的外部已部署合约被称为钻石面(facets)
标准
钻石标准定义在EIP2535中。标准文本在这里。https://github.com/ethereum/EIPs/issues/2535
例子实现
概览
diamondCut 函数是用来合约升级的函数,可以增加,替代和删除钻石合约里的任意函数 。它接收一个bytes[]类型的参数输入,指明修改内部映射表所需要的方法-钻石面对。比如,调用diamondCut函数可以一次性在一个交易里增加2个新函数,替换3个函数并且删除4个函数。同时diamondCut函数可以触发事件,记录所有的增加,替换和删除。
放大镜(The Loupe)是用来查询钻石合约的内部状况。钻石合约提供4个函数来提供钻石合约当前存储的函数和钻石面。这些函数被统称为放大镜。所有的钻石合约都必须实现这些函数
例子解释
下面我们以diamond-1为例来说明
数据结构
在IDiamondCut.sol, 有如下的数据结构:
struct FacetCut {
address facetAddress; // 当前钻石面(Facet)的地址
FacetCutAction action; // 当前DiamondCut的操作,增删改查
bytes4[] functionSelectors; // 该钻石面(Facet)所支持的函数选择子的集合
}
在IFacet.sol, 有如下的数据结构:
struct Facet {
address facetAddress; // 本钻石面(Facet)地址
bytes4[] functionSelectors; // 本钻石面(Facet)所支持的函数选择子的集合
}
IDiamondLoupe.sol中定义了需要实现的4个函数:
/// @notice Gets all facet addresses and their four byte function selectors.
/// @return facets_ Facet
function facets() external view returns (Facet[] memory facets_);
/// @notice Gets all the function selectors supported by a specific facet.
/// @param _facet The facet address.
/// @return facetFunctionSelectors_
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
/// @notice Get all the facet addresses used by a diamond.
/// @return facetAddresses_
function facetAddresses() external view returns (address[] memory facetAddresses_);
/// @notice Gets the facet that supports the given selector.
/// @dev If facet is not found return address(0).
/// @param _functionSelector The function selector.
/// @return facetAddress_ The facet address.
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
在LibDiamond.sol中,定义了下面的数据结构
struct FacetAddressAndSelectorPosition {
address facetAddress;
uint16 selectorPosition;
}
struct DiamondStorage {
// function selector => facet address and selector position in selectors array
mapping(bytes4 => FacetAddressAndSelectorPosition) facetAddressAndSelectorPosition;
bytes4[] selectors;
mapping(bytes4 => bool) supportedInterfaces;
// owner of the contract
address contractOwner;
}
包装合约
Dianmond合约是标准的入口。Diamond合约中除了一些初始化的工作以外,最主要的下面的Proxy功能。
下面的程序要点:
- ds.slot是内联汇编,意思是获取状态变量ds的Slot(存储槽)位置。见https://solidity.readthedocs.io/en/v0.7.4/assembly.html
- 通过调用的传递过来的函数选择子获取facet的地址
- 通过Delegatecall汇编指令来调用相应钻石面(facet)里的函数
fallback() external payable {
LibDiamond.DiamondStorage storage ds;
bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
address facet = address(bytes20(ds.facetAddressAndSelectorPosition[msg.sig].facetAddress));
require(facet != address(0), "Diamond: Function does not exist");
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
参考文献
- https://medium.com/1milliondevs/new-storage-layout-for-proxy-contracts-and-diamonds-98d01d0eadb
- https://dev.to/mudgen/understanding-diamonds-on-ethereum-1fb
- https://learnblockchain.cn/article/1398
- https://naturaldao.io/collaboration/blog-cn/113-eip-2535%E5%8D%B3%E9%92%BB%E7%9F%B3%E6%A0%87%E5%87%86%E4%BB%8B%E7%BB%8D.html
- https://medium.com/1milliondevs/solidity-storage-layout-for-proxy-contracts-and-diamonds-c4f009b6903
- https://hiddentao.com/archives/2020/05/28/upgradeable-smart-contracts-using-diamond-standard
- https://hiddentao.com/archives/2019/10/03/upgradeable-smart-contracts-with-eternal-storage
- https://hiddentao.com/archives/2020/03/19/nested-delegate-call-in-solidity
- https://hiddentao.com/archives/2020/05/28/upgradeable-smart-contracts-using-diamond-standard
版权声明
本文为[怎当她临去时秋波那一转]所创,转载请带上原文链接,感谢
https://my.oschina.net/gavinzheng731/blog/4704491
边栏推荐
- 【快速因數分解】Pollard's Rho 演算法
- 使用Asponse.Words處理Word模板
- ETCD核心機制解析
- 中国提出的AI方法影响越来越大,天大等从大量文献中挖掘AI发展规律
- Don't go! Here is a note: picture and text to explain AQS, let's have a look at the source code of AQS (long text)
- 小白量化投资交易入门课(python入门金融分析)
- Swagger 3.0 天天刷屏,真的香嗎?
- WeihanLi.Npoi 1.11.0/1.12.0 Release Notes
- 人工智能学什么课程?它将替代人类工作?
- Network programming NiO: Bio and NiO
猜你喜欢
Aprelu: cross border application, adaptive relu | IEEE tie 2020 for machine fault detection
熬夜总结了报表自动化、数据可视化和挖掘的要点,和你想的不一样
Kitty中的动态线程池支持Nacos,Apollo多配置中心了
01 . Go语言的SSH远程终端及WebSocket
谁说Cat不能做链路跟踪的,给我站出来
DRF JWT authentication module and self customization
python 保存list数据
文本去重的技术方案讨论(一)
被老程式設計師壓榨怎麼辦?我不想辭職
Pattern matching: The gestalt approach一种序列的文本相似度方法
随机推荐
Menu permission control configuration of hub plug-in for azure Devops extension
谁说Cat不能做链路跟踪的,给我站出来
Dapr實現分散式有狀態服務的細節
03_ Detailed explanation and test of installation and configuration of Ubuntu Samba
(1)ASP.NET Core3.1 Ocelot介紹
简直骚操作,ThreadLocal还能当缓存用
mac 下常用快捷键,mac启动ftp
Aprelu: cross border application, adaptive relu | IEEE tie 2020 for machine fault detection
python过滤敏感词记录
JetCache埋点的骚操作,不服不行啊
读取、创建和运行多个文件的3个Python技巧
自然语言处理之命名实体识别-tanfordcorenlp-NER(一)
7.2.2 compressing static resources through gzipresourceresolver
哇,ElasticSearch多字段权重排序居然可以这么玩
神经网络简史
Microservices: how to solve the problem of link tracing
Electron应用使用electron-builder配合electron-updater实现自动更新
如果前端不使用SPA又能怎样?- Hacker News
WeihanLi.Npoi 1.11.0/1.12.0 Release Notes
怎么理解Python迭代器与生成器?