从ERC-20到ERC-3525,浅谈标准代币合约的用例和发展

引言

相信大家一定都对代币和NFT非常熟悉了,也知道它们背后的经典代币标准,如ERC-20和ERC-721等。ERC-20是同质化代币,而ERC-721是非同质化的,非常适合用于艺术品或者具备稀缺性的资产。但是这些代币是如何实现的呢?为什么就能适合于相关的应用呢?

这篇文章就带大家来盘点一下这些代币合约的原理、适用范围以及未来的发展趋势,涵盖标准包括ERC-20、ERC-721、ERC-1155以及最近通过的ERC-3525。

(参考的ERC-20、ERC-721、ERC-1155代码来自OpenZeppelin,ERC-3525代币来自Solv Protocol)

哈希表

在了解代币合约的原理之前,首先要了解其中一个重要的概念——哈希表(Mapping),简单来说它是一种可以利用关键词(Key)快速查找值(Value)的映射数据结构。代币合约利用哈希表来储存资产信息、被授权人信息等。具体哈希表介绍可以看这里: https://en.wikipedia.org/wiki/Hash_table

Data Hashing & 功能

代币都有自己的Data Hashing的方式,这个方式会决定代币功能,可以理解为代币的资产构造以及记录的方式。Data Hashing按目的可以分为总体账号以及个体账号。总体账号记录代币的整体资产情况(包括代币种类、个数和整体授权等等),同时也有被授权人/管理人的设置(被授权人自由传输/再授权资产拥有者的资产)。

功能指的是基于代币的Data Hashing设计,代币的一些可实现功能(即public函数),其中包括资产的查询传输、铸造销毁等。

下文将会用这两个方面对各类型的代币标准进行盘点。

ERC-20

1. Data Hashing

总体账户:ERC-20通过一个哈希表来管理和记录代币总体的资产,其中Key是用户地址,映射的Value是正整数用以记录每个地址拥有代币的个数。

个体账户:ERC-20由于本身的简单性,一个记录总体的哈希表即可记录资产的数量,所以仅需要一个登记个人账户被授权人的表即可。这个表是一个以单个地址为Key映射另一个以地址为Key正整数为目标的表:

