您正在查看: Ethereum-优秀转载 分类下的文章

区块链模块化设计是未来吗?

如何使用模块化可能是突破不可能三角的一个途径。

介绍

大约十年前,世界见证了移动智能手机的增长。当时,一些大公司认为他们可以通过引入模块化架构来彻底改变智能手机。2013 年,谷歌发布了 Project Ara,这是一款采用模块化设计的新型智能手机。与今天由密封的铝和玻璃片制成的“单体”手机不同,Ara 允许用户以多种方式定制他们的手机,使所有基本部件都可以模块化。你不会被迫频繁升级到新手机。相反,你可以根据自己的喜好简单地为旧手机添加最好的新部件。可悲的是,模块化并没有在手机生态系统中取得成功,这个概念仍然是一段几乎被遗忘的技术历史。

模块化智能手机可以作为模块化区块链的警示故事,因为尽管当前工具存在合理的缺点,但新的和令人兴奋的解决方案的炒作并不能保证长期的胜利。然而,就区块链而言,用户对可扩展性的需求已经在推动开发人员构建和采用模块化架构。这种需求使得模块化区块链架构不太可能与模块化智能手机那样,遵循相同的命运。

但究竟什么是模块化区块链架构?我们如何确保这些解决方案不会成为另一个 Project Ara?这篇文章希望能回答所有这些问题。

单体和模块化

在进一步深入研究之前,让我们梳理一下单体架构和模块化架构之间的区别。介绍这个概念的最简单方法是举一个类似而熟悉的概念的例子。正如手机有一些核心部件,比如摄像头、电池和触摸屏,区块链也有核心部件。

iPhone 是“单体”手机的一个很好的例子。它配备了使用手机所需的所有部件,并没有提供太多定制选项。当然,你可能无法对内部进行太多定制,但它既流畅又快速。但是,有时你可能希望进一步自定义你的手机。假设随着岁月的流逝,新手机配备了更好的相机。过时手机的其余部分可能工作正常,但使用现有的相机,你无法获得新手机那样的体验。

使用模块化架构,你不必购买全新的手机。相反,你可以像乐高积木一样更换相机,然后换上更好的相机。

Google 的 Project Ara 是模块化手机的一个例子。这款手机由积木制成,可以根据你的选择换入和换出零件。只要有兼容的部件,Ara 都会支持。

与智能手机一样,区块链由多个基本组件组成;这些组件如下所示:

  • 共识
    区块链的共识层通过计算机网络就链的状态达成共识来提供排序和最终性。

  • 执行
    该层通过运行指定的代码来处理交易。它也是用户通常与区块链交互的地方,例如通过签署交易、部署智能合约和转移资产。

  • 结算
    结算层用作验证在第 2 层执行的活动的平台,例如Rollup以及争议解决。最重要的是,它是记录实际区块链最终状态的地方。

  • 数据可用性
    验证状态转换是否有效所需的数据应发布并存储在该层上。在发生攻击或操作失误,区块生产者未能提供交易数据的情况下,这应该是容易检索和验证的。

简而言之,单体式区块链在单个软件中自行执行所有这些任务,而模块化区块链将它们分成多个软件。现在,你可能想知道一次处理所有这些任务的区块链有什么缺点?

这又回到了古老的问题,即可扩展性不可能三角困境。

可扩展性不可能三角困境表示区块链只能具有以下三个特征中的两个:去中心化、安全性和可扩展性。
现有的(新的)单体区块链倾向于针对三角的安全和可扩展进行优化。比特币和以太坊更加强调去中心化和尽可能安全。但都是有代价的。去中心化区块链通常没有高带宽来执行交易。以太坊每秒最多处理 20 笔交易,而比特币的处理能力甚至更低。如果我们想在全球范围内使用这些协议,每秒 20 个交易是远远不够的。一些单体链至少在理论上,可以使我们更接近全球规模,因为它们的 TPS 和总吞吐量是足够的。然而,他们往往缺乏去中心化,而这是区块链技术的核心原则。

模块化架构的目的是将区块链的一些工作外包出去,在保持去中心化的同时做出更多性能更高的链。让我们讨论一下以太坊,并讨论它有望如何利用模块化。

以以太坊为中心的生态系统

大多数第 1 层区块链

现在的以太坊是一个单体的区块链。今天大多数其他第 1 层区块链也将被归类为单体区块链。就像 iPhone 的例子一样,单体区块链的某些功能有时会开始落后于较新的替代方案,导致在对比最新和最具创新性的第 1 层时流失开发人员和消费者。为了解决以太坊目前在吞吐量方面的瓶颈,开发人员正在构建Rollup执行层以增加交易带宽。

模块化执行层

示例:Optimism, Arbitrum, Fuel, Scroll, ZkSync

Rollups 作为执行层是当今以太坊上使用最广泛的扩容方法。Rollups 是独立的区块链,具有更高的交易执行性能,其最终结果在以太坊上结算,以有效继承其(更好的)安全性和去中心化。

在高层次上,Rollup只是一个区块链,它将其区块的结果发布到另一个区块链。然而,这只是Rollup的一个组成部分,因为你还需要欺诈和有效性证明以及一种无许可插入交易的方法。Rollups 通过在两个智能合约之间同步数据来实现这一点,一个部署在第 1 层,一个部署在第 2 层。这种设计使其成为 rollup 而不是侧链。这些关键组件对于 rollup 的安全是必不可少的,因为没有这些组件,rollup 可以被停止或审查 。

目前,大多数 rollup 都提供 EVM 兼容性以帮助以太坊开发人员轻松迁移,但在计算效率和开发易用性方面,执行层可能有更好的替代方案。用户甚至可能想要更多 EVM 等效链上不存在的功能,例如帐户抽象。鉴于开发人员的偏好广泛,这种趋势很可能会持续下去,我们将看到更多新颖的解决方案进入市场,例如 SolanaVM 和 MoveVM 执行层。Fuel 是一个不兼容 EVM 的执行层的例子,它的唯一重点是执行在其他Rollup上不可能执行的计算。Fuel 也是第一个“模块化执行层”,正如我们将看到的那样,它允许它成为一个主权Rollup、一个结算链,甚至是一个单体区块链。Rollup 只是执行层,而 Fuel 可以是更多。


