与 Solidity 比较

本节是那些正在考虑使用Vyper编程语言开发智能合约的人的参考。该部分主要对比了Vyper与Solidity的对比; 概览,合理的推理,为什么Vyper不包括以下传统的面向对象编程(OOP)概念:

Modifiers

在Solidity中,你可以使用修饰器编写函数。例如,以下函数`changeOwner`将在一个名为`onlyBy`的修饰器中运行代码,作为其执行的一部分。

  1. function changeOwner(address _newOwner)
  2. public
  3. onlyBy(owner)
  4. {
  5. owner = _newOwner;
  6. }

正如我们在下面看到的,名为`onlyBy`的修饰器强制执行与所有权相关的规则。虽然修饰器很强大(能够改变函数体中发生的事情),但它们也可能导致误导性的代码执行。例如,确保`changeOwner`函数逻辑的唯一方法是每次实现代码时检查并测试`onlyBy`修饰器。显然,如果将来更改修改器,则调用它的函数可能会产生与最初预期不同的结果。

  1. modifier onlyBy(address _account)
  2. {
  3. require(msg.sender == _account);
  4. _;
  5. }

总的来说,修饰器的通常用例是在函数执行之前执行单个检查。鉴于这种情况,Vyper的建议是完全取消修饰器,并简单地使用内联检查和断言作为函数的一部分。这样做将提高审计能力和可读性,因为Vyper函数将在明显的视线中遵循逻辑内联序列,而不必引用已在别处编写的修饰器代码。

类继承

继承允许程序员通过从现有软件库中获取预先存在的功能,属性和行为来利用预先编写的代码。继承功能强大,可以促进代码的重用。Solidity支持多重继承以及多态,虽然这些被认为是面向对象编程的一些最重要的特性,但Vyper并不支持它们。Vyper坚持认为继承的实现要求编码人员和审计人员在多个文件之间跳转,以便了解程序正在做什么。Vyper还了解优先级规则以及多个继承如何使代码过于复杂而无法理解。鉴于Solidity 关于继承的文档给出了多重继承为何有问题的例子,这是一个公平的陈述。

内联汇编

内联汇编为开发人员提供了以低级别访问以太坊虚拟机(EVM)的机会。使用内联汇编代码(在更高级别的源代码中)时,开发人员可以通过直接访问EVM操作码指令来执行操作。例如,以下内联汇编代码通过使用EVM操作码mload在内存位置0x80处添加3。

  1. 3 0x80 mload add 0x80 mstore

如前所述,Vyper致力于为开发人员和代码审计人员提供最易读的代码。虽然内联汇编可以提供强大的细粒度控制,但Vyper编程语言不支持它。

函数重载

具有相同名称和不同参数选项的多个函数定义会导致在任何给定时间调用哪个函数时会产生很多混淆。随着函数重载,编写误导代码会更容易( foo(“hello”)记录“hello”但foo(“hello”,“world”)窃取你的资金。)函数重载的另一个问题是它使代码更难以搜索,因为你必须跟踪哪个调用指的是哪个功能。

变量类型转换

类型转换是一种允许程序员将变量从一种数据类型转换为另一种数据类型的机制。

前置条件和后置条件

Vyper明确处理前置条件,后置条件和状态更改。虽然这会产生冗余代码,但它也允许最大的可读性和安全性。在Vyper中编写智能合约时,开发人员应遵守以下3点。理想情况下,应仔细考虑3个点中的每个点,然后在代码中进行详细记录。这样做将改进代码的设计,最终使代码更具可读性和可审计性。

  • 条件 - 以太坊状态变量的当前状态/条件是什么

  • 效果 - 这个智能合约代码对执行状态变量的条件有什么影响,即什么会影响,什么不会受到影响?这些影响是否与智能合约的意图一致?

  • 交互 - 现在已经详尽地处理了前两个步骤,现在是运行代码的时候了。在部署之前,逻辑上逐步执行代码并考虑执行代码的所有可能的永久结果,后果和方案,包括与其他合约的交互。