从 ERC-20 到 ERC-3525,浅谈标准代币合约的用例和发展
ViaBTC Capital
2022-11-01 17:06
订阅此专栏
收藏此文章

引言

相信大家一定都对代币和 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 成本,以及一些未知的漏洞攻击(毕竟未受到时间检验)。

【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

ViaBTC Capital
数据请求中
查看更多

推荐专栏

数据请求中
在 App 打开