Fuel 可以用普通 Rollups 做不到的方式进行模块化。因此得名“模块化执行层”。我们将很快深入探讨 Celestia 架构的机制。(图源:Fuel)

Fuel 显示执行层可以具有创造性,并且优先考虑计算速度而不是 EVM 支持。虽然许多熟悉模块化架构的人都知道 Fuel,但另一个强大的竞争者却鲜为人知。最有趣的即将到来的模块化执行层之一是Kindelia。除了是最快的计算层之一,Kindelia 还拥有一个利用其虚拟机的独特证明系统。Kindelia 的 HVM 提供了一种近乎即时的证明检查器,内置于他们名为 Kind 的智能合约语言中。Kind是必不可少的,因为智能合约可以在它们的代码中证明它们的代码是安全的,不会被利用并且操作正确。这种类型的设计可以解决智能合约编码不当的问题,并使我们免受当今困扰智能合约的漏洞之苦。这只是Kindelia比其他执行层提供价值的一种方式。

但在执行层方面的扩展只是难题的一个部分。开发人员寻求进一步模块化单体区块链,以挤出每一点可能的性能。这就引除了如何模块化数据可用性层。

模块化数据可用性层


示例:Metis、ZkPorter、Anytrust
Validium 是一种Rollup,其数据在链下而不是存储在链上。

但为什么我们要将数据转移到链下呢?这是因为我们正在尝试优化数据可用性。Rollup系统的效率在很大程度上取决于其数据可用性层的能力。当底层无法处理Rollup的交易排序器生成的数据量时,就会导致处理交易的瓶颈。因此,rollup 无法处理额外的交易,导致 gas 费用增加和/或执行时间变慢。换句话说,rollup 的数据可用性层的性能是决定其依靠的单体区块链交易处理能力和相关费用的关键因素。

validiums 的缺点是它们是链下的,引入了更多的信任假设。我们想要一个链上解决方案来提高以太坊的数据可用性层。答案是 Danksharding。

Danksharding 与以太坊的整合将其转变为一个用于结算和数据可访问性的精简平台。

Danksharding 的创新之处在于它能够将这些概念合并成一个有凝聚力的单元。Rollup证明和数据在同一块内进行验证,从而创建一个无缝且高效的系统。但是,作为其正常操作的一部分,Rollup需要为其压缩数据提供大量存储空间。Danksharding 为这一需求提供了解决方案,提供了跨多个Rollup实现数百万 TPS 的潜力。Danksharding 是一种将网络活动分成片以增加data blob 空间的技术。data blob 是以太坊中一种更高效和标准化的数据格式,可以承载大量数据,并被 rollups 使用以降低 gas 费用。Danksharding 利用“数据可用性抽样”使节点能够通过仅检查一小部分来验证大量数据,为未来铺平道路,使更便宜和更快的第二层网络能够蓬勃发展,同时实现以太坊的直接交易。

Danksharding 很棒,因为它将继承以太坊本身的所有安全性和去中心化。然而,这有一个缺点。由于以太坊的发展速度相对缓慢,我们可能需要数年时间才能将 Danksharding 正确实现到以太坊中。EIP-4844 计划引入 Proto-Danksharding,这是实现 Danksharding 的第一步。EIP-4844 通过引入容纳数据块的新交易来增强以太坊。这种用于Rollup数据的专门存储为更具成本效益的收费市场铺平了道路。

如果你想要一个快速的数据可用性层但又不想坐等 Danksharding 发布怎么办?Celestia 正是提供了这一功能的协议。转变以以太坊为中心的模块化视角,我们值得深入研究 Celestia,看看模块化区块链还可以如何解释。

以 Celestia 为中心的生态系统


Celestium 是一种独特的解决方案,它结合了 Celestia 的数据可用性和以太坊的结算及共识。Danksharding仍然是最安全的方法,因为它融入了以太坊、去中心化和稳健性。然而,一些Rollup 宁愿现在就寻求可扩展性,而不是等待 Danksharding 被实施到以太坊中。

对于等不及 Danksharding 的项目,一种可能的选择是利用链下数据可用性解决方案,例如 Validiums,它利用“数据可用性委员会”(DAC)来证明数据可用。然而,这种方法不那么去中心化或安全,因为它依赖于多重签名,并且无法验证 DAC 当前是否诚实或他们过去是否诚实。

Celestium 提供了比 DAC 更安全的替代方案。在 Celestium 中,数据可用的证明由整个 Celestia 验证者集的质押支持,这意味着如果 ⅔ 的验证者提供了不正确的信息,他们可能会被削减并可能损失一大笔钱。与不存在惩罚的 DAC 不同,Celestium提供了一个严厉和即时的反应。

此外,用户可以通过在区块上运行数据可用性采样并检查量子引力桥(Quantum Gravity Bridge)来验证 Celestia 的诚实性,量子引力桥是从 Celestia 到以太坊的无信任单向消息传递桥。桥通常是任何解决方案中最脆弱的部分,因此必须建立冗余。

Celestium 与 Danksharding 一起利用数据可用性采样 (DAS) 来验证所有数据的非恶意性质。DAS 允许节点通过下载随机片段并在任何部分丢失时发出警报来确保块的可用性。该警报系统只是采用欺诈证明(例如 Celestia)的 DAS 机制的一个方面。在像 Danksharding 这样的有效性证明 DAS 机制的情况下,不需要警报系统,因为有效性证明保证了纠删码和承诺的正确性。这些机制降低了隐藏区块数据的风险,并确保大量节点随机检查区块。

