内置函数¶
Vyper 提供了一组在所有合约的全局命名空间中可用的内置函数。
位运算¶
- bitwise_and(x: uint256, y: uint256) uint256 ¶
执行“按位与”运算。输出的每个位为 1,如果
x
和y
的相应位为 1,否则为 0。@external @view def foo(x: uint256, y: uint256) -> uint256: return bitwise_and(x, y)
>>> ExampleContract.foo(31337, 8008135) 12353
注意
此函数已从 0.3.4 版开始弃用。请改用 &
运算符。
- bitwise_not(x: uint256) uint256 ¶
返回
x
的按位补码 - 通过将每个 1 替换为 0 以及每个 0 替换为 1 获得的数字。@external @view def foo(x: uint256) -> uint256: return bitwise_not(x)
>>> ExampleContract.foo(0) 115792089237316195423570985008687907853269984665640564039457584007913129639935
注意
此函数已从 0.3.4 版开始弃用。请改用 ~
运算符。
- bitwise_or(x: uint256, y: uint256) uint256 ¶
执行“按位或”运算。输出的每个位为 0,如果
x
和y
的相应位为 0,否则为 1。@external @view def foo(x: uint256, y: uint256) -> uint256: return bitwise_or(x, y)
>>> ExampleContract.foo(31337, 8008135) 8027119
注意
此函数已从 0.3.4 版开始弃用。请改用 |
运算符。
- bitwise_xor(x: uint256, y: uint256) uint256 ¶
执行“按位异或”运算。输出的每个位与
x
中的相应位相同,如果y
中的该位为 0,并且是x
中该位的补码,如果y
中的该位为 1。@external @view def foo(x: uint256, y: uint256) -> uint256: return bitwise_xor(x, y)
>>> ExampleContract.foo(31337, 8008135) 8014766
注意
此函数已从 0.3.4 版开始弃用。请改用 ^
运算符。
- shift(x: int256 | uint256, _shift: integer) uint256 ¶
返回将位移动
_shift
位的x
。正的_shift
值等于左移,负值是右移。@external @view def foo(x: uint256, y: int128) -> uint256: return shift(x, y)
>>> ExampleContract.foo(2, 8) 512
注意
此函数已从 0.3.8 版开始弃用。请改用 <<
和 >>
运算符。
链交互¶
Vyper 有三个用于创建合约的内置函数;所有三个合约创建内置函数都依赖于要部署的代码已存储在链上,但它们在调用与部署开销以及是否调用要部署的合约的构造函数方面有所不同。以下列表简要总结了它们之间的差异。
create_minimal_proxy_to(target: address, ...)
创建一个不可变的代理到
target
调用开销大(每次调用都会产生一个
DELEGATECALL
开销),创建开销小(因为它只部署EIP-1167
转发器字节码)没有调用构造函数的功能
不检查
target
处是否有代码(允许以反事实的方式部署代理)
create_copy_of(target: address, ...)
创建存储在
target
处的运行时代码的逐字节复制调用开销小(没有
DELEGATECALL
开销),创建开销大(每部署一个字节 200 gas)没有调用构造函数的功能
执行
EXTCODESIZE
检查以检查target
处是否有代码
create_from_blueprint(target: address, ...)
使用存储在
target
处的 initcode 部署合约调用开销小(没有
DELEGATECALL
开销),创建开销大(每部署一个字节 200 gas)调用构造函数,要求部署一个特殊的“蓝图”合约
执行
EXTCODESIZE
检查以检查target
处是否有代码
- create_minimal_proxy_to(target: address, value: uint256 = 0[, salt: bytes32]) address ¶
部署一个小的、符合 EIP1167 的“最小代理合约”,该合约复制了
target
处合约的逻辑,但有自己的状态,因为对target
的每次调用都是使用DELEGATECALL
对target
进行的。对最终用户而言,这应该与使用与target
相同代码的独立部署的合约没有区别。target
: 要代理到的合约的地址value
: 要发送到新合约地址的 wei 值(可选,默认值为 0)salt
: 确定性CREATE2
操作码使用的bytes32
值(可选,如果未提供,则使用CREATE
)
返回新创建的代理合约的地址。如果创建操作失败(例如,在
CREATE2
冲突的情况下),执行将回滚。@external def foo(target: address) -> address: return create_minimal_proxy_to(target)
注意
至关重要的是,在 target
处部署的合约是您了解并信任的代码,并且不实现 selfdestruct
操作码或具有可升级的代码,因为这会影响代理合约的操作。
注意
没有运行时检查以确保 target
处已部署代码(因为代理可以以反事实的方式部署)。大多数应用程序可能希望插入此检查。
注意
在 0.3.4 版之前,此函数名为 create_forwarder_to
。
- create_copy_of(target: address, value: uint256 = 0[, salt: bytes32]) address ¶
创建
target
处运行时代码的物理副本。在target
处的代码会逐字节复制到一个新部署的合约中。target
: 要复制的合约的地址value
: 要发送到新合约地址的 wei 值(可选,默认值为 0)salt
: 确定性CREATE2
操作码使用的bytes32
值(可选,如果未提供,则使用CREATE
)
返回已创建的合约的地址。如果创建操作失败(例如,在
CREATE2
冲突的情况下),执行将回滚。如果target
处没有代码,执行将回滚。@external def foo(target: address) -> address: return create_copy_of(target)
注意
create_copy_of
的实现假设 target
处的代码小于 16MB。虽然这远大于 EIP-170 的 24KB 限制,但它是一个保守的尺寸限制,旨在防止部署者合约在 EIP-170 限制解除的情况下出现问题。如果 target
处的代码大于 16MB,则 create_copy_of
的行为未定义。
- create_from_blueprint(target: address, *args, value: uint256 = 0, raw_args: bool = False, code_offset: int = 0[, salt: bytes32]) address ¶
将
target
的代码复制到内存中并作为初始化代码执行。换句话说,此操作将target
中的代码解释为初始化代码,而不是常规的运行时代码。*args
被解释为构造函数参数,并被 ABI 编码,并在执行初始化代码时包含在内。target
: 要调用的蓝图的地址*args
: 要转发到初始化代码的构造函数参数。value
: 要发送到新合约地址的 wei 值(可选,默认值为 0)raw_args
: 如果为True
,*args
必须是一个Bytes[...]
参数,它将被解释为一个原始字节缓冲区,转发到创建操作(例如,如果预 ABI 编码数据从其他地方传递进来)。(可选,默认值为False
)code_offset
:EXTCODECOPY
开始的偏移量(可选,默认值为 0)salt
: 确定性CREATE2
操作码使用的bytes32
值(可选,如果未提供,则使用CREATE
)
返回创建的合约的地址。如果创建操作失败(例如,在
CREATE2
冲突的情况下),执行将回滚。如果code_offset >= target.codesize
(例如,如果target
中没有代码),执行将回滚。@external def foo(blueprint: address) -> address: arg1: uint256 = 18 arg2: String[32] = "some string" return create_from_blueprint(blueprint, arg1, arg2, code_offset=1)
注意
要正确部署蓝图合约,必须使用特殊的部署字节码。 vyper -f blueprint_bytecode
的输出将产生部署与 ERC-5202 兼容的蓝图的字节码。
警告
建议使用 ERC-5202 前缀 0xFE7100
部署蓝图,以防止它们被当作常规合约调用。这对于工厂来说尤其重要,因为工厂的构造函数有副作用(包括 SELFDESTRUCT
!),因为这些副作用可能会被任何直接调用蓝图合约的人执行。提供 code_offset=
关键字参数是为了启用这种模式
@external
def foo(blueprint: address) -> address:
# `blueprint` is a blueprint contract with some known preamble b"abcd..."
return create_from_blueprint(blueprint, code_offset=<preamble length>)
- raw_call(to: address, data: Bytes, max_outsize: uint256 = 0, gas: uint256 = gasLeft, value: uint256 = 0, is_delegate_call: bool = False, is_static_call: bool = False, revert_on_failure: bool = True) Bytes[max_outsize] ¶
调用指定的以太坊地址。
to
: 要调用的目标地址data
: 要发送到目标地址的数据max_outsize
: 从调用返回的字节数组的最大长度。如果返回的调用数据超过此长度,则仅返回此数量的字节。(可选,默认值为0
)gas
: 附加到调用的汽油量。(可选,默认为msg.gas
)。value
: 要发送到该地址的 wei 值(可选,默认为0
)is_delegate_call
: 如果为True
,则调用将作为DELEGATECALL
发送(可选,默认为False
)is_static_call
: 如果为True
,则调用将作为STATICCALL
发送(可选,默认为False
)revert_on_failure
: 如果为True
,则调用将在失败时回滚,否则将返回success
(可选,默认为True
)
注意
返回调用返回的数据作为
Bytes
列表,max_outsize
作为最大长度。返回数据的实际大小可能小于max_outsize
。可以使用len
来获取实际大小。如果省略或设置为
0
,则不返回任何内容。如果
revert_on_failure
设置为False
,则返回一个包含返回值的元组中的success
。@external @payable def foo(_target: address) -> Bytes[32]: response: Bytes[32] = raw_call(_target, method_id("someMethodName()"), max_outsize=32, value=msg.value) return response @external @payable def bar(_target: address) -> Bytes[32]: success: bool = False response: Bytes[32] = b"" x: uint256 = 123 success, response = raw_call( _target, _abi_encode(x, method_id=method_id("someMethodName(uint256)")), max_outsize=32, value=msg.value, revert_on_failure=False ) assert success return response
注意
关于“转发所有汽油”,请注意,虽然 Vyper 会向调用提供
msg.gas
,但实际上,在 EVM 上转发所有剩余汽油有一些细微之处,这些细微之处超出了本文档的范围,可能会发生变化。例如,请参阅 EIP-150 中关于“除了六十四分之一以外的所有汽油”的语言。
- raw_log(topics: bytes32[4], data: Union[Bytes, bytes32]) None ¶
提供对
LOG
操作码的低级访问,发出日志,而无需指定 ABI 类型。topics
:bytes32
日志主题列表。此数组的长度决定了使用哪个操作码。data
: 要包含在日志中的未索引事件数据。可以作为Bytes
或bytes32
提供。
@external def foo(_topic: bytes32, _data: Bytes[100]): raw_log([_topic], _data)
- raw_revert(data: Bytes) None ¶
提供对
REVERT
操作码的低级访问,使用指定的数据返回回滚执行。data
: 表示导致回滚的错误消息的数据。
@external def foo(_data: Bytes[100]): raw_revert(_data)
密码学¶
- ecadd(a: uint256[2], b: uint256[2]) uint256[2] ¶
将 Alt-BN128 曲线上的两个点加在一起。
@external @view def foo(x: uint256[2], y: uint256[2]) -> uint256[2]: return ecadd(x, y)
>>> ExampleContract.foo([1, 2], [1, 2]) [ 1368015179489954701390400359078579693043519447331113978918064868415326638035, 9918110051302171585080402603319702774565515993150576347155970296011118125764, ]
- ecmul(point: uint256[2], scalar: uint256) uint256[2] ¶
取 Alt-BN128 曲线上的一个点 (
p
) 和一个标量值 (s
),并返回将该点自身加上s
次的结果,即p * s
。point
: 要乘以的点scalar
: 标量值
@external @view def foo(point: uint256[2], scalar: uint256) -> uint256[2]: return ecmul(point, scalar)
>>> ExampleContract.foo([1, 2], 3) [ 3353031288059533942658390886683067124040920775575537747144343083137631628272, 19321533766552368860946552437480515441416830039777911637913418824951667761761, ]
- ecrecover(hash: bytes32, v: uint256 | uint8, r: uint256 | bytes32, s: uint256 | bytes32) address ¶
从给定的椭圆曲线签名中恢复与公钥关联的地址。
r
: 签名的前 32 个字节s
: 签名的后 32 个字节v
: 签名的最后 1 个字节
返回关联的地址,或在出错时返回
empty(address)
。注意
在 Vyper
0.3.10
之前,ecrecover
函数可能会为ecrecover
的无效输入返回一个未定义的值(可能非零)。有关更多信息,请参见 GHSA-f5x6-7qgp-jhf3。@external @view def foo(hash: bytes32, v: uint8, r:bytes32, s:bytes32) -> address: return ecrecover(hash, v, r, s) @external @view def foo(hash: bytes32, v: uint256, r:uint256, s:uint256) -> address: return ecrecover(hash, v, r, s)
>>> ExampleContract.foo('0x6c9c5e133b8aafb2ea74f524a5263495e7ae5701c7248805f7b511d973dc7055', 28, 78616903610408968922803823221221116251138855211764625814919875002740131251724, 37668412420813231458864536126575229553064045345107737433087067088194345044408 ) '0x9eE53ad38Bb67d745223a4257D7d48cE973FeB7A'
- keccak256(_value) bytes32 ¶
返回给定值的
keccak256
哈希值。_value
: 要哈希的值。可以是String
、Bytes
或bytes32
。
@external @view def foo(_value: Bytes[100]) -> bytes32 return keccak256(_value)
>>> ExampleContract.foo(b"potato") 0x9e159dfcfe557cc1ca6c716e87af98fdcb94cd8c832386d0429b2b7bec02754f
- sha256(_value) bytes32 ¶
返回给定值的
sha256
(SHA2 256 位输出)哈希值。_value
: 要哈希的值。可以是String
、Bytes
或bytes32
。
@external @view def foo(_value: Bytes[100]) -> bytes32 return sha256(_value)
>>> ExampleContract.foo(b"potato") 0xe91c254ad58860a02c788dfb5c1a65d6a8846ab1dc649631c7db16fef4af2dec
数据操作¶
- concat(a, b, *args) Union[Bytes, String] ¶
取 2 个或更多个类型为
bytesM
、Bytes
或String
的字节数组,并将它们组合成一个值。如果输入参数是
String
,则返回类型是String
。否则返回类型是Bytes
。@external @view def foo(a: String[5], b: String[5], c: String[5]) -> String[100]: return concat(a, " ", b, " ", c, "!")
>>> ExampleContract.foo("why","hello","there") "why hello there!"
- convert(value, type_) Any ¶
将变量或字面量从一种类型转换为另一种类型。
value
: 要转换的值type_
: 要转换到的目标类型(例如,bool
、decimal
、int128
、uint256
或bytes32
)
返回
type_
指定类型的的值。有关可用类型转换的更多详细信息,请参见 类型转换。
- uint2str(value: unsigned integer) String ¶
返回无符号整数的字符串表示形式。
value
: 要转换的无符号整数。
返回
value
的字符串表示形式。@external @view def foo(b: uint256) -> String[78]: return uint2str(b)
>>> ExampleContract.foo(420) "420"
- extract32(b: Bytes, start: uint256, output_type=bytes32) Any ¶
从
Bytes
列表中提取值。b
: 要从中提取的Bytes
列表start
: 要从中提取的起点output_type
: 输出类型 (bytesM
、integer
或address
)。默认为bytes32
。
返回
output_type
指定类型的的值。@external @view def foo(b: Bytes[32]) -> address: return extract32(b, 0, output_type=address)
>>> ExampleContract.foo("0x0000000000000000000000009f8F72aA9304c8B593d555F12eF6589cC3A579A2") "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2"
- slice(b: Union[Bytes, bytes32, String], start: uint256, length: uint256) Union[Bytes, String] ¶
复制字节列表并返回指定的切片。
b
: 要切片的 valuestart
: 切片的起始位置length
: 切片的长度
如果被切片的 value 是
Bytes
或bytes32
,则返回类型为Bytes
。如果它是String
,则返回类型为String
。@external @view def foo(s: String[32]) -> String[5]: return slice(s, 4, 5)
>>> ExampleContract.foo("why hello! how are you?") "hello"
数学¶
- abs(value: int256) int256 ¶
返回有符号整数的绝对值。
value
: 要返回绝对值的整数
@external @view def foo(value: int256) -> int256: return abs(value)
>>> ExampleContract.foo(-31337) 31337
- ceil(value: decimal) int256 ¶
将小数向上舍入到最接近的整数。
value
: 要向上舍入的小数值
@external @view def foo(x: decimal) -> int256: return ceil(x)
>>> ExampleContract.foo(3.1337) 4
- epsilon(typename) Any ¶
返回小数类型的最小非零值。
typename
: 小数类型的名称(目前只有decimal
)
@external @view def foo() -> decimal: return epsilon(decimal)
>>> ExampleContract.foo() Decimal('1E-10')
- floor(value: decimal) int256 ¶
将小数向下舍入到最接近的整数。
value
: 要向下舍入的小数值
@external @view def foo(x: decimal) -> int256: return floor(x)
>>> ExampleContract.foo(3.1337) 3
- max(a: numeric, b: numeric) numeric ¶
返回
a
和b
中较大的值。输入值可以是任何数字类型,只要它们都是相同类型。输出值的类型与输入值的类型相同。@external @view def foo(a: uint256, b: uint256) -> uint256: return max(a, b)
>>> ExampleContract.foo(23, 42) 42
- max_value(type_) numeric ¶
返回由
type_
指定的数字类型的最大值(例如,int128
、uint256
、decimal
)。@external @view def foo() -> int256: return max_value(int256)
>>> ExampleContract.foo() 57896044618658097711785492504343953926634992332820282019728792003956564819967
- min(a: numeric, b: numeric) numeric ¶
返回
a
和b
中较小的值。输入值可以是任何数字类型,只要它们都是相同类型。输出值的类型与输入值的类型相同。@external @view def foo(a: uint256, b: uint256) -> uint256: return min(a, b)
>>> ExampleContract.foo(23, 42) 23
- min_value(type_) numeric ¶
返回由
type_
指定的数字类型的最小值(例如,int128
、uint256
、decimal
)。@external @view def foo() -> int256: return min_value(int256)
>>> ExampleContract.foo() -57896044618658097711785492504343953926634992332820282019728792003956564819968
- pow_mod256(a: uint256, b: uint256) uint256 ¶
返回
a ** b % (2 ** 256)
的结果。此方法用于执行不带溢出检查的指数运算。
@external @view def foo(a: uint256, b: uint256) -> uint256: return pow_mod256(a, b)
>>> ExampleContract.foo(2, 3) 8 >>> ExampleContract.foo(100, 100) 59041770658110225754900818312084884949620587934026984283048776718299468660736
- sqrt(d: decimal) decimal ¶
返回提供的小数的平方根,使用巴比伦平方根算法。
@external @view def foo(d: decimal) -> decimal: return sqrt(d)
>>> ExampleContract.foo(9.0) 3.0
- isqrt(x: uint256) uint256 ¶
返回提供整数的(整数)平方根,使用巴比伦平方根算法。舍入模式是向下舍入到最接近的整数。例如,
isqrt(101) == 10
。@external @view def foo(x: uint256) -> uint256: return isqrt(x)
>>> ExampleContract.foo(101) 10
- uint256_addmod(a: uint256, b: uint256, c: uint256) uint256 ¶
返回
(a + b) % c
的模。如果c == 0
,则会回滚。由于此内置函数旨在提供对底层ADDMOD
操作码的访问,因此根据 EVM 规范,此操作的所有中间计算都不受2 ** 256
模的影响。@external @view def foo(a: uint256, b: uint256, c: uint256) -> uint256: return uint256_addmod(a, b, c)
>>> (6 + 13) % 8 3 >>> ExampleContract.foo(6, 13, 8) 3
- uint256_mulmod(a: uint256, b: uint256, c: uint256) uint256 ¶
返回
(a * b) % c
的模。如果c == 0
,则会回滚。由于此内置函数旨在提供对底层MULMOD
操作码的访问,因此根据 EVM 规范,此操作的所有中间计算都不受2 ** 256
模的影响。@external @view def foo(a: uint256, b: uint256, c: uint256) -> uint256: return uint256_mulmod(a, b, c)
>>> (11 * 2) % 5 2 >>> ExampleContract.foo(11, 2, 5) 2
- unsafe_add(x: integer, y: integer) integer ¶
将
x
和y
相加,不检查溢出。x
和y
必须都是相同类型的整数。如果结果超过输入类型的边界,它将被包装。@external @view def foo(x: uint8, y: uint8) -> uint8: return unsafe_add(x, y) @external @view def bar(x: int8, y: int8) -> int8: return unsafe_add(x, y)
>>> ExampleContract.foo(1, 1) 2 >>> ExampleContract.foo(255, 255) 254 >>> ExampleContract.bar(127, 127) -2
注意
性能说明:对于 EVM 的本机字类型 uint256
和 int256
,这将编译为单个 ADD
指令,因为 EVM 本机地包装了 256 位字上的加法。
- unsafe_sub(x: integer, y: integer) integer ¶
将
x
和y
相减,不检查溢出。x
和y
必须都是相同类型的整数。如果结果下溢出输入类型的边界,它将被包装。@external @view def foo(x: uint8, y: uint8) -> uint8: return unsafe_sub(x, y) @external @view def bar(x: int8, y: int8) -> int8: return unsafe_sub(x, y)
>>> ExampleContract.foo(4, 3) 1 >>> ExampleContract.foo(0, 1) 255 >>> ExampleContract.bar(-128, 1) 127
注意
性能说明:对于 EVM 的原生字类型 uint256
和 int256
,这将编译成单个 SUB
指令,因为 EVM 原生支持对 256 位字进行减法运算。
- unsafe_mul(x: integer, y: integer) integer ¶
将
x
和y
相乘,不检查溢出。x
和y
必须都是相同类型的整数。如果结果超出输入类型的范围,它将被截断。@external @view def foo(x: uint8, y: uint8) -> uint8: return unsafe_mul(x, y) @external @view def bar(x: int8, y: int8) -> int8: return unsafe_mul(x, y)
>>> ExampleContract.foo(1, 1) 1 >>> ExampleContract.foo(255, 255) 1 >>> ExampleContract.bar(-128, -128) 0 >>> ExampleContract.bar(127, -128) -128
注意
性能说明:对于 EVM 的原生字类型 uint256
和 int256
,这将编译成单个 MUL
指令,因为 EVM 原生支持对 256 位字进行乘法运算。
- unsafe_div(x: integer, y: integer) integer ¶
将
x
除以y
,不检查除以零。x
和y
必须都是相同类型的整数。如果除数为零,结果(遵循 EVM 语义)将为零。@external @view def foo(x: uint8, y: uint8) -> uint8: return unsafe_div(x, y) @external @view def bar(x: int8, y: int8) -> int8: return unsafe_div(x, y)
>>> ExampleContract.foo(1, 1) 1 >>> ExampleContract.foo(1, 0) 0 >>> ExampleContract.bar(-128, -1) -128
注意
性能说明:这将编译成单个 SDIV
或 DIV
指令,具体取决于输入是带符号的还是无符号的(分别)。
工具¶
- as_wei_value(_value, unit: str) uint256 ¶
获取由数字和单位指定的以太币数量,并返回等效的以太币数量。
_value
:以太币单位的值。可以使用任何数值类型,但值不能为负。unit
:以太币单位名称(例如"wei"
、"ether"
、"gwei"
等),指示_value
的面值。必须作为字面字符串给出。
@external @view def foo(s: String[32]) -> uint256: return as_wei_value(1.337, "ether")
>>> ExampleContract.foo(1) 1337000000000000000
- blockhash(block_num: uint256) bytes32 ¶
返回指定高度的区块的哈希值。
注意
EVM 仅提供对最近 256 个区块的访问权限。如果区块编号大于或等于当前区块编号,或比当前区块落后 256 个以上,则此函数将回滚。
@external @view def foo() -> bytes32: return blockhash(block.number - 16)
>>> ExampleContract.foo() 0xf3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
- empty(typename) Any ¶
返回一个值,该值是其类型的默认值(零值)。对于初始化新的内存变量很有用。
typename
:类型的名称,除了HashMap[_KeyType, _ValueType]
@external @view def foo(): x: uint256[2][5] = empty(uint256[2][5])
- len(b: Union[Bytes, String, DynArray[_Type, _Integer]]) uint256 ¶
返回给定
Bytes
、String
或DynArray[_Type, _Integer]
的长度。@external @view def foo(s: String[32]) -> uint256: return len(s)
>>> ExampleContract.foo("hello") 5
- method_id(method, output_type: type = Bytes[4]) Union[Bytes[4], bytes4] ¶
获取函数声明并返回其 method_id(在数据字段中用于调用它)。
method
:方法声明,作为字面字符串给出output_type
:输出类型(Bytes[4]
或bytes4
)。默认值为Bytes[4]
。
返回
output_type
指定类型的的值。@external @view def foo() -> Bytes[4]: return method_id('transfer(address,uint256)', output_type=Bytes[4])
>>> ExampleContract.foo() 0xa9059cbb
- _abi_encode(*args, ensure_tuple: bool = True) Bytes[<depends on input>] ¶
将可变数量的参数作为输入,并返回 ABIv2 编码的字节字符串。用于将参数打包到 raw_call、EIP712 和需要一致且高效的序列化方法的其他情况下。一旦此函数得到更多使用,我们暂时计划将其放入
ethereum.abi
命名空间中。*args
:任意参数ensure_tuple
:如果设置为 True,则确保即使单个参数也被编码为元组。换句话说,bytes
被编码为(bytes,)
,而(bytes,)
被编码为((bytes,),)
。这是 Vyper 和 Solidity 函数的调用约定。除了非常具体的用例,这应该设置为 True。必须是字面值。method_id
:要附加到 ABI 编码的字节字符串开头的字面十六进制或 Bytes[4] 值。
返回一个字节字符串,其最大长度由参数决定。例如,编码
Bytes[32]
会导致Bytes[64]
(第一个字是字节字符串变量的长度)。@external @view def foo() -> Bytes[132]: x: uint256 = 1 y: Bytes[32] = b"234" return _abi_encode(x, y, method_id=method_id("foo()"))
>>> ExampleContract.foo().hex() "c2985578" "0000000000000000000000000000000000000000000000000000000000000001" "0000000000000000000000000000000000000000000000000000000000000040" "0000000000000000000000000000000000000000000000000000000000000003" "3233340000000000000000000000000000000000000000000000000000000000"
- _abi_decode(b: Bytes, output_type: type_, unwrap_tuple: bool = True) Any ¶
将字节数组作为输入,并根据指定的输出类型返回解码后的值。用于解压缩 ABIv2 编码的值。一旦此函数得到更多使用,我们暂时计划将其放入
ethereum.abi
命名空间中。b
:长度介于output type
的 ABIv2 最小和最大大小范围之间的字节数组。output_type
:要解码的输出类型或输出类型的元组的名称。unwrap_tuple
: 如果设置为 True,则即使只指定了一种输出类型,输入也将被解码为元组。换句话说,_abi_decode(b, Bytes[32])
将被解码为(Bytes[32],)
。这是 Vyper 和 Solidity 函数生成的 ABIv2 编码值的约定。除了非常特殊的用例之外,这应该设置为 True。必须是字面量。
返回解码后的值(s),类型由 output_type 指定。
@external @view def foo(someInput: Bytes[128]) -> (uint256, Bytes[32]): x: uint256 = empty(uint256) y: Bytes[32] = empty(Bytes[32]) x, y = _abi_decode(someInput, (uint256, Bytes[32])) return x, y
- print(*args, hardhat_compat=False) None ¶
通过对“console”地址
0x000000000000000000636F6E736F6C652E6C6F67
发出静态调用来“打印”参数。某些智能合约开发框架支持此功能。默认模式在 titanoboa 中原生工作。对于 hardhat 风格的框架,请使用
hardhat_compat=True)
。
注意
发出静态调用与模式无关(即,不会从生产代码中删除),尽管编译器会在使用 print
时发出警告。