Mapping(address => (Mapping(address => unit 256))

举例来说,对于代币A下的一个账户,举例0x1,该地址是可以授权别的账户(如0x2,0x3)来代为使用自己的代币的。额度的授权只能由账户本身(即0x1)发起才能生效。

2. 功能(基础版)

ERC-20标准基本满足了流通货币、股权和大宗商品等概念的代币所需要的条件,而且简单好用。

ERC-721

1. Data Hashing

总体账户:

这个表是把正整数映射给地址,即理解为id为Key,地址为Value,一个id能且只能对应一个地址。这实现了NFT的独一性以及稀缺性。

个体账户:

对比ERC-20的一个表记录所有地址的资产数额,721增加了个体账户资产记录的表,这个表以个人地址为Key,个人地址拥有的NFT数量为Value,记录了地址拥有总的NFT的个数;但是并没有记录个体账户拥有NFT的具体ID,这只能通过event查询。

被授权人授权方面,个人账户有一个整体被授权人,这个被授权地址可以操作该地址在账户中所有的该合约代币。授权人只能是个人地址本身。

另一方面,单独id的NFT也可以被独立授权,被授权人可以操作该id的NFT。授权人可以是整体被授权人或者NFT拥有者本身。

总的来说,个人地址的被授权人可以有无数个,而且他们可以更改个人地址所有的id被授权人地址,而个体id的被授权人地址只能有一个。

举个例子来说,0x1拥有某系列3个NFT,id分别是1,2,3。0x1可以把自己这个系列授权给无数个别的地址,比如它设置给了0x2,那么0x2就有资格传输1,2,3这个3个NFT,同时0x2也有资格把单个id,如1,的传输权授予给其他地址,如0x3。这时候0x3可以自由传输1这个id的NFT。

2. 功能

**721实现了数字艺术品的单一性和稀缺性,即一个id为一个藏品而且只能被一个地址拥有。**而收藏者也可以收藏一个系列的多个id,同时支持查看个数。然而可能考虑到gas的消耗,721合约并不支持单个地址的所有NFT id咨询,比如0x1持有了2个该系列的NFT,通过合约功能仅仅可以查到0x1有2个NFT,但是并不知道是哪两个。想知道0x1持有的具体NFT id,就只能通过合约的log/event去查找。

ERC-1155

1. Data Hashing

在ERC-1155里面,总体账户和个体账户同时实现。利用地址指向一个Mapping的Mapping完成了记录。

这里我们可以发现一个有趣的事实,就是1155的设计其实就是20和721的某种融合,可以理解为多个20标准和721标准(把数量设置为1地址只对应一个)的代币融合为一个整体的代币管理方案。

授权管理方面,没有了个体id的授权,只有个体账户的全部授权,可以简化授权的复杂度。

2. 功能

总结来说,我们发现**1155严格来说并不是某一个代币的标准,而是一个代币的管理集合。整体合约甚至没有Name或者Symbol,而且一个id允许被多个地址同时拥有,这让一个id可以选择拥有同质化或非同质化的性质。**使用场景是适用于有多代币需求的情况,比如游戏中道具实现,从非同质化金币或者材料,到独一性的神器都可以用一个1155合约解决。或者可用于一个比较小型的整体生态,比如DEX的LP Token集合等。

 

同时**由于有了数值的概念,如果设置一个id只有一个人拥有(可通过后续的合约实现),1155可以成为一个有数值概念的721(即Semi-Fungible Token的概念)。**这意味着它有了NFT的可更新性。比如信用方面可以更新用户信用分数,而且可以构建多信用行为体系,每个信用的方面都有一个数值等级。

 

不过笔者个人觉得由于它对于授权的管理过于简单(只有全部授权,没有单个id的授权,也没有额度的授权),并不适用于大生态的代币系统管理;而且也没有完整的个人账户记录,即通过个人地址作为Key去Map出全部的相关id的资产。这个也只能通过log/event读取。

ERC-3525

 

相比之下,这是一个复杂的合约,但是功能记录等都十分完善,可定制性也很高。

 

1. Data Hashing

 

总体账户:3525在这方面创新地先构建了一个取名TokenData的struct作为单个id的描述。不了解代码的同学可以把这个理解为一个id的描述小卡片。内容包括了:id、Slot(很重要,3525的一个核心创新)、在这个id之下的代币数量、所有人、id的被授权人(只有一个)、可以花费这个id余额的被授权地址。

有了这个小卡片,我们就可以把每个id的信息都记录下来。然后通过一个叫_allTokens的list把一张张的小卡片放进去保存起来。

_allTokens: [ TokenData, TokenData, TokenData............ ]

那当我们要取出查找我们想要看的小卡片的时候我们怎么定位呢?3525通过一个id到struct在list中的位置的映射完成。比如我们查到id 214的位置是在1,那么_allTokens[1]就可以拿出小卡片查看。_allTokens这个list记录了该3525的总体资产情况。

id授权方面添加了值的目标,即用id作为Key,标记了各个地址对于这个id的使用额度。

个人账户:3525对于个人账户构建了一个AddressData小卡片和一个哈希表来管理。小卡片内容包括拥有的Token的id的列表,拥有的id在总体账户list的位置的哈希表,账户的被授权人的哈希表。即小卡片实现了记录个人持有的id(每一个都记录)、以及账户被授权人。

后面再通过一个映射把个人地址作为Key去记录了对应的小卡片(AddressData)信息

Slot

整体来看,3525的数据记录非常全面,而且也很有条理。但是到目前为止,和1155相比,3525并无太大不同,只是记录更加完善而已。下面要讲讲Slot,这个放在id小卡片里面的一个变量,正是这个变量让3525高度可定制化,能做1155不能做的事情。

 

简单来说,Slot是一个Struct,和前面介绍的AddressData和TokenData一样。但是在3525中,Slot这个Struct是需要开发者自定义的,即开发者可以根据自己产品的需求,给Slot添加变量的数量和类型。以Solv Protocol的一个可转债类型债券作为例子,Slot可以包含的信息有到期时间(Maturity Date)、行权价格(Conversion Price)、以及行权价值(Convertible)。加上之前的ID(#6800)、Balance(2400 USDC)等变量,就构建出了一个可转债的NFT。

2. 功能

由于3525的记帐本身非常全面,所以其功能也非常多,想象空间大。其中关键的是实现了id数值的传输以及个人拥有的id之间的数值传输功能,这个实现可以让NFT有了更能多可能。

 

比如由于有id数值传输的功能,NFT可以更新自己的数值状态。对于信用、灵魂绑定类NFT来说,如果只是简单不可传输的721是不可以实现所有功能需求的。因为个人信用应该是一个动态的过程。这时候3525可以通过改变数值来反应个人信用的变化,又或者可以用于类似Uniswap V3那种NFT仓位中,可以让用户更方便地更新仓位大小。不过其实这个特性1155也可以实现,只要在1155中把每个id的拥有者设为只有一个地址上就行了(虽然在Data Hashing结构上不是,但是可以后期实现),这时候也可以传输/更新数值;而且1155设计更加简洁,甚至在多代币需求的场景下1155有更好的适用性。

 

**个人拥有的id之间的数值传输,这是3525在功能方面最大区别于1155和721的方面。**这个功能的用例可以在金融中。比如两个不同期限的交割合约的展期,又或者不同金融账号之间的切换等(如现货账户到期货账户的转换,类比CEX的设计)。这个时候每个id就是一个金融账号,用Slot记录账号信息,数值就是账号余额。又比如V3的Range管理(不仅仅是数值),通过Slot记录Range,个人想改变仓位Range的时候通过id到id的数值传输就可以做到。

 

3525也留下了一些小遗憾。比如,可能是出于重叠id的问题又或者是便于管理的考虑,3525不能自定义id的名字,只能从0开始逐步叠加,即每一个新的NFT的id只能是以【系列总数量+1】开始。再者,在一些extension中,3525虽然做了Slot的记录以及排序,但是缺少了基于Slot的id分类/查询。笔者觉得这在很多的产品设计中可能是一个重要的方向以及用例,比如债券类产品,它们通过Slot记录不同的债的信息然后发行,如果可以用Slot把相同的期限id债券分出,则可以构建更方便功能化的交易/管理等产品。目前这个目的只可以通过查询id的Slot信息,然后通过这个查询构建Slot和id的DB,又或者通过event和log构建去实现。

 

结语

 

总结来看,20、721、1155、3525都有自己独特的使用范例,项目方根据自己代币经济需求去选择最适合的。但是相比之下,新型的3525则是一个比前三者都复杂很多的合约,它不仅继承了前面3个标准的特性,还加入了独特的Slot数据结构,而这让它可以完成一些新的任务。此外,虽然3525功能变多了,但它依然保持记录的条理性,目前感觉是个不错的创新。但是由于更多元的信息记录,可以预见的是3525相对高额的gas成本,以及一些未知的漏洞攻击(毕竟未受到时间检验)。

Subscribe to ViaBTC Capital
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.