一个节点随机抽取一个区块来检查它的可用性。(来源:Vitalik Buterin)

数据抽样是使Celestia和Danksharding如此安全的原因。至少用户知道,如果发生损坏,他们可以很快发现。相比之下,在DAC这个黑匣子里,可能会有一年的“腐坏”,而没有人会意识到这一点。

示例:Fuel

与以太坊上的传统Rollup相比,主权Rollup的功能不同。与标准Rollup不同,主权Rollup不依赖第 1 层上的一组智能合约来验证区块并将其附加到规范链。相反,区块作为原始数据直接发布到链上,rollup 上的节点负责验证本地分叉选择规则以确定正确的链。这将结算责任从第 1 层转移到Rollup。与传统的 rollup 不同,在主权 rollup 和 Celestia 之间没有建立信任最小化的桥梁。这可以被视为一个负面因素,因为你希望桥接尽可能信任最小化,但这确实为主权Rollup提供了通过分叉独立升级路径的优势。并且比非主权Rollup提供的升级更加安全。从技术上讲,我们不应该将其视为Rollup,因为Rollup通常意味着具有统一的结算和数据可用性层。因此,主权Rollup也简称为主权区块链。

为了让开发人员更容易在 Celestia 上创建主权Rollup,Celestia 创建了 Rollmint,取代 Tendermint 作为共识机制。这使得 rollups 能够直接向Celestia发布区块 ,而不是通过 Tendermint 程序。通过这种设计,链背后的社区拥有完全的主权,不受其他状态机的权威约束。这使其他与以太坊上智能合约或Rollup背后的社区不同,后者受以太坊社区社会共识的约束。


结算链示例:Fuel、Cevmos、dYmension

结算Rollup 是指创建独立和模块化结算组件的。目前,rollups 使用以太坊主链进行结算,但除此之外还有其他解决方案。以太坊链与非Rollup应用(智能合约交易)共享网络,导致扩容受限和缺乏特定优化。

一个理想的Rollup结算层将只允许Rollup智能合约和Rollup之间的简单转账,同时禁止非Rollup应用或使其交易高昂。

Celestia 的设计为开发人员提供了一个标准的全局状态共识层,以构建作为单一信任最小化执行层Rollup。它还可以在同一全局状态共识层上的Rollup之间实现信任最小化的桥接,这是当前架构中没有的新概念。开发人员是否会采用这种新的跨Rollup范式还有待观察。

结算链的示例包括 Cevmos、Fuel 和 dYmension,其中 Polygon 通过建立其对模块化架构的解释与 Celestia 竞争。在Polygon的模块化设计中,Polygon Avail作为数据可用性和共识的模块化组件,Polygon区块链作为结算层。

单体链的案例

与较新的模块化解决方案相比,许多介绍模块化区块链的文章通常将单体第 1 层区块链称为过时的“恐龙”技术。目前,很难完全支持这钟说法,因为这些扩容解决方案的一个主要问题是它们给整个系统添加了更多的信任假设。虽然我们已经讨论了大多数 DAC 和 validium 是如何不安全的,但这甚至可以扩展到执行层(即Rollup)。

当今使用最广泛的一些Rollup仍然没有真正去中心化,即使它们获得了数十亿美元。在撰写本文时,Optimism 仍然没有功能性欺诈证明,而 Arbitrum 可以从单个多重签名中改变。这两种协议都在努力解决这些问题,作为其开发计划的一部分,但重要的是要记住,去中心化并不是因为协议使用特定架构就一定能实现。此外,所有模块化组件之间的桥梁,主要是主权Rollup,可能面临与跨链桥梁相同的不安全性。最后,一个主要问题是在模块化堆栈的基础之上进行开发会增加复杂性;对于某些开发人员来说,这可能是一个挑战。最终,我们希望 rollup 能解决这些问题并实现充分的去中心化。然而,与此同时,单体的第 1 层也可能变得同样去中心化。

我们之前的报告讨论了一些单体式第 1 层如何使用DAG 架构在内部进行扩展。这只是一个例子,表明单体区块链正在尝试在不依赖链下组件的情况下进行创新,并且正在进行无数其他优化以最大限度地提高性能。我们不能简单地诋毁旨在解决可扩展性三角难题的新区块链设计的想法。

结论

就像以前有模块化手机一样,现在也有模块化区块链。然而,看到基于 Danksharding 的以Rollup为中心的未来的潜力表明,模块化区块链架构不太可能遭受与模块化手机相同的命运。Kindelia 和 Fuel 等执行层尤其会看到用户增长,因为它们对速度和新功能的关注将使构建在它们之上的应用程序真正具有创新性。

不幸的是,其中许多模块化设计仍未经过测试,一些模块化区块链设计可能永远不会得到广泛采用。随着 Celestia 和 Danksharding 被广泛采用,Validiums 可能会被完全淘汰。Celestia 的 主权 rollups 可能面临一些与现有第 1 层相同的桥接问题,由于安全和复杂性问题而阻碍采用。

一个去中心化、模块化的区块链未来仍然是一个漫长的过程。在此期间,单体区块链将继续发挥作用并不断创新。当我们最终达到模块化区块链被广泛采用的未来时,单体区块链的格局可能也会完全不同。尽管如此,我们需要扩容解决方案来为现有区块链提供流动性和用户服务,从长远来看,模块化区块链架构可能是实现这一目标的最佳方式。

转载自:https://learnblockchain.cn/article/5413

分析0xSplits - 收入拆分协议

技术背景

很多时候,我们需要把一份收入(金额)拆分到不同的地址,而又不想让付款人(通常是用户)承担拆分收入部分的 GAS费用, 0xSplits 的架构及解决思路值得我们参考。
本文先介绍了0xSplits 是什么,0xSplits 采用的架构是怎么样的,同时介绍了几种其他的拆分方式可能带来的问题,另外还有一些0xSplits在 Gas 优化上的做法。

0xSplits是什么

