铭文内容上链:BTC的文艺复兴
文化是数字加密货币价值共识的根基,传播价值共识离不开加密货币的自有文化。
JinseFinance作者:雾月,极客Web3
导语:目前的以太坊铭文本质还是Ordinals的新瓶装旧酒,没有真正意义的新范式。ETHS仍然存在安全风险,虽然它的确比Rollup去中心化,但其提款流程还是依赖于第三方公证人/管理者,有被盗风险。显然ETHS当下还是以金融炒作居多,而不是说它能带来以太坊Layer2带不来的革新。
近期BTC生态铭文的火热,带动了其他链的开发者搭建类似的系统。不同链上的铭文系统的实现方式和可实现的功能略有不同,但有一些共同点:
铭文都利用了转账时附加的文本信息来表达想要完成的操作,如,在信息内写入“向XXX转1个币”。注意,这些信息是纯文本的,不会涉及链上的智能合约执行等操作。
开发者会设计一系列规范和标准,来将所有的文本信息规范化。
开发者提供一套Indexer索引器,用于将链上所有铭文的文本信息归集后,计算铭文系统的内的状态。Indexer是个链下的开源组件,任何人都可以运行。
BTC铭文Ordinals在BTC上建立了一套发行NFT、代币的机制,也引出了对BTC L2的大规模思考,在这个意义上我们可以认为Ordinals具有一定的前沿和探索性质。不过,Ordinals在技术和产品体验上受到了BTC本身架构的限制,同时也因为粉尘污染和数据占用等原因,遭到了BTC社区OG的非议。
那么,在以太坊上复刻铭文,是否有意义呢?毕竟以太坊本身具有复杂的智能合约,ERC20、NFT也是以太坊上本身就有的内容;这些铭文项目又会对以太坊生态产生怎样的影响,会出现在BTC上上的争议和风波吗?
Ethscriptions的技术实现方式
我们先来看一下Ethscriptions的实现方式,它是以太坊上著名的铭文项目,主要利用Calldata来实现运转。
Calldata是以太坊交易中传输的原始输入数据。一般用于传输智能合约交互时需要的参数,但也可以用于向EOA地址发送文本消息(留言,铭文刻字,转账备注等任何用途)。图中Input Data即calldata。
如果你想使用Ethscriptions在交易中铭刻”Hello world”,则需要构建一条包含如下calldata的交易:
链下的Indexer监听到这笔交易后,就会更新数据库并通知用户:一条新的铭文产生了,铭刻的内容是Hello world。铭文里也可以放更复杂的内容,如代表图片信息的base64等。
Ethscriptions目前通过了6个ESIP(Proposals for improvement to the Ethscriptions protocol),类似EIP的提案,来定义不同场景下铭文的使用。但这些仅仅是比较基础的铭文规范,比如从EOA发起的铭文交易的格式,合约emit事件等等。
Ethscriptions由于是在以太坊上的项目,也可以利用以太坊的智能合约实现一定程度上的逻辑。需要注意的是,直接与智能合约进行交互并不是Ethscriptions推荐的方式。
虽然官方的NFT市场等也是直接用智能合约实现的。根据官方文档的说法,Ethscriptions想要为用户提供的是“去中心化且价格合理的运算服务”:将运算剥离至链下,将显著降低以太坊的使用成本。
我们来具体探究一下调用智能合约的成本,可以分为三部分:
基本交易成本:任何以太坊交易都需要支付,目前为21000 gas。
数据传输成本(calldata):calldata一般用于提交与智能合约交互的数据和参数。EIP-2028调整后,calldata数据每个字节一般消耗16 gas(若是数据为0的字节 消耗4 gas)。
合约执行成本:如果交易调用了智能合约中的函数,那么根据函数执行的复杂度,还需要支付计算成本。例如,如果涉及状态更新(比如在ERC-20合约中更新余额信息),调用SSTORE会消耗高达5000~20000 gas。
我们以一个非常简单的USDT转账的交易为例,该交易总共耗费了63197 gas,calldata为:
我们解析下该calldata,以及它会花费多少gas:
以太坊calldata为十六进制格式,也即每两位为一个字节(16^2 = 2^8)。开头的0x代表数据采用16进制。
开头0x后面的a9059cbb
是函数选择子,占用4个非零字节。
之后的32字节为地址,前面有12字节的零(因为以太坊地址是20字节,这里左补了零到32字节),以及20字节的非零地址数据。
最后32字节代表金额,左补了大量的零,末尾有3b9aca00
非零数据,4字节非零。
所以,非零字节28个,零字节40 个
因此,calldataGas = 28 * 16 + 40 * 4 = 608 gas
。
而总gas为63197,减去calldata成本和固定成本,则执行该交易的智能合约计算成本为41589 gas。在这笔交易里合约运算成本占了大头,而这仅仅是一笔简单的交易,复杂的交易中合约运算的成本会进一步上升。
将运算过程放至链下确实会显著地降低使用成本:不想在链上直接调用智能合约的话,可以向一个约定好的EOA地址
0x00000000000000000000000000000000000face7
发送交易数据
在交易的calldata中声明原本想调用哪个合约,以及相应的输入参数。由于上述地址是一个EOA账户,没有合约代码,所以前面所说的操作不会在链上触发计算任务,只是发布了一条消息而已。
而在链下,Indexer监听到这条消息后,就会进行解析,弄清楚这条消息的发起者原本想调用ETH链上哪个合约,然后Indexer会在链下计算出合约调用的结果。
那么线下的Indexer想要进行铭文和智能合约的运算,就必须有一套STF(状态转换函数)规则和运行时,复杂点的可以叫虚拟机VM。Ethscriptions在ESIP-4中推出了自己的VM——Ethscriptions VM,后来改名为Facet VM。
Facet——有点像协处理器
Facet将自身定义为一个便宜好用,安全,去中心化的计算平台。监听以太坊上Ethscriptions的calldata,拉到VM中进行运算,最终给用户返还结果。Facet包含几个关键的组成部分:
Facet VM,用ruby编写的一套VM,负责监听ETHS交易,解析calldata,执行运算。
Rubidity,Facet中的智能合约编程语言,与Ruby有一定相似性,又保留了很多solidity的用法和概念,以期开发者能快速上手。
Dumb Contract,呆笨合约,一种在Facet上运行的合约。这个名字充满了幽默感。有人称其为哑合约也是对的,dumb本身是双关的,哑可以描述这种合约工作的静默过程。但另一方面根据官方名言"So dumb, they're smart”,大愚若智,一股浓浓的与smart contract叫板的意味,所以叫呆笨合约也没问题。
呆笨合约本身不会真正部署在以太坊上,只是其代码会以calldata的形式发布到ETH链上。下面是一个Facet对呆笨合约的调用案例:
一笔铸币交易,向EOA黑洞地址
0x00000000000000000000000000000000000face7
提交下图中的calldata,声明自己要mint的代币和数量即可,这其实和Ordinals或BRC-20如出一辙:
我们再来看一下Rubidity和Solidity的直观对比,见下图。
虽然官方说Rubidity具有类似Solidity的概念和结构,以便开发者快速上手。但我们知道其实这对开发者侧的发展来说是有一定负面影响的。并且目前Facet VM仅支持官方白名单中的呆笨合约,这说明官方对这套语言以及VM并没有很十足的信心。是否复用EVM对官方而言,在工程技术上比新开发一个VM和一个新的语言更难,我不得而知。但有一点可以肯定的是:全新的语言、全新的合约、全新的生态、全新的以太坊使用方式,确实有足够的噱头。
Facet对智能合约的抨击
Facet文档中对以太坊和智能合约做出了如下的劲爆评论:“Smart Contracts are considered to be the feature above all others that makes Ethereum special, and yet Facet’s thesis is that Smart Contracts are Ethereum’s biggest design flaw.”
他们认为以太坊的智能合约是最大的设计缺陷,因为合约本身只要给定输入(calldata),其输出就是确定的,因此不应该在链上进行运算,平白无故浪费钱。再结合Ethscriptions所说的“去中心化且价格合理的运算服务”,显然Ethscriptions和Facet非常想打造一种市场印象,“我们正在制造全新的以太坊扩容范式和使用方式”,但实际上ETHS自己的一些技术方案不是很靠谱。
从产品角度看,Facet可以在链下间接调用智能合约,又有自己的链下的呆笨合约体系,确实官方正在践行其口号。
但从经济角度讲,天下没有免费的午餐,存储和运算当然是要钱的。那请问Indexer该如何解决这部分成本呢?这官方就没有什么明确说明了,我们可以想象一下:
向用户收费。比如NFT市场向买家收取的手续费,但我们不能以一个简易的项目的收费模型看待一个类L2网络的长远收费方式。
靠自身生态炒作关联致富。这个当然可行,但只是一种短期的让项目方一时爽的方案。Ethscriptions如果想成为一种全新的以太坊范式,Indexer必须有长久的,从网络出发的经济机制来保障运转。
如果是不盈利的Public goods,那么会有哪些机构donate呢?我觉得至少以太坊基金会不会特别积极,因为本身以太坊有非常好的方案——Rollup。
Facet和呆笨合约出现的根本原因
如果我们只是需要以太坊铭文的简单形式,那么只需要Ethscriptions一个项目就够了。那为什么其ESIP-4提案又催生出了Facet呢?
因为铭文体系没法用于复杂的交易逻辑。我们可以考察下Ethscriptions官方的NFT市场合约的运作逻辑,它使用了挂单机制。
如果要将铭文NFT充值进合约,仅需要把calldata写为铭文的EthscriptionId
并调用市场合约。由于这种操作故意选择无效的函数调用形式,默认会触发fallback()。
最终会在以太坊链上抛出一个名为PotentialEthscriptionDeposited
的事件,Indexer节点在链下监听到这个事件后,便会在本地将NFT的归属权划转为市场合约。
为了节省gas,ETHS的交易市场没有把卖家挂单的一些参数,如价格、截止时间等放在ETH合约里存储,而是以消息的形式放在了线下,目测应该是存储在了dApp的服务器上。买家监测这个消息后,就可以发布buyWithSignature()
指令提出购买。
对NFT而言使用挂单机制是正常的,因为NFT本身不具有同质性。那么如果是均质化的代币铭文,能否使用合约的AMM机制呢?答案是不行的。铭文NFT或代币的状态,都不在L1上,就和Ordinals和BRC-20差不多。这和一些社群的宣传是截然相反的,大家需要注意甄别,铭文并不是真正意义的ETH链上的资产。我们并不能说生成资产的calldata在L1上,并且可以在L1上声明操作指令,就叫L1上的原生资产,否则Rollup上的L2原生资产我们也可以称为L1资产,因为Rollup的calldata都在L1上。显然,管这种资产叫L1原生资产非常荒谬。
你可能会疑惑,上面不就是利用智能合约进行了买卖吗?怎么就说合约不能读取和操作铭文呢?其实这个合约只负责收钱,转钱,抛出事件供链下的Indexer节点监听并触发对应的操作。在以太坊EVM眼中,铭文这类东西的状态,无法在以太坊专门存储状态的数据库“世界状态”中还原出来,合约也没法引用它。
不论资产是什么形态,代币也好NFT也好或者任何稀奇古怪的东西,我可以给出一个非常简单的标准鉴别L1资产和L2资产:它的状态能否在以太坊的“世界状态”上还原出来,L1的EVM能否引用、调用、查询、修改该资产的状态,如果不能,那它就不是L1的资产。
所以你也可以看到充值的事件名字叫PotentialEthscriptionDeposit
,即“可能的铭文充值”,而不是一个确定性的充值,因为合约没法判定这个铭文是否存在,无法验证其真伪。如果你挂单了一个不存在的铭文,或者别人的铭文,合约不会拒绝你,只是Indexer不会收录你的行为而已。
因此铭文系统只能实现这种简易的伪合约逻辑,挂单就是其中一种。挂单的本质是交易双方在一种规则下互相认同对方提供的信息,其实不用智能合约用纯文本也可以表达,这和铭文的道理类似。
我们可以想象一下如何不使用智能合约来完成上述过程:卖家在普通交易中刻一笔消息,转给我1ETH并附言123的人可以获得我编号为123的铭文NFT。这样只需要Indexer支持这种逻辑,它监听到了有人转了1ETH给卖家并附言ABC,就可以直接在链下的Indexer数据库里划转。
当然这个例子实际上会带来一些问题,比如多人抢购一个NFT可能导致的重复交易等,卖家收了多笔转账,但最终NFT只能被Indexer划给一个人。这也应该是官方明明抨击智能合约,却使用合约实现NFT市场的原因之一,因此你也应该能明白官方所说的通过Facet不进行计算而调用智能合约是不靠谱的宣传。
当然,挂单理论上可以使用纯文本,而不是非要用合约,但AMM这种相对比较复杂的逻辑就必须用智能合约,因为它需要的不是双方p2p式的认同,而是合约认同。充当了可靠审查者的合约,需要检查余额、流动性等基础信息,并进行运算,任何他所需的资产数据,合约都必须能够获取到。
而AMM仅仅是比较简单的一种DeFi形式,其他任何复杂的逻辑在仅仅在Ethscriptions上都是无法实现的。这也是为什么推出了Facet的原因——Facet的第一要务是跨域!它其实就是个L2,只是没有区块结构,所以我们不叫跨链而叫跨域。当所有的L1资产跨域到Facet后,就不存在跨域无法调用的问题,可以在链下对所有链下资产用呆笨合约进行操作,进而支持复杂的合约逻辑。
和Rollup的对比
通过上面的长篇大论,大家应该能发现,Ethscriptions的方案有点类似于Rollup。但这仅仅是“类似于”,如果严格的说的话,它只能实现Rollup核心功能的子集。而残缺的功能则为其叙事带来了致命伤,或者说将用户置于严重的威胁之中。
Rollup是一套复杂的体系,这里我们不展开。它和Ethscriptions有些共同点:
- 都在以太坊上提交L2交易的数据calldata。
- 都将运算放在链下处理。
共同点非常清晰,我们需要详细论证一下不同点。
Rollup批量提交calldata
Rollup中用户大部分情况不会向L1直接提交交易,而是提交给链下的排序器,排序器会对所有交易排序后打包、压缩,将calldata批量发送至L1。这样多个用户的calldata在一笔交易中提交,可以摊薄21000 gas的基础成本。
在Ethscriptions中没有这样的机制,所有的用户直接向L1提交calldata。
我们用上面那个USDT的例子(608 gas for calldata),假设有100个用户发起了100笔交易,非常不严谨地粗略计算下二者的成本差别:
铭文用户每人都需要支付21608 gas(608 + 21000)。其余运算部分不支付,因为运算在链下。
Rollup用户每人支付 818 gas ((608*100+21000)/100)。运算部分同上。
当然,Rollup用户每个人还需要向排序器缴纳L2的运算和存储费用,但相对L1低廉很多,在本例中可以忽略不计。另外,rollup还需要额外的一些特殊字段增加了体积,但同时又有比较好的数据压缩,这里我们也不展开。
通过这种粗略的估算就可以发现,Ethscriptions对比Layer2,在成本方面没任何优势。另外,该项目的社区宣传话术中我看到过类似“4000个铭文可以批量转账,大概需要0.11ETH,平均每笔转账只需要0.05U”以此来证明Ethscriptions的使用很便宜,这其实都没有理清ETHS的原理与交互细节。
链下预确认
由于具有链下的排序器,Rollup的用户请求可以在1s内得到预确认。这一点比铭文系统在L1上的12秒或更久,UX要好很多。当然,铭文支持者也可以反驳说,在calldata 提交到ETH链上前,这样的交易结果最终性都是不可靠的。
抗审查性和去中心化
用户在Rollup有可能被链下的排序器审查,而Ethscriptions无法审查用户。但设计良好的Rollup会有强制归集功能,以对抗排序器的审查,最终使排序器完全不具备审查用户的权力。
所以用户使用Rollup时,也是可以直接在L1上绕过排序器使用的。Rollup给用户不同的选择,可以使用更快的排序器,也可以直接用L1。但Ethscriptions只能使用L1,并没有给用户自由选择的余地。
另外Ethscriptions诟病Rollup的排序器是中心化的。但Indexer本身也是高度中心化的组件。Ethscriptions解释说Indexer由于任何人都可以运行、验证,所以不算中心化,但事实上绝大多数人都不会自己运行节点。所以ETHS只是在极端情况下,会体现出它比Rollup去中心化的一面,毕竟Rollup排序器可能宕机或者故障,但ETHS只要有社区成员运行多个Indexer,就可以持续运转。
盈利模式
任何项目都不可能用爱发电,长远发展的项目必须认真考虑盈利模式的问题,不论是中心化实体还是去中心化实体的组合,都必须有盈利才能够长期地守护网络安全。
Rollup的排序器有明确的盈利模式:多收取gas,榨取MEV等。排序器有动力保证网络的正常运转。Ethscriptions由于用户直接向L1提交calldata,Indexer其实不好收费。
开发者友好程度
大多数Rollup的合约开发语言、工具链等都直接使用以太坊的即可,开发者可以无缝迁移至Rollup。在Ethscriptions中这些都不存在,需要掌握新的Rubidity,需要构建新的scan,熟悉新的VM等等。当然,这些阻力反过来看也是一个新生态发展时可能带来的拓荒的机会。
提现和状态结算
这是Facet的致命问题。我们知道Rollup不仅仅会将calldata(输入)批量提交到L1上,也会定时将N个运算后的状态结算(输出)提交到L1上。ZKR和OPR有不同的证明方式来确定输入和输出的关系是否正确,不论什么证明方式,最终的裁判都是L1上的合约。在Rollup上输出和输入是有迹可循的,无法造假的。
那么状态结算有什么用呢?用于提现,也即L2到L1的资金提取。当L1上的状态发布后,我们就可以根据状态根,用Merkle Proof等手段,去证明我在L2上的提现请求包含在了该状态根里。合约验证无误后就可以在L1上放行资产。
Facet没有状态结算机制,所以他无法实现L2到L1的无许可、去中心化的提现。上面提到过,他又需要一个L2层,以执行更复杂的合约逻辑。如他的AMM Swap FacetSwap。
我们可以看到在FacetSwap(Facet上用呆笨合约构建的dex)中明确有充值和提现两个动作。一般Swap是没有充值和提现的,因为Facet需要你先跨域才能使用。
在Facet中,充值需要在L1桥合约上将L1的资金锁定,并且发射出对应的事件ethscriptions_protocol_CreateEthscription
让Indexer进行索引。这和其他的L2的充值的手段是一致的。
而提现则有严重的安全问题。由于在Facet上没有任何的状态结算机制,L2到L1上无法用合约自动判定一笔提现是否有效。那Facet使用了什么方法呢?管理员放行,或者叫见证人机制,类似于此前被盗的Axie桥。
我们直接来看一眼Facet的桥,地址为
0xD729345aA12c5Af2121D96f87B673987f354496B
。
hashedMessage
是经过signer签名的一个消息,里面即提现的一些内容。signer是一个预设的管理员地址。因为没有状态结算没法做任何校验,比如该账户在L2上是否有这么多币。所以完全凭signer签名就可以将合约上的所有资金取走,不论是项目方作恶还是黑客攻击获取私钥。
在Rollup中,根本不需要见证人放行资产;在侧链中,见证人如果想做的去中心化一些,可以从本身的共识体系中选择出一部分作为代理,用质押等方式进行一定的经济威慑遏制作恶。
在Ethscriptions和Facet中,nothing。它简单地、不加掩饰地就是一个管理员地址。这对于一个动辄喊着“智能合约是设计缺陷”、“Rollup是中心化的”、“我们是新一代计算平台”的类L2项目而言,恐怕过于潦草了。显然,他的缺陷还有很多,但我们可以对此保持观望,虽然这些缺陷不太好弥补,并且可能同样在比特币Layer2身上存在。
总结
目前的Ethscriptions存在一定的“虚假宣传”,几个要点:
Ethscriptions和Facet上的资产,都不是发行在L1上的资产。
为了有复杂的合约能力,演化出了Facet这个L2实体,但有极大的资金安全隐患。
官方宣称的在L1上去合约运算化,却连自己的头牌应用都不用。
Ethscriptions类似一个基础功能非常不全的Rollup。既没有Rollup的便宜和迅速,也没有Rollup的安全。他能实现的,Rollup都能实现,Rollup能实现的很重要的功能它无法提供。
如果想解决上述问题,他需要发展出状态结算机制,再加上排序器,L2区块,那么它最终就变成了Rollup。
Ethscriptions趁着BTC铭文的风口,依靠概念炒作新瓶装旧酒,但还没有发掘出新的范式。目前的ETHS还是以金融炒作为主,而不是说这种产品本身能带来以太坊Layer2没有的东西。这种东西的长期价值,显然还有待人们去挖掘,但就以目前的形式来看,ETHS已经承担了“生命不可承受之重”,他的宣传口号与其实践效果相差甚远。
文化是数字加密货币价值共识的根基,传播价值共识离不开加密货币的自有文化。
JinseFinance由于铭文协议的复杂性和新颖性,各种安全问题频出。这不仅威胁到用户的资产安全,也对整个铭文生态的健康发展产生了负面影响。
JinseFinance哲学家维特根斯坦说过,“语言的界限即是世界的界限。” 同样是数据上链,铭文这个汉语词汇,比NFT这个三字母缩写词,要高明到不知哪里去了。
JinseFinance本文介绍并整理了超过 20 个铭文协议与超过 30 个铭文市场
JinseFinance