NatSpec 元数据

Vyper 合约可以使用一种特殊的 docstring 格式来提供函数、返回值变量等的丰富文档。这种特殊格式被称为以太坊自然语言规范格式 (NatSpec)。

该文档分为面向开发者的消息和面向最终用户的消息。这些消息可能会在最终用户(人)与合约交互(例如,签署交易)时显示给最终用户。

示例

Vyper 使用 doxygen 符号格式支持合约和外部函数的结构化文档。

注意

编译器不解析内部函数的 docstring。欢迎您在内部函数的注释中使用 NatSpec,但它们不会被处理或包含在编译器输出中。

"""
@title A simulator for Bug Bunny, the most famous Rabbit
@license MIT
@author Warned Bros
@notice You can use this contract for only the most basic simulation
@dev
    Simply chewing a carrot does not count, carrots must pass
    the throat to be considered eaten
"""

@external
@payable
def doesEat(food: string[30], qty: uint256) -> bool:
    """
    @notice Determine if Bugs will accept `qty` of `food` to eat
    @dev Compares the entire string and does not rely on a hash
    @param food The name of a food to evaluate (in English)
    @param qty The number of food items to evaluate
    @return True if Bugs will eat it, False otherwise
    """

标签

所有标签都是可选的。下表解释了每个 NatSpec 标签的用途及其使用位置

标签

描述

上下文

@title

描述合约的标题

合约

@license

合约的许可证

合约

@author

作者姓名

合约、函数

@notice

向最终用户解释此功能

合约、函数

@dev

向开发人员解释任何额外的细节

合约、函数

@param

记录单个参数

函数

@return

记录一个或所有返回值变量

函数

@custom:...

自定义标签,语义由应用程序定义

合约、函数

一些规则/限制

  1. 单个标签描述可以跨越多行。所有行之间的空格被解释为单个空格。

  2. 如果 docstring 包含没有 NatSpec 标签,它会被解释为 @notice.

  3. 每次使用 @param 后面必须是输入参数的名称。包含无效或重复的参数名称会引发 NatSpecSyntaxException.

  4. 首选使用 @return 是每个输出值一个条目,但您也可以一次为所有输出使用它。包含比输出值更多的 @return 值会引发 NatSpecSyntaxException.

文档输出

当被编译器解析时,如上例中的文档将生成两个不同的 JSON 输出。一个旨在作为最终用户在执行函数时的通知,另一个旨在供开发者使用。

如果上面的合约保存为 carrots.vy 那么您可以使用以下命令生成文档

vyper -f userdoc,devdoc carrots.vy

用户文档

上面的文档将生成以下用户文档 JSON 作为输出

{
  "methods": {
    "doesEat(string,uint256)": {
      "notice": "Determine if Bugs will accept `qty` of `food` to eat"
    }
  },
  "notice": "You can use this contract for only the most basic simulation"
}

请注意,查找方法的键是合约 ABI 中定义的函数规范签名,而不仅仅是函数名称。

开发者文档

除了用户文档文件之外,还应生成一个开发者文档 JSON 文件,它应如下所示

{
  "author": "Warned Bros",
  "license": "MIT",
  "details": "Simply chewing a carrot does not count, carrots must pass the throat to be considered eaten",
  "methods": {
    "doesEat(string,uint256)": {
      "details" : "Compares the entire string and does not rely on a hash",
      "params": {
        "food": "The name of a food to evaluate (in English)",
        "qty": "The number of food items to evaluate"
      },
      "returns": {
        "_0": "True if Bugs will eat it, False otherwise"
      }
    }
  },
  "title" : "A simulator for Bug Bunny, the most famous Rabbit"
}