0xSplits 是链上收入拆分的协议, 它是一个智能合约,允许你将任何付款拆分到许多收款人,例如,它可以用于NFT版税。EIP-2918允许你只指定一个地址作为收款人,但如果你把这个地址设置为0xSplits地址,你就可以有很多个收款人。
0xSplits由一个主合约组成,可以创建许多子克隆合约(SplitWallet)。

  1. 你通过调用主合约创建一个新的拆分(split)
  2. 它创建一个负责接收ETH的子合约
  3. 在需要接收ETH的地方使用子合约的地址

译者注:克隆合约是使用同一份代码,创建(复制)多个出合约, 每个合约都有自己的状态。

这里是子克隆合约的代码,你可以看到,它非常简单。它可以接收ETH,并且有一个函数可以将ETH转移到主合约, 0xSplits也支持ERC-20,但省略了这部分代码

但收到的ETH如何拆分给接收者?这就是主合约的任务(为了便于阅读,代码做了修改):


所以,资金是静止不动的,直到有人明确地调用 distributeETH。但为什么有人会浪费Gas来调用这个函数呢?答案是distributorFee(分配费用)。这是在创建拆分时设置的,谁调用distributionETH就归谁。

这种激励性的代码调用是必要的,因为EVM没有周期任务(cron )或回调来定期分配资金,一切都需要由个人或链外机器人发起,distributorFee有点类似于CryptoKitties合约中的autoBirthFee。

为什么0xSplits会选择这种架构?还有,为什么不在收到资金的时候立即分发?这是我们这篇文章的主要想解决的问题。

0xSplits 架构

你可以在Etherscan找到0xSplits的代码

克隆SplitWallet合约接收付款并持有资金,直到它们被调用,将资金转移到主合约。

分销商(distributor)被激励在主合约中调用distributeEth,这将把资金从克隆合约转移到主合约中,同时也将支付/分成。

但是在这一点上,资金仍然存放在主合约中(合约有一个从收款人地址到余额的映射)。为了实际接收资金,用户必须调用主合约中的withdraw函数。

此架构的可能替代方案
现有的设定是相当复杂的:克隆合约接收付款,分销商(distributor)将这些资金从克隆合约转移到主合约,并将资金分给接收者。但是收款人仍然需要调用withdraw来接收实际拆分到的资金。所以,端到端的用户流程并不是完全自动化的(另外,有些钱会被分销商收取)。

为什么0xSplits需要如此复杂的设置?让我们来看看其他的方法,以及它们为什么不可行。

若在收到资金时进行拆分?

为什么不在收到资金的同一函数中进行拆分呢?也就是说,不在合约中保存资金, 而是立即分配,这里有2个原因:

  1. 付款人需要提供额外的Gas
  2. 它破坏了互操作性。付款人不能再直接将ETH转账(transfer)到克隆合约中。而是要求付款人将不得不调用合约上的一个特定函数(来进行拆分),这会破坏互操作性。你可能会说只要重写receive函数,但receive函数经常受2300个Gas限制,这意味着你不能在其函数中进行大量的转账。

若使用共享合约而不是克隆合约呢?

为什么没有一个共享的合约,为所有可能的拆分接收所有的付款?这将摆脱克隆(创建新合约),但它并不奏效,因为当共享合约收到付款时,它不知道付款是要进行怎样的拆分。

将distributeEth和withdraw合二为一呢?

为什么不把整个过程端到端自动化,让分销商在一个函数中执行这2个操作?主要是因为安全问题。强烈建议使用pull over push - 即让用户手动拉取他们的自己资金,而不是把资金自动推送他们。

为什么 "推(push)"被认为是一种安全风险?阅读下面的链接以获得完整的答案,但简而言之,这是因为不是所有的接收者都能保证正确处理ETH的接收。一些恶意的行为者可能会部署一个智能合约,在 receive 功能中进行回退(revert)。因此,如果至少有一个接收者回退(revert),整个操作就会回退(revert)。
参考阅读文章:Pull over Push 将转移以太坊的相关风险转移到用户身上。

如果你想出另一种替代架构,请告诉我(在评论中这里)。

我认为0xSplits为他们所针对的使用场景选择了正确的架构--这就是成为DeFi生态系统中的一个基本构件。还有其他类似的支付拆分器,它们是针对不同的使用场景,它们使用不同的架构。例如,disperse.app在收到资金时进行拆分,它可能是一个更好的一次性付款拆分工具。

0xSplits 代码

我对合约进行了重组,并将所有内容按功能分组,以方便阅读。
现在我们来看看现有的架构是如何在代码中实现的。
这里只有2个合约:SplitMain.sol和SplitWallet.sol(克隆)。其余的是库和接口。
你已经在前面看到了SplitWallet.sol的代码,但我把再次复制到这里只是为了参考。

这很简单。它可以接收ETH并将资金转账到主合约。你可能会问,如果没有 receive 功能,它如何接收ETH?答案是,"克隆 "库创建该合约的克隆,神奇地插入 receive 功能的汇编代码。

现在到了主合约 - SplitMain.sol, 这是所有行动发生的地方。

创建一个拆分合约

SplitMain.sol合约开头的函数,用于创建新的拆分。

validSplit只是验证一些东西,如:

  • 百分比的总和应该是1。
  • 收款人和百分比数组具有相同的长度。
  • 收款人地址数组需要被排序。为什么?我们很快就会知道。

如果controller是零地址,这意味着拆分没有所有者,它变得不可改变。Clones库将创建一个SplitWallet合约的克隆,并保存在构造函数中。

clone和cloneDeterministic(在上面的createSplit函数中)的区别是,确定性的部署到一个预先定义的地址(由传入的splitHash决定)。不可变(Immutable)的拆分合约使用确定性的克隆,以避免有人创建完全相同的拆分合约时时发生碰撞。

拆分(split)是由这些数据结构表示的:

使用哈希值的Gas优化

