Legoot合约研究笔记09--最终的合约设计文档

规划中项目需要实现avatar+虚拟服装,效果图如下。为了实现这些功能,必须按照之前的研究文章完成最终的合约设计,本文集中实现了的新合约= ERC721+ UUPS+ ERC3664。
  遇到到问题:主体合约编译后字节码超过24576字节数限制,精简代码函数也无法达到要求。
  解决方法:把主体合约拆分成两部分:core平台合约+avatar合约,这样core平台合约只负责组合拆分,降低了代码量。avtar合约作为纯粹的虚拟人合约,不具备拆分组合功能代码,也降低了代码量。
  最终结果:在Remix+Ganache环境中,使用代理模式顺利部署,完成avatar发行、组件发行、重复组合拆分、合约升级等测试。
1.系统概述
觅境项目智能合约是该项目的基石,设计一套功能完备、协议可靠的智能合约是NFT项目成功的先决条件,本文分析项目合约现状与不足,提出了新的架构方案,并实现了solidity代码,通过功能测试。
2.设计策略
2.1.背景
ERC20合约的代币是可分割的,最小精度一般是18位小数。对于每一个代币来说没有任何属性上的区别,简单地说就是每一个都一样。
ERC721合约代币是不可分割的,最小精度是1。每个代币都可以设置tokenURI,对应的属性都可以不一样,因此每个代币代表的物品都是独一无二的。必须一枚一枚的铸造,无法一次铸造多个。
ERC721代币代表的价值可能很大,实际应用场景中经常需要进行价值分割(例如一个代币表示一个价值高昂的瓷器就无法分割瓷器),这时就无法使用ERC721代币了,因此ERC1155应运而生。ERC1155合约的每个tokenID代表一种物品,而每个代币具备数量属性,可以分割价值了。在实际应用场景中,ERC1155经常代表着一定数量的一类物品,例如一种武器数量100件,可以一次铸造出来,每次可以转移1件。
ERC721代币的tokenId是不同的,每一个tokenID都代表一个NFT,天生是NFT的编号。ERC1155代币每一个tokenId代表着一类物品,该类有多个完全相同的物品,因此每件物品的tokenId相同,这样在藏品市场就无法给每件藏品不同的编号。
2.2.现状:
当前数藏项目的合约是ERC1155合约,并且以此为基础改造而来。设计思想是ERC1155合约兼容ERC721,可以支持单个或批量物品发布计划。
经过这5个月的使用,我感觉到几点情况变化:
(1)市场上数藏平台发布的藏品更多是ERC721合约,一般是每种藏品数量较少,很少出现藏品数量超过1000个的。例如字画玩偶类,单品数量只有几百个,虚拟时装类单品数量更少,通常1~10件。这样的话就可以直接用ERC721代替了,只需要设计一种批量铸造功能函数,就可以解决无法批量铸造的缺陷。
(2)市场上的合约一部分是无法升级的,一部分是支持UUPS代理模式(EIP1822定义了通用的可升级代理标准)。如果数藏平台的合约从一开始就支持可升级,以后就可以不断对合约功能进行改进,引入新功能或新数据。元宇宙到底会朝那个方向发展,NFT合约要朝那个方向进化都是说不清楚的,必须为未来做好升级准备。
(3)NFT属性也在进化中,在ERC3664协议中提出了6种属性扩展方案:可升级,可修改,可添加,可移除,可拆分,可组合。我们产品设计目标是虚拟时装可以穿戴在avatar虚拟人身上,形成整套穿搭风格,这样就要求avatar合约必须具备可组合可拆分功能,对应的时装饰品类合约也必须支持组合拆分功能。
(4)另外观察到的ERC3664合约都是针对ERC721升级而来,扩展属性方案已经覆盖了ERC1155的一个tokenId数量多个的特点。在UUPS升级模式中针对ERC721和ERC1155都有实现。
2.3.改进方向
经过思考,我确定虚拟人的重点功能是可组合可拆分,暂不考虑其他属性扩展功能。简明表达如下:
模块                  合约名称                           协议特点
拆分组合平台    MetaPortsCore                 ERC721 + ERC3664 + UUPS
虚拟人               MetaPortsAvatar              ERC721 + ISynthetic721 + UUPS
组件                  MetaPortsComponent      ERC721 + ISynthetic721 + UUPS
组件支持多种类型,使用MetaPortsComponent合约多次部署,设置不同的类型名称。
盲盒不再使用合约实现,采用应用层功能设计实现,开箱后使用虚拟人、组件合约铸造出来具体的NFT。
3.系统总体结构
合约设计方案经过了两个阶段。
阶段1:在开源的MetaCore合约基础上增加UUPS功能,难点是openzeppelin合约库变更为可升级合约库。设计方案是 主体是Avatar合约,可以组合拆分组件。功能编写完后在编译阶段报告合约编译后的字节码超过24576字节,编译失败。经过分析认为是主体Avatar合约功能太多,必须拆解成core+avatar两个合约分别功能。
阶段2:按照平台+虚拟人+组件思想设计方案。目标1是虚拟人和组件都是标准的721合约,必须支持接口ISynthetic721。目标2是平台是纯粹的组合拆分容器,抛弃其他属性扩展代码,尽可能的减少代码。
经过上述改动,终于把平台合约代码精简了,成功通过编译测试。
3.1.系统结构框图
合约的UML框架如下图:
3.2.功能清单
3.3.核心流程
3.3.1.平台合约初始化
为了节约合约代码空间,有一些数据设计代码变形成了外部调用函数,从构造函数中完成数据设置操作变成了部署后管理员手动调用,这样完成合约数据的初始化。
函数参数数据:
主要流程:
3.3.2.组合
组合操作流程:
3.3.3.分解
分解操作流程:
3.3.4.读取tokenURI
平台合约的读取tokenURI过程最复杂,合约内容组装出json数据直接返回,过程如下:
4.数据结构设计
合约数据结构略
MetaPortsCore主要数据结构:
// 定义枚举类型
    enum ComponentAttrID {
        ATTRID_AVATAR,
        ATTRID_BACKGROUND,
        ATTRID_HAIR,
        ATTRID_CAP,
        ATTRID_CLOTHING,
        ATTRID_TROUSER,
        ATTRID_SHOE,
        ATTRID_NECKLACE,
        ATTRID_EARRING,
        ATTRID_RING
    }      
    //属性映射关系name->attrId,用于根据属性名称查找属性id
