Vyper logo

yper

语言基础Vyper 中文文档

环境变量与常量

掌握区块链上下文变量、self 引用,以及全局常量的定义方式。

这一页定义了 Vyper 里最常用的上下文信息来源: 区块链环境变量、self 引用,以及在模块级定义的自定义常量。

环境变量

环境变量始终存在于命名空间中,主要用于暴露当前区块、交易和调用上下文的信息。 它们不需要声明,也不能被重写。

区块与交易属性

名称类型含义
block.coinbaseaddress当前区块出块者地址
block.difficultyuint256当前区块难度
block.prevrandaobytes32Beacon 链提供的随机性信标
block.numberuint256当前区块号
block.gaslimituint256当前区块 gas 上限
block.basefeeuint256当前区块的 base fee
block.blobbasefeeuint256当前区块 blob gas 的 base fee
block.prevhashbytes32等价于 blockhash(block.number - 1)
block.timestampuint256当前区块的 Unix 时间戳
chain.iduint256当前链的 Chain ID
msg.dataBytes调用携带的 calldata
msg.gasuint256当前剩余 gas
msg.manauint256msg.gas 的别名
msg.senderaddress当前调用的直接发送者
msg.valueuint256随消息发送的 wei 数量
tx.originaddress整条调用链的原始交易发送者
tx.gaspriceuint256当前交易的 gas price(wei)

关于 block.prevrandao

block.prevrandaoblock.difficulty 操作码的别名。根据 EIP-4399,在 2022 年 9 月 15 日 以太坊完成 Paris 升级(The Merge)之后,block.difficulty 已被视为弃用语义, 新代码应优先使用 block.prevrandao

msg.data 需要配合 slice() 显式截取 calldata 片段。如果截取范围超出边界会直接抛错, 长度则可以通过 len(msg.data) 判断。

vyper

@external
def first_four_bytes() -> Bytes[4]:
    assert len(msg.data) >= 4, "calldata too short"
    return slice(msg.data, 0, 4)

self 变量

self 是一个特殊环境变量,用来在合约内部引用当前合约自身。它既能表示当前合约地址, 也能访问状态变量和内部函数。

名称类型含义
selfaddress当前合约地址
self.balanceuint256当前合约余额

访问状态变量

在 Vyper 中,函数内部访问状态变量必须显式写成 self.<name>

vyper

stored_value: uint256

@external
def set_value(value: uint256) -> bool:
    self.stored_value = value
    return True

@external
@view
def get_value() -> uint256:
    return self.stored_value

调用内部函数

self 也用于调用内部函数,这能明确区分“当前合约内部逻辑”与“外部合约调用”:

vyper

@internal
def _times_two(amount: uint256) -> uint256:
    return amount * 2

@external
def calculate(amount: uint256) -> uint256:
    return self._times_two(amount)

自定义常量

Vyper 允许在模块级定义自定义常量。常量使用 constant(...) 关键字声明, 一旦定义就不能被修改。

vyper

TOTAL_SUPPLY: constant(uint256) = 10_000_000
total_supply: public(uint256)

@deploy
def __init__():
    self.total_supply = TOTAL_SUPPLY

常量适合保存以下内容:

  • 协议固定参数,例如费率分母、最大供应量、精度缩放因子。
  • 与链无关、部署后不会变化的配置。
  • 希望在编译期就被内联并固定下来的值。

如果某个值是在部署时确定,但部署后不再变化,应优先考虑 immutable。 它的约束与写法在作用域与声明里单独展开。

使用建议

  • 对随机性或区块属性敏感的逻辑,优先先判断输入边界,再读取环境变量。
  • 除了读地址和余额,self 最重要的用途其实是明确“这是状态访问”或“这是内部调用”。
  • 对不会变化的协议参数使用 constant,对部署时确定的配置使用 immutable,不要把两者混用。
  • 谨慎使用 tx.origin。它暴露的是整条调用链最初的发送者,通常不适合作为权限控制依据。