请注意,上面只保存了拆分的哈希值,而没有保存地址、收款人和distributorFee。为什么我们需要哈希值?

哈希值是用来将所有关于拆分的信息(收款人、百分比、distributorFee)合成一个字符串。

通过只存储哈希值而不是函数的所有参数,我们节省了大量的存储空间,从而节省了Gas。

但是,我们如何查找在哈希过程中丢失的信息,如recipients?我们要求这些信息被传递到需要它们的函数中。在合约中,我们只需再次对传入的参数进行散列,并与存储的散列进行比较。如果它们匹配,传入的参数就是正确的。

分销商被激励在链外记录recipients, percentages等,并将这些信息传递给所有需要它们的函数。分销商费用则是支付他们的服务的费用。

另外,我们现在明白为什么收款人地址数组需要在createSplit函数中进行排序。因为否则,哈希值将无法重现。

更新拆分的内容

用哈希值更新拆分也变得非常有效。只要更新哈希值即可。

(onlySplitController确保msg.sender == split.controller)

所有权的转移

如果一个拆分是可变的,你可以转移其所有权。

这是有两步过程:

为什么是两步程序?为了防止意外转移到一个错误的地址。两步程序使你的合约更安全一些(代价是略微多一点Gas)。

资金如何拆分分配

资金是如何分配的?让我们来看看:

我们首先通过哈希算法验证传入的args,并与存储的哈希算法进行比较。然后我们将资金转移到主合约,为分销商预留奖励,最后分配资金。

这个函数为了可读性做了大量的修改。请阅读原始的源代码以了解实际的实现。

终端用户提取资金

主合约的最后一个功能是收款人提取资金的能力。这是一个非常简单的功能。


由于ethBalances中的资金来于所有的克隆拆分合约。但是withdraw需要手动调用,机器人/分销商没有受到激励进行这个动作。

同样有趣的是,有人可以代表你调用withdraw(为你的Gas付钱)。

其他的想法

  • 0xSplits 实际上允许你有嵌套的拆分--指定一个拆分为另一个拆分的收款人。
  • 0xSplits 也适用于 ERC-20 资金的拆分。我只是省略了代码以方便阅读。
  • 不小心发送到主合约的资金是无法恢复的,因为没有办法提取多余的ETH。
  • OpenZeppelin也有一个支付拆分器,但我还没有研究过它是如何实现的,还有disperse.app,对于一次性的拆分来说可能更好。
  • 用比特币而不是用以太坊来拆分支付要容易得多。由于UTXO架构的存在,比特币几乎拥有这种开箱即用的功能。(见 Solidity Fridays)

就这样吧!让我知道你对0xSplits的看法,在评论区

转载:https://learnblockchain.cn/article/5560

Solidity Gas 优化 - 理解不同变量 Gas 差异

本文我们来尝试进行 RareSkills Gas 优化的一个挑战,完成这个挑战可以学习到更多 Gas 技巧。
以下是 Distribute 合约,合约的作用是向 4 个贡献者平均分配 1 ETH, 代码如下

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.15;

contract Distribute {
    address[4] public contributors;
    uint256 public createTime;

    constructor(address[4] memory _contributors) payable {
        contributors = _contributors;
        createTime = block.timestamp;
    }

    function distribute() external {
        require(
            block.timestamp > createTime + 1 weeks,
            "cannot distribute yet"
        );

        uint256 amount = address(this).balance / 4;
        payable(contributors[0]).transfer(amount);
        payable(contributors[1]).transfer(amount);
        payable(contributors[2]).transfer(amount);
        payable(contributors[3]).transfer(amount);
    }
}

合约代码:https://github.com/RareSkills/gas-puzzles/blob/main/contracts/Distribute.sol

这个合约默认情况下,所需 GAS 是 71953, 需要优化到 57044, 以便通过测试用例,测试用例代码在这里。
这是默认运行的截图:

在原始合约上运行测试结果

挑战的要求是仅修改合约Solidity代码来使 distribute 下降到57044, 因此不可以修改优化器或solidity版本、不可以修改测试文件,也不使用huff/yul/bytecode 层面的优化,也不变更函数属性(不能使函数为 "payable")。
在进一步阅读之前,请确保你自己先尝试解决这个难题,它真的很有趣,而且能让你学到东西。

让我们来优化吧!

让我们先做一些明显的事情。

  • 变更变量为不可变(immutable)变量,而不是存储变量(节省 10710Gas--因为不可变变量是作为常量嵌入合约字节码的,而不是从存储中读取)。
  • 用 send 取代 transfer(节省108 Gas--因为send没有检查转账是否成功)。
  • 用endTime代替currentTime (节省了69个Gas - 在构造函数中进行时间计算)

以下是修改后的合约:

这样我们就可以让Gas 节约到61066,已经比原来的好了10887,但仍比目标值高出 4千, 需继续努力。

那么,还有什么诀窍呢?

这个挑战有一个特别的技巧,应该教给你。而这是一种通过SELFDESTRUCT向地址发送ETH的老方法:

通过Selfdestruct 解谜, 仅仅这一招就为你节省了4066*的Gas,并且达到了目标!

但如果继续深入呢?

每一个理智的优化总是有其疯狂的邪恶兄弟(作弊)......让我们看看我们能把这个推到什么程度!
让合约自毁(selfdestruct)感觉像是在作弊 -- 为什么你会有一个这样的合约,在第一次调用分发后就不存在了呢?不过测试通过,所以我想这是允许的......?