mapping(string => ComponentAttrID) public _attrNameId;
ERC3664CrossSynthetic合约中的数据结构:
//定义组件数据结构
    struct SynthesizedToken {
        address token;   //组件合约地址
        address owner;   //所有者
        uint256 id;      //组件代币id
    }
    // mainToken => SynthesizedToken
    mapping(uint256 => SynthesizedToken[]) public synthesizedTokens;
MetaPortsAvatar合约中的数据结构:
//对象实例通用数据
    struct InstanceGenericData {
        string name;      // 组件名称
        string rare;      // 稀有度
        string imageURI;  // 图片链接
        string objURI;    // 3d模型链接
        bool   exist;     // 存在标记
    }
    // tokenId => InstanceData
    mapping(uint256 => InstanceGenericData) private _instanceGenericDatas;  //对象实例仓库
    //定义属性序号及名称
    string[] private attrNames;   
    //属性数据结构
    struct AttrData {
        string value;    //属性值
        string rare;     //稀有度
    }
    mapping(uint256 => AttrData[]) private _instanceAttrDatas;  //对象实例属性仓库
5.项目配置
5.1.配置说明
源代码在GieLab仓库:
合约目录:MetaPortsNFT/contract/
如果在node.js下编译部署,需要预先安装依赖的@openzeppelin可升级库,当前使用版本是4.8.0。单独安装命令:
npm install @openzeppelin/contracts-upgradeable
也可以直接执行:
npm install
5.2.部署说明
通过Remix环境直接编译部署,注意保存记录下各个代理合约地址。
---------------------END---------------

猜你喜欢

转载自blog.csdn.net/u012084827/article/details/127608613