在前两节的内容我们从交易开始认识比特币及以太坊的基础架构,随后介绍了以太坊智慧合约运作的概念。第三节我们将来回顾区块链「代币」演进的历史,并解析与之相关的技术。
既然要谈代币,就必须先厘清代币的定义。用比喻来说明的话,我们现实世界中有各国发行流通的法币,如:台币(NTD)、美金(USD)。然而,有些公司为了便于平台管理或流通便利性等因素,会发行在平台流通的「代币」,如:汤姆熊币、Line Points。
在区块链的世界里,其实也存在类似的概念,在公链上流通的加密货币如:比特币(BTC)、以太币(ETH),就像是各国的法币,普遍被称之为「协议代币」(在比特币/以太坊协议下流通的代币)。
然而,在以太坊上我们可以透过智慧合约客制化来创造出类似于代币性质的产物,可称之为「自定义代币」,透过智慧合约来赋予代币功能,类似我们传统上理解的代币。
「协议代币」与「自定义代币」我们都称为加密货币(Cryptocurrency)。而「协议代币」往往有自己的区块链或类似的分散式帐本技术,不需要任何其它区块链就能独立运作。而「自定义代币」则是利用现有的区块链(绝大多数是Ethereum),透过智慧合约或其它方式来发行及运行。
本文主要是以「自定义代币」为主题来介绍。
2017 年的ICO 浪潮开启了大发币时代,人人都能在以太坊区块链上发行自己的代币。但其实在以太坊上线之前便已有区块链代币(以下简称代币)的存在。
区块链代币的起源:染色币(Colored Coin)
代币的历史最早可以溯及到比特币上的染色币。但比特币没有智慧合约,要如何发币呢?当时铸造Token的做法是:我们把1 Satoshi (10^-8个Bitcoin)重新定义为1 USD。
如此一来,1 Bitcoin (100 Million Satoshi )的价值便变成了100M USD。然而这样的做法必须具有公信力,因此铸造的机构应该要抵押 100M的USD来担保这100M的Satoshi具有等值100M USD的价值(但没有机制保证铸造机构真的有抵押)。
于是我们会说这些比特币被染色了,因为它代表的不再是比特币的帐面价值,而被赋予了新的价值意义,只是这个Token 透过比特币的区块链网络来进行流通。我发送给你100 Satoshi,其实是发送给你100 USD。
但这100M的染色币要怎么跟其它比特币来区隔呢?于是许多铸造商会再利用一个比特币外部的帐本来追踪这100M Satoshi的交易纪录,如此来确认谁手上具有这些被「染色」的Satoshi,他们有权利可以用这些Satoshi兑换为美金。
此外,在比特币UTXO 的架构下,若是同时交易了染色币与比特币,该怎么区分哪些是有染色的Satoshi 呢?一种可能的做法是:一笔交易的Output 中在前的钱堆是染色币;在后的钱堆则是比特币。
以上,便是最古早铸造的Token的作法。这个作法主要的缺点是:当你把这1颗Bitcoin染色,也代表你失去了这1 Bitcoin(因为这1 Bitcoin被当作其它的用途了)。
并且当你要交易300美金( 300 Satoshi )给别人时,却必须付出远大于300 Satoshi的手续费给矿工,所以其实很少人这样子铸造。在2017年币价突破天际后,便几乎没人再这样铸造了。
USDT 与Omni Layer
接下来的作法,便是由Tether 公司发行,赫赫有名的第一代USDT。第一代USDT 是建构在比特币上,采用Omni Layer 的技术。做法是在比特币上发送交易,然而交易本身不是重点,重点是在交易的OP_RETURN 中写下讯息。
如:地址A给地址B 《10 USDT》,地址B便可以再给地址C 《4 USDT》、给地址D 《2 USDT》。如此不断的接续下去,就像是把比特币当作便条纸来使用一般,仅是利用比特币的OP_RETURN内容会永久存在区块链上的特性来记录USDT的流通。
然而,若是一个地址A并没有持有USDT,但他却写下了给B 《10 USDT》,这样具有效力吗?于是,Omni Layer便另外建立了一个Explorer来追踪这些所有Bitcoin交易上OP_RETURN内的Omni讯息,借以得知每个地址持有的USDT。若是有地址写下了无效的交易讯息将被自动滤掉。
以太坊ERC-20 Token
以上便是在比特币上发行Token 常见的作法。接下来进入到以太坊的世界,由于智能合约功能的出现,一切都变得简单了些。ERC-20 Token 是至今最常见的代币,那么ERC-20 是什么?ERC-20 Token 是怎么铸造出来的呢?
ERC-20是以太坊上发行代币的协定规范,约定发行的代币必须包含的资讯(如发行几颗)以及代币具有的功能(如发送与接收)和限制(如一定时间内能从钱包提领的上限)等,并且会在以太坊上建立资料库来记录每个地址持有的代币数量。
举例来说,我今天想要发行一个ERC-20 Token,取名叫Pelith Token。假设想发行一百万颗,要怎么做到呢?
用最直白的方式来说,就是要写一个ERC-20 代币发行规范的智能合约,并在发行量这段程式码中写一百万颗,接着把这个智能合约放入一笔交易的Input Data 中,交易的接收地址填为0x0,被矿工执行部署完成后,一百万颗Pelith Token 便诞生了。
所以说,代币的创造在技术上是非常容易的,无论想要发行一百万颗、一亿颗、十亿颗,其实都只是智能合约内改个数字的差别,发行量的变动成本趋近于零。
所以2017 年的ICO 浪潮,才会出现这么多各式各样的shitcoin,只要写个智能合约和白皮书,一个代币就此诞生了,可以开始圈钱。啊!不是,是募资。
真正的难处往往是代币发行后实际的应用场景搭建和社群行销营运,让这个代币被认可、让人愿意持有及应用才是最大的困难点和成本之所在。
小结
1. 「协议代币」往往有自己的区块链或类似的分散式帐本技术,而「自定义代币」则是利用现有的区块链来发行及运行。
2. 早期比特币上常见的代币有改变单位定义的染色币与把比特币作为便条纸的Omni Layer 两种做法。
3. 以太坊与智能合约的出现让发行代币在技术门槛上变得更简易且更有统一的规范,然而应用场景搭建与社群行销营运才是真正难处。
在上文中我们谈到从比特币开始到以太坊ERC-20 Token出现的自定义代币发展史。下面将更着重在以太坊技术面的介绍,并在最后综观代币演进发展史给予一些观点评论。
代币转移的成本
大家在第1节中应该都了解到区块链加密货币交易必须支付手续费给矿工,那么既然「自定义代币」要透过区块链来进行传输,当我要发送代币给别人,支付手续费给矿工也是很合乎逻辑的。
接着要解释的部分会用到许多第2节的概念,如果您还没读过,建议您先去阅读,否则可能会有些难消化。
假设我(A)要把10 个Pelith Token(自定义代币)转给B,其实是发生了什么事呢?我简单做了一张示意图来说明。(只做概念阐释,省略了很多可以很复杂的中间细节)
首先要知道,在区块链上发行代币不是真的发行硬币或发行钞票,而是建立了一个「类Excel帐本」来纪录谁拥有多少代币。当我们进行代币转移时,只是更改这个帐本上格子里的数字。
因此,当我透过智慧合约创造了Pelith Token 时,建立了一个类似Excel 的表格来追踪所有Pelith Token 持有者的持有数量,并且这些资料会以某种形式储存备份在每一个节点中(对,就是在全节点那200 G 左右里)。
当我要把10个Pelith Token转给B时,我必须发送一笔接收对象为合约地址的交易,矿工看到便知道我是要对智慧合约进行操作,不是一般发送Ether给别人的交易。并且在Input Data中呼叫我要操作动作的function,输入相对应的参数,大概会长类似下面这样:
我要call的function格式:
transferFrom(address _from, address _to, uint256 _value)
[从address _from传送_value数量的代币到_to钱包地址] 填入参数:transferFrom(0xA⋯⋯, 0xB⋯⋯, 10)
→ transferFrom(0xA⋯⋯, 0xB⋯⋯, 10000000000000000000)
注:第三个参数uint256_value是10个Pelith Token,不过因为在以太坊上没有小数点,所以进入运算时要以wei (10^-18,以太坊最小的单位)来进行,因此在10后面要补上18个0。然后转换成类似下面这个样子:
0x23b872dd000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000008ac7230489e80000
再放入Input Data中。*(0xA⋯⋯, 0xB⋯⋯, 10)这一串function中的参数称为“Payload”(装载的货物)
这些Bytecode 被矿工验证执行后,更新了「帐本内」对应地址的Balance,随后连同其它交易一起打包入新的区块中。最先找到Nonce 获得出块权利的矿工广播给其它节点,直到各节点同步完成,并确认区块在最长区块链中,便正式验证我(A)把10 个Pelith Token 转给B 了。
而以上这些动作,其实跟交易一样须缴些许的Ether 手续费给矿工。当你的ERC-20 Token 要转移给一个新的地址持有时(假设B 过去未曾持有过Pelith Token),我们在「帐本中」便必须要多开一个格子来记录并追踪这个地址的Balance。
要「多开一个格子」的价格是20,000 gas ;「更改一个现有格子内的数字」的价格是5,000 gas,在这笔交易中一共更改了A、B 两格,故是10,000 gas。再加上交易的基本手续费21,000 gas。我执行了将10 Pelith Token 转给B 的动作,总共花费了51,000 gas。
执行操作的Gas 总花费计算:
20,000 gas + 5,000*2 gas + 21,000 gas = 51,000 gas 手续费(Eth)= Gas Used * Gas Price
51,000 gas * 10 Gwei(fast) = 510,000 Gwei = 0.00051 ETH = 0.1 USD
(以1 Ether = 200 USD 计算)
大约3 块台币,便是更改一个格子大约需付出的手续费。
至此,我们知道了转移Token须付出的手续费。如果转移的量很大,其实金额也是有一定量的。并且,若你的Token Transfer交易无效,被弹掉时(例如你只有10个Token却发了20个给别人),由于必须到矿工要改格子时才会触发error,但矿工已执行了这笔交易到触发error为止的运算。故虽然交易失败,手续费还是要付。
以太坊2.0 与无头合约
最近随着以太坊2.0 有越来越多的消息释出,出现了一个新名词:「无头合约」。原本在智慧合约,当我们从Input Data 呼叫合约中的function 后,合约中的程式码便会执行逻辑运算去更新「帐本」内的Balance。
然而,以太坊2.0的Phase 1并没有EVM,无法执行合约中的逻辑部分。因此发布的合约中的function 会长下面这个样子:
transferFrom(address _from, address _to, uint256 _value) {
}
原本1.0 的合约function 是长这个样子:
transferFrom(address _from, address _to, uint256 _value)returns (bool) {
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
return true;
}
这是什么意思呢?就是当我们在Input Data 中呼叫了合约中的function,但function 并不会真的去更新帐本上格子里的balance。因此这个合约只是个空壳,虽然看起来有东西,但实际上却不会执行动作。
因此当我们发送to 合约的交易,在Input Data 中输入:
transferFrom(0xA⋯⋯, 0xB⋯⋯, 10)
合约并不会真的更新帐本(因为根本没有帐本的存在),也不会同步到其它的节点中。因此这些Input Data输入的内容只是被当作一般的备注文字讯息被写在to合约的交易中。于是呢,又回到了比特币Omni Layer的做法,我必须要去爬这些所有的「便条纸」上的资讯,才会知道最新各地址的余额状态。也因此,我们发送呼叫这个合约的交易,因为不会进行逻辑执行,所以实际上可以省下非常多的gas,只需要付出交易的基本手续费21,000 gas加上些许的文字写入gas费用。
我们回顾到目前为止4节 的内容,可以发现区块链从1.0的比特币,到2.0的以太坊,最大的升级便是智慧合约的功能,允许开发者可以客制化开发许多需要的功能。
结论
1. 在区块链上发行代币不是真的发行硬币或发行钞票,而是建立了一个「类Excel帐本」来纪录谁拥有多少代币
2. 代币转移时必须发送一笔接收地址为合约地址的交易,并在Input Data中呼叫合约中的function 进行操作,并付出相应的运算成本给矿工。
3. 以太坊2.0的Phase 1中由于没有逻辑执行的功能,因此智慧合约都成了「无头合约」,让以太坊2.0再次被当作如Omni Layer般的「便条纸」来使用。
来源:动区动趋
评论
查看更多