让我们看看还有什么(真正的作弊)能让测试通过,但又能优化更多Gas。

  • 让contributors成为常数,而不是不可变(immutable)(节省24个Gas - 因为Hardhat地址总是相同的,所以可以这样做,对吧?
  • 使金额恒定为0.25ETH,而不是从余额中计算(节省了106个Gas -- 因为在测试中金额总是相同的,所以为什么不这样做呢?)
  • 使用Assembly来做call,而不是通常的solidityaddress.send(节省9 0 Gas)。


到目前为止使用的 Gas 是 56780

还可以更进一步吗?

把地址作为字节32的数字直接放在调用中,可以为我们多节省9个Gas!

在调用中的手动用零填充地址, 可以节约到 56771 Gas

我们继续走下去如何?

既然我们已经针对测试上做优化,那我们就进一步
为什么我们不直接返回,如果测试是 "Gas目标"?
知道Hardhat总是在相同的区块链中运行测试,我们可以把这个代码放在 distribute()函数的开头:

if (block.number == 5) return;

这样在测试中,测量 gas 时,直接返回,而不会消耗很多Gas,但仍将在 "逻辑检查" 测试中完成了的功能检查:)
不明白的同学可以回顾这里的测试用例代码,测试用例会先检查 Gas 是否达标再检查是否"逻辑"满足。


这给了我们一个惊人的21207Gas! 令人难以置信吧,不过你明白这里发生了什么......

但,这就是作弊!

是的,但谨记,这样的作弊经常在链上发生,MEV,漏洞,代码即法律,以及所有其他的东西。

还记得最近的Gas挑战比赛吗,最佳优化者获得了NFT?在那里,没有人在解决原来的问题--一切都在 "欺骗 "智能合约,以接受所需的值,并通过所需的测试,以最低的字节码和最低的Gas--你就能得到NFT。

这也给我们了一些启示,更好的测试和更好的条件可以规避这些作弊,同时让程序更安全。
对于开发我们更应该注重有效的程序,而不仅仅是巧妙地入侵系统。

转载自:https://learnblockchain.cn/article/5515

Goerli 与 Sepolia 测试网比较:哪个更好?

Goerli 和 Sepolia 是以太坊开发人员用来测试其应用程序的两个权益证明测试网。web3 开发人员在选择测试网之前应考虑多种原因,包括测试 ETH 的可用性、RPC 节点提供商支持、智能合约可用性等。

在本文中,我们将介绍每个测试网是什么,它们的技术差异,强调三个注意事项,并帮助您为您的项目选择最佳的以太坊测试网。

Goerli 测试网介绍

Goerli 于 2018 年在 ETH-Berlin 开始作为黑客马拉松项目,然后于 2019 年正式启动。它是第一个成功与 Geth、Nethermind、Besu 等客户端同步的权威证明 (PoA) 跨客户端测试网。

Goerli测试网络是一个公开开放的权益证明 (PoS) 测试网,由一个开放的验证器集维护,这意味着任何希望运行自己的测试网验证器的人都可以参与。但是,由于网络的状态很大,需要更长的同步时间和更多的存储来运行一个节点。

与 Sepolia 相比的主要区别

  • 开放验证者集
  • 无需许可即可获得共识
  • 支持跨客户端功能
  • 携带大状态并需要高存储承诺
  • 需要更长的时间才能与网络的当前状态同步

Goerli 测试网络配置

如果您要将 Goerli 区块链添加到您的钱包,这是要包括的网络信息:

Sepolia 测试网

Sepolia于 2021 年推出,是一个经过许可的权益证明测试网络,由主要由客户和测试团队控制的封闭验证器集维护。虽然开发人员可以公开使用测试网来测试和部署他们的去中心化应用程序 dDapps),但并不是每个人都可以选择运行验证节点,使其成为一个许可网络

由于 Sepolia 是一个较年轻的测试网,与 Goerli 等更成熟的测试网相比,部署的应用程序较少。它具有更小的状态和历史记录,允许更快的同步并需要最少的磁盘空间来运行节点。

与Goerli相比的主要区别

  • 封闭验证器集(权威证明配置)
  • 获得共识是允许的
  • 验证者集受到限制,主要由客户和测试团队监督
  • 支持跨客户端兼容性
  • 较小的区块链状态和历史
  • 同步速度快,需要更少的存储承诺

Sepolia链信息

如果您要将 Sepolia 区块链添加到您的钱包,这是要包括的网络信息:

要开始在 Sepolia 上构建,请注册一个免费的 Alchemy 帐户,并从 Alchemy 的公共水龙头获取免费的 SepoliaETH 代币

选择在 Sepolia 或 Goerli 上开发之前需要考虑的事项

在选择 Sepolia 测试网络或 Goerli 之前要考虑的三件事是:

  1. 测试 ETH 的可用性和成本
  2. RPC 和 API 支持
  3. 智能合约的可用性

1. 测试ETH的可用性

在 Goerli 和 Sepolia 之间进行选择时的主要考虑因素是可用性、可访问性和获取测试 ETH 代币的成本。测试 ETH 代币用于支付测试网上的 gas,web3 开发人员需要在与以太坊主网环境非常相似的环境中部署和测试他们的智能合约。

Goerli ETH是免费的吗?

从历史上看,开发人员在 Goerli 测试网上使用的测试 ETH goETH 一直是免费的,但是由于 goETH 的稀缺性,已经创建了流动性市场,开发人员可以在其中买卖 goETH 以换取真实的 ETH。

Web3 开发者仍然可以通过 Goerli Faucet 获取免费的 Goerli ETH,但是由于 goETH 的总量有硬性上限,所以每天可以领取的 goETH 数量是有限制的。

与积累 Goerli ETH 相关的稀缺性和成本是许多以太坊开发人员从 Goerli 转向 Sepolia 的原因之一。

Sepolia ETH 是免费的吗?

是的,Sepolia ETH 是免费的,可以从Sepolia ETH 水龙头领取。由于市场上可用的 sepETH 总数没有上限,因此每次从 Sepolia 水龙头请求测试 ETH 时,像 Alchemy 这样的水龙头供应商都能够为开发人员提供更多的 sepETH。

2. RPC 和 API 支持

在决定在 Sepolia 或 Goerli 上构建之前,了解支持每个测试网的 RPC 节点提供商以及它们支持的 API 端点非常重要。例如,Alchemy 等一些 RPC 提供商支持 Sepolia 测试网,而其他提供商可能不支持。此外,某些 RPC 提供程序可能缺乏对重要 API 端点的支持,例如需要 Erigon 节点的跟踪 API。

Alchemy 支持 Sepolia 上的所有核心 JSON-RPC 方法以及存档节点支持和跟踪 API 端点。未来,Alchemy 还将支持在 Sepolia 上增强的 API 方法。

3. 智能合约可用性

如果你的智能合约依赖于其他智能合约,那么你决定构建 Goerli 还是 Sepolia 将取决于依赖智能合约的部署位置。

例如,如果您的智能合约需要访问 Uniswap v3 合约,而 Uniswap 只在 Goerli 测试网上部署了他们的合约,那么您将需要在 Goerli 上部署您的智能合约,直到 Uniswap 将他们的测试网迁移到 Sepolia。

4. 其他注意事项

在 Goerli 和 Sepolia 测试网络之间进行选择时,除了智能合约的可用性和节点提供商的支持外,还应考虑网络稳定性、验证者集和以太坊基金会的长期支持等因素。

Goerli 或 Sepolia:我应该选择哪个测试网?

选择正确的测试网络是一个重要的决定,它会影响 dapp 开发的成功。每个测试网络都有自己的技术规范、功能和权衡,选择正确的网络可以节省您的时间和资源。

在部署和测试应用程序和智能合约方面,Ethereum.org 推荐 Sepolia 作为测试应用程序和智能合约的首选,因为它具有受限的验证器集和更高的稳定性保证。

另一方面,如果你想测试你的信标链验证器、节点设置、客户端版本,或者想在部署到主网络之前尝试协议升级,Goerli 是一个不错的选择。它是最接近以太坊主网的测试网,也可用于测试复杂的智能合约交互。

英文原文:https://www.alchemy.com/overviews/goerli-vs-sepolia
翻译:谷歌

智能合约安全工具-比较

介绍:

在本文中,我将解释如何使用一些智能合约安全工具(Mythril、MythX、Slither、Manticore、Security、SmartCheck)来查找和利用以太坊智能合约中的安全漏洞。文章将涵盖基本原理和高级技术,例如测试安全属性、比较这些安全工具。我们将以Capture of the Ether挑战中名为Fifty years的智能合约为例子用上面的工具测试。Letsgo!

漏洞合约代码

下面我们将这个漏洞合约作为例子测试:

pragma solidity ^0.4.21;

contract FiftyYearsChallenge {
    struct Contribution {
        uint256 amount;
        uint256 unlockTimestamp;
    }
    Contribution[] queue;
    uint256 head;

    address owner;
    function FiftyYearsChallenge(address player) public payable {
        require(msg.value == 1 ether);

        owner = player;
        queue.push(Contribution(msg.value, now + 50 years));
    }

    function isComplete() public view returns (bool) {
        return address(this).balance == 0;
    }

    function upsert(uint256 index, uint256 timestamp) public payable {
        require(msg.sender == owner);

        if (index >= head && index < queue.length) {
            // Update existing contribution amount without updating timestamp.
            Contribution storage contribution = queue[index];
            contribution.amount += msg.value;
        } else {
            // Append a new contribution. Require that each contribution unlock
            // at least 1 day after the previous one.
            require(timestamp >= queue[queue.length - 1].unlockTimestamp + 1 days);

            contribution.amount = msg.value;
            contribution.unlockTimestamp = timestamp;
            queue.push(contribution);
        }
    }

    function withdraw(uint256 index) public {
        require(msg.sender == owner);
        require(now >= queue[index].unlockTimestamp);

        // Withdraw this and any earlier contributions.
        uint256 total = 0;
        for (uint256 i = head; i <= index; i++) {
            total += queue[i].amount;

            // Reclaim storage.
            delete queue[i];
        }

        // Move the head of the queue forward so we don't have to loop over
        // already-withdrawn contributions.
        head = index + 1;

        msg.sender.transfer(total);
    }
}

开始

MythX:

MythX 是以太坊智能合约的首要安全分析服务工具,MythX 的使命是确保开发团队避免代价高昂的错误,并使以太坊成为更安全、更值得信赖的平台。
这是使用 MythX for Remix IDE 的结果演示:

  1. HIGHSWC-101 | 整数上溢和下溢
    加法运算的操作数没有得到充分的约束。因此,添加可能会导致整数溢出。通过检查输入来防止溢出或确保溢出被断言捕获。
  2. HIGHSWC-105 | 不受保护的 ETH 取款
    合约创建者以外的任意发送者可以从合约账户中取款 ETH。这很可能是一个漏洞。
  3. MEDIUMSWC-134 | 带有硬编码气体量
    的消息调用突出显示的函数调用转发固定量的气体。这是不鼓励的,因为 EVM 指令的 gas 成本在未来可能会发生变化,这可能会破坏该合约的假设。如果这样做是为了防止重入攻击,请考虑替代方法,例如检查-效果-交互模式或重入锁。

Mythril:

Mythril 是 EVM 字节码的安全分析工具。它检测为 Ethereum、Hedera、Quorum、Vechain、Roostock、Tron 和其他 EVM 兼容区块链构建的智能合约中的安全漏洞。
它使用符号执行、SMT 求解和污点分析来检测各种安全漏洞。它还用于MythX安全分析平台结合使用。

安装:

pip3 install mythril

扫描合约

myth analyze contract.sol

结果

重点是三个漏洞:

  1. 整数溢出
  2. 对可预测环境变量的依赖性
  3. 未受保护的 ETH 取款

详细细节可以看下面:

==== Integer Overflow ====
SWC ID: 101
Severity: High
Contract: FiftyYearsChallenge
Function name: constructor
PC address: 179
Estimated Gas Usage: 23146 - 109214
The binary addition can overflow.
The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.
--------------------
In file: fifrthyyear.sol:16
now + 50 years
--------------------
Initial State:
Account: [CREATOR], balance: 0x21c10c0542040001, nonce:0, storage:{}
Account: [ATTACKER], balance: 0x0, nonce:0, storage:{}
Account: [SOMEGUY], balance: 0x0, nonce:0, storage:{}
Transaction Sequence:
Caller: [CREATOR], calldata: , value: 0xde0b6b3a7640000
==== Dependence on predictable environment variable ====
SWC ID: 116
Severity: Low
Contract: FiftyYearsChallenge
Function name: withdraw(uint256)
PC address: 342
Estimated Gas Usage: 22161 - 117057
A control flow decision is made based on a predictable variable.
The block.timestamp environment variable is used in to determine a control flow decision. Note that the values of variables like coinbase, gaslimit, block number and timestamp are predictable and can be manipulated by a malicious miner. Also keep in mind that attackers know hashes of earlier blocks. Don't use any of those environment variables for random number generation or to make critical control flow decisions.
--------------------
In file: fifrthyyear.sol:43
require(now >= queue[index].unlockTimestamp)
--------------------
Initial State:
Account: [CREATOR], balance: 0x1000000000000001, nonce:0, storage:{}
Account: [ATTACKER], balance: 0x0, nonce:0, storage:{}
Account: [SOMEGUY], balance: 0x0, nonce:0, storage:{}
Transaction Sequence:
Caller: [CREATOR], calldata: fefefefefefefefefefefefeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe, value: 0xde0b6b3a7640000
Caller: [CREATOR], function: withdraw(uint256), txdata: 0x2e1a7d4d, value: 0x0
==== Unprotected Ether Withdrawal ====
SWC ID: 105
Severity: High
Contract: FiftyYearsChallenge
Function name: withdraw(uint256)
PC address: 522
Estimated Gas Usage: 22161 - 117057
Anyone can withdraw ETH from the contract account.
Arbitrary senders other than the contract creator can withdraw ETH from the contract account. This is likely to be a vulnerability.
--------------------
In file: fifrthyyear.sol:58
msg.sender.transfer(total)
--------------------
Initial State:
Account: [CREATOR], balance: 0x2181000142640001, nonce:0, storage:{}
Account: [ATTACKER], balance: 0x42101040440090000, nonce:0, storage:
Account: [SOMEGUY], balance: 0x0, nonce:0, storage:{}
Transaction Sequence:
Caller: [CREATOR], calldata: efefefefefefefefefefefefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef, value: 0xde0b6b3a7640000
Caller: [ATTACKER], function: withdraw(uint256), txdata: 0x2e1a7d4d, value: 0x0

Slither

Slither 是一个用 Python 3 编写的 Solidity 静态分析框架。它运行一套漏洞检测器,打印有关合约细节的视觉信息,并提供一个 API 来轻松编写自定义分析。Slither 使开发人员能够发现漏洞,增强他们的代码理解力,并快速构建自定义分析原型。

安装:

使用pip
pip3 install slither-analyzer
使用git
git clone https://github.com/crytic/slither.git && cd slither
python3 setup.py install
Scan 命令
slither contract.sol


下面是扫描结果:

INFO:Detectors:
FiftyYearsChallenge.isComplete() (fifrthyyear.sol#19-21) uses a dangerous strict equality:
        - address(this).balance == 0 (fifrthyyear.sol#20)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities
INFO:Detectors:
Pragma version^0.4.21 (fifrthyyear.sol#1) allows old versions
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity
INFO:Detectors:
isComplete() should be declared external:
        - FiftyYearsChallenge.isComplete() (fifrthyyear.sol#19-21)
upsert(uint256,uint256) should be declared external:
        - FiftyYearsChallenge.upsert(uint256,uint256) (fifrthyyear.sol#23-39)
withdraw(uint256) should be declared external:
        - FiftyYearsChallenge.withdraw(uint256) (fifrthyyear.sol#41-59)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-as-external

Securify:

Securify 2.0 是以太坊基金会和ChainSecurity支持的以太坊智能合约安全扫描器。Securify 背后的核心研究是在苏黎世联邦理工学院的安全、可靠和智能系统实验室进行的。
有两种使用 Securify 的方法。在你的计算机安装它或使用网络应用程序,如果你想在“这里”安装它,你可以查看本指南。如果您想使用网络应用程序,
这里是链接:https ://securify.chainsecurity.com/

SmartCheck:

SmartCheck 是一种可扩展的静态分析工具,用于发现以 Solidity 编程语言编写的以太坊智能合约中的漏洞和其他代码问题。作为 Securify,您可以将 SmartCheck 作为 Web 应用程序使用或将其安装在您的电脑中。

确保你的机器上安装了 nodejs 和 npm

npm install @smartdec/smartcheck -g

扫描

smartcheck -p contract.sol


这是在网站上扫描的示例:

Manticore:

Manticore 是一个用于分析智能合约和二进制文件的符号执行工具。

安装系统依赖

sudo apt-get update && sudo apt-get install python3 python3-dev python3-pip -y

安装 Manticore 及其依赖

sudo pip3 install manticore[native]

结果分析:

我认为比较这些工具的最佳方法是扫描多个不同的合同并分析每次扫描的结果。这是我使用工具(MythX、Mythril、Securify、SmartCheck、Slither)选择 3 个随机智能合约进行的扫描。结果如下表所示:

结论:

结果显示,Mythx 总共发现了 18 个不同的错误,这明显高于其他对中等错误具有高识别度的工具。另一方面,Securify 在关键错误检测方面得分最高。
最后,每个工具都有特定的方法来检查智能合约的漏洞(静态分析、符号分析、正式合约验证器……),我们的实验只关注 3 个智能合约,为了得到更合理的比较,最好是分析更多合同(例如 1000S-C)

转载自:https://learnblockchain.cn/article/5289