Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Yul 语言说明

一夜雨十年灯潞
268 0 0
Yul (先前被也被称为 JULIA 或 IULIA)是一种可以编译到各种不同后端的中间语言( |evm| 1.0,|evm| 1.5,而 eWASM 也在计划中)。* ?. l; H' F6 d( x
正因为如此,它被设计成为这三种平台的可用的共同标准。+ i. n% d! |( J) v
它已经可以用于 Solidity 内部的“内联汇编”,并且未来版本的 Solidity 编译器甚至会将 Yul 用作中间语言。 为 Yul 构建高级的优化器阶段也将会很容易。
% ?1 s6 Q$ |4 J  M; T7 O… note::0 N6 r$ Y+ A4 `* G: q0 ?
请注意,用于“内联汇编”的书写风格是不带类型的(所有的都是 ``u256``),内置函数与 |evm| 操作码相同。
2 x3 Y( D# J4 y& T- E有关详细信息,请参阅内联汇编文档。6 ^2 m- t* c: w& U# c4 U
Yul 的核心组件是函数,代码块,变量,字面量,for 循环,if 条件语句,switch 条件语句,表达式和变量赋值。# ~9 j0 f: z/ u' X
Yul 是强类型的,变量和字面量都需要通过前缀符号来指明类型。支持的类型有:bool, u8, s8, u32, s32,. c! N, y8 y8 Y! M% k
u64, s64, u128, s128, u256 和 s256。% o. r' ~) U6 B7 p8 K3 w, Q, M
Yul 本身甚至不提供操作符。如果目标平台是 |evm|,则操作码将作为内置函数提供,但如果后端平台发生了变化,则可以重新实现它们。
8 o; ?) U4 M/ Q9 D+ m! T  V5 t有关强制性的内置函数的列表,请参阅下面的章节。
% {0 N9 A0 G- n% \) p以下示例程序假定 |evm| 操作码 mul,div 和 mo 是原生支持或可以作为函数用以计算指数的。/ I7 v* T6 r/ _+ R5 M6 ]/ D3 b
… code::
0 k' L' ]+ ~2 n( k{& W9 E* U- I- Z
    function power(base:u256, exponent:u256) -> result:u256
, `, {/ K" g' ?( q6 B5 S8 r3 ]    {
2 X6 u# h- w4 c# g9 M& O        switch exponent
9 V! M" e* b+ {9 j- G        case 0:u256 { result := 1:u256 }5 C2 i, J7 b6 `% F+ s1 k6 I9 F
        case 1:u256 { result := base }( |: Q+ p! e+ v9 B
        default:( e, W6 N  O+ \# Z/ t
        {
( F9 E; g5 ^% s- ]9 j% ]9 V4 h; ~: Q            result := power(mul(base, base), div(exponent, 2:u256))
- ]( O1 y- q! |5 a) U6 E  J. ^8 T            switch mod(exponent, 2:u256)+ B0 M- D% O% G* z6 V$ y4 O8 f: l; L
                case 1:u256 { result := mul(base, result) }6 F) b1 x6 j0 F# n; \! i
        }
) ]- v) I! k! h- X    }9 e4 f* {0 b$ b) v6 w
}7 Y( F& x' b5 H& T$ [* e; I
也可用 for 循环代替递归来实现相同的功能。这里,我们需要 |evm| 操作码 lt (小于)和 add 可用。- g0 |3 g7 b" b' S' G3 E- }0 v
… code::+ Z  Q9 M( O/ I8 e5 c2 z; l; I$ s& O
{5 G& h8 z4 Q# L
    function power(base:u256, exponent:u256) -> result:u256
. j: e) v/ j" M& \# ~  C( F' |    {
! Y6 P1 V/ N0 C4 [, T% O1 v        result := 1:u256
7 Y/ c# @' P  v5 P: b: j: F        for { let i := 0:u256 } lt(i, exponent) { i := add(i, 1:u256) }/ c4 B+ r1 a& e& G# X! B
        {' F! N9 V: W: I* e# c
            result := mul(result, base)
5 a+ J! T# a% e2 u7 T        }8 ~6 w, J( |, k5 t; f" t
    }4 m( y4 U# H3 k) b! @
}3 a) P- T* k7 t. T
Yul 语言说明
  x% L( h, S) ?3 g本章介绍 Yul 代码。Yul 代码通常放置在一个 Yul 对象中,它将在下一节中介绍。
) |0 w# J! l8 Y2 z+ t语法::
7 a- A9 K" I; w' [( ~* @# Q代码块 = '{' 语句* '}'
* h* F+ d' D; @3 F2 {% M) |语句 =
; ?, C5 N& q/ v+ T6 e( R    代码块 |
; ^% {2 ^. w3 Y, h) A5 \    函数定义 |
3 u# u. }" m- I/ z2 z3 G% J# A# v    变量声明 |
8 U9 J% J" e4 C# Y    赋值 |
& v/ a, V6 u& X) K6 |: @    表达式 |
  Y( X0 x& |5 {! b" n% @5 j    Switch |- V1 B4 C8 s0 p. l
    For 循环 |
( y3 T( ^$ V  G$ ^6 [. d, D    循环中断
: ]# g: c5 `6 k5 S8 u' @6 p% K4 L函数定义 =
; {" k+ \: a" j; J    'function' 标识符 '(' 带类型的标识符列表? ')'
, u7 m2 l5 {+ t8 O4 Y  L    ( '->' 带类型的标识符列表 )? 代码块
; x/ r. S( L* O) F变量声明 =% G# R7 L1 _( X; I
    'let' 带类型的标识符列表 ( ':=' 表达式 )?" L3 l- M1 P* f8 l& K
赋值 =5 ^' }! i# X! }$ T1 j% Q6 e, H2 [
    标识符列表 ':=' 表达式$ U4 E6 |5 S4 {3 a3 H9 b
表达式 =" n. e% ]4 w3 o9 x
    函数调用 | 标识符 | 字面量8 w, i, A/ q: l' K5 q: f. x* x
If 条件语句 =! Y6 ~# C8 s5 d( ^0 i5 Q3 M
    'if' 表达式 代码块
" V" G. w, a( q* z8 aSwitch 条件语句 =% Q$ F: e6 T5 `2 @7 }: z+ S
    'switch' 表达式 Case* ( 'default' 代码块 )?+ Y, D* C" a0 D' W* x
Case =; r" E6 U+ |6 C+ t
    'case' 字面量 代码块! ]1 @" z1 b: j
For 循环 =  o8 `7 y, Q3 l! C, q; X
    'for' 代码块 表达式 代码块 代码块1 r7 ]+ f/ O# _' c6 v4 v
循环中断 =
: n0 W7 k( h- v  ~: O    'break' | 'continue'
/ U7 K# d  A. ?1 h0 V! K# ]函数调用 =3 a: V. y  I$ U; O
    标识符 '(' ( 表达式 ( ',' 表达式 )* )? ')'7 I7 g4 `& n0 a
标识符 = [a-zA-Z_$] [a-zA-Z_0-9]*0 P# {; L! k; @  ^; R7 K
标识符列表 = 标识符 ( ',' 标识符)*
9 {& ?6 `+ a$ ^+ k7 g, ^类型名 = 标识符 | 内置的类型名
8 b8 X! J. Y5 i# A内置的类型名 = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )$ u# }. `! D! u, {& Z0 V
带类型的标识符列表 = 标识符 ':' 类型名 ( ',' 标识符 ':' 类型名 )*. F- d8 T- B: y- y3 ~$ q" o
字面量 =
) c( D2 K! n, \, r2 t    (数字字面量 | 字符串字面量 | 十六进制字面量 | True字面量 | False字面量) ':' 类型名9 ~! k) U% ?, I6 y: s  S. P
数字字面量 = 十六进制数字 | 十进制数字
$ G  {* m. o; O$ G# R$ I; P十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
/ Y7 b' t% q4 N6 C% ~' U+ ^' \字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"') a" X4 a3 ~7 f2 q& k
True字面量 = 'true'
% i5 z) D5 t- N* ^# S) Y$ _False字面量 = 'false'% ^( O* V3 c) E: Z
十六进制数字 = '0x' [0-9a-fA-F]+% S' Q9 e) a' L" g" q9 l, F
十进制数字 = [0-9]+
7 ]+ n( m4 J% W" C- P5 W语法层面的限制
6 {; ^1 F7 \9 G7 KSwitches 必须至少有一个 case(包括 default )。
8 G# i7 }; m- @) ]# e如果表达式的所有可能值都被覆盖了,那么不应该允许使用 default! o% q: \/ H  H% h+ l4 w
(即带 bool 表达式的 switch 语句同时具有 true case 和 false case 的情况下不应再有 default 语句)。, d7 H' w" x- `9 ]$ @6 B
每个表达式都求值为零个或多个值。 标识符和字面量求值为一个值,函数调用求值为所调用函数的返回值。
- N' F6 c7 ~8 i, W$ w/ g在变量声明和赋值中,右侧表达式(如果存在)求值后,必须得出与左侧变量数量相等的值。' R& A9 L% A% J
这是唯一允许求值出多个值的表达式。
. i: k7 B$ W2 ~那种同时又是语句的表达式(即在代码块的层次)求值结果必须只有零个值。
6 t8 H' C; D/ e7 [/ m在其他所有情况中,表达式求值后必须仅有一个值。( `, {7 x. _4 U  n# i1 N2 g8 ?
continue 和 break 语句只能用在循环体中,并且必须与循环处于同一个函数中(或者两者都必须在顶层)。* N4 u) R' A" _' L( M# L$ R! r
for 循环的条件部分的求值结果只能为一个值。' d5 p0 p& d) V- G0 R; P
字面量不可以大于它们本身的类型。已定义的最大类型宽度为 256 比特。9 ~, F# B4 C+ K8 \, a& n
作用域规则
# m/ u5 U6 M2 e$ [! tYul 中的作用域是与块(除了函数和 for 循环,如下所述)和所有引入新的标识符到作用域中的声明3 r% F4 o1 L+ r" X
( FunctionDefinition ,VariableDeclaration )紧密绑定的。
. D7 O* G9 t2 \, ]标识符在将其定义的块中可见(包括所有子节点和子块)。
/ D, D" V' R4 [+ z作为例外,for 循环的 “init” 部分中(第一个块)定义的标识符在 for 循环的所有其他部分(但不在循环之外)中都是可见的。+ Z/ ?7 y! |3 J+ r4 F
在 for 循环的其他部分声明的标识符遵守常规的作用域语法规则。5 P# ?3 W' {# k$ p5 g
函数的参数和返回参数在函数体中可见,并且它们的名称不能相同。5 d, d/ e; |* p( j: e- G
变量只能在声明后引用。 尤其是,变量不能在它们自己的变量声明的右边被引用。
8 Y) Y4 \: Y* E. L7 P5 H5 f' _7 E函数可以在声明之前被引用(如果它们是可见的)。; R2 m- _4 ?* E0 }) y& u& \
Shadowing 是不被允许的,即是说,你不能在同名标识符已经可见的情况下又定义该标识符,即使它是不可访问的。
5 R) V4 l, b- x. I0 v在函数内,不可能访问声明在函数外的变量。5 j6 i! ]& {" a9 [2 U6 T5 l
形式规范, P$ C+ o; E$ `4 {% u6 ^& M
我们通过在 AST 的各个节点上提供重载的求值函数 E 来正式指定 Yul。# T6 J+ H" I3 o! q( `" y3 u
任何函数都可能有副作用,所以 E 接受两个状态对象和 AST 节点作为它的参数,并返回两个新的状态对象和数量可变的其他值。
$ G9 @. {1 i- G( f2 G; h这两个状态对象是全局状态对象(在 |evm| 的上下文中是 |memory|,|storage| 和区块链的状态)和本地状态对象(局部变量的状态,即 |evm| 中堆栈的某个段)。; r8 h# G3 J! o. E7 g2 b3 p
如果 AST 节点是一个语句,E 将返回两个状态对象和一个用于 break 和 continue 语句的 “mode”。7 t4 Q0 I9 \( Z) W* Q$ G
如果 AST 节点是表达式,则 E 返回两个状态对象,并返回与表达式求值结果相同数量的值。8 F% [( e/ |) Z: f7 P
在这份高层次的描述中,并没有对全局状态的确切本质进行说明。
# s2 Y* n$ F! A3 f4 u本地状态 L 是标识符 i 到值 v 的映射,表示为 L = v。
+ C0 @' _- h0 o  p$ ~% Y% \对于标识符 v, 我们用 $v 作为标识符的名字。5 K5 Q) A6 n( [& Y
我们将为 AST 节点使用解构符号。" [: o/ ^0 y6 N* j0 l# r8 ]- P5 a
… code::
9 ?8 K" h2 L- `. p7 S, m5 `+ w+ FE(G, L, : Block) =
- y2 M" i: o# d2 j  k    let G1, L1, mode = E(G, L, St1, ..., Stn)! V2 p* C7 U, a/ z* W
    let L2 be a restriction of L1 to the identifiers of L3 S* Y9 e4 V4 s3 v
    G1, L2, mode8 u' @0 [1 q5 [2 R1 I4 X9 O0 g/ H8 `
E(G, L, St1, ..., Stn: Statement) =
' b- _* Y) O! H    if n is zero:
% F+ ?' ~  F; K- ?        G, L, regular
) G7 r3 l5 I( w- X    else:% j; m- e% s8 o! V  ~
        let G1, L1, mode = E(G, L, St1)
0 \' g+ v* t- \' V& {8 }        if mode is regular then
, F& [! Q0 p6 N- g) h5 u; ^            E(G1, L1, St2, ..., Stn)
0 N, B) p0 v9 ?  z/ e- W        otherwise+ [7 @+ G" L0 _$ E( _. [0 y, j
            G1, L1, mode
* c+ x. ^/ z# r$ e5 vE(G, L, FunctionDefinition) =
9 S( O, x" O  _+ F7 g/ i7 b' G3 {    G, L, regular) q$ J# q& _: n. ~; x$ K4 Y
E(G, L, : VariableDeclaration) =& ~& H6 ?- n  W9 ]- G2 C
    E(G, L, : Assignment)( G" S9 I8 B( n6 ]& U" Y8 E
E(G, L, : VariableDeclaration) =6 M0 c' Z% i- V/ d4 Z; n0 ]
    let L1 be a copy of L where L1[$vari] = 0 for i = 1, ..., n
4 n3 Q; B/ ]& E. ~( O( L    G, L1, regular
( `) e1 R' n2 r6 wE(G, L, : Assignment) =
3 V4 ~7 o$ S$ y+ i9 q0 Z% r    let G1, L1, v1, ..., vn = E(G, L, rhs)6 C2 a0 }. i5 f! C5 v
    let L2 be a copy of L1 where L2[$vari] = vi for i = 1, ..., n4 }7 `/ P9 l: |. Z8 i6 V
    G, L2, regular
# L4 c0 W) ^8 H8 M  K$ UE(G, L, : ForLoop) =
  \2 ^9 R4 `2 i! [    if n >= 1:
" R- M; h& `- x        let G1, L1, mode = E(G, L, i1, ..., in)
: h4 h3 o. j) o; v( J9 m        // 由于语法限制,mode 必须是规则的# K4 Z4 n1 U2 f, v
        let G2, L2, mode = E(G1, L1, for {} condition post body)
6 |0 Y* M) l) j5 }# w+ M1 p& p        // 由于语法限制,mode 必须是规则的
+ C1 ?; i" N9 z2 I: g        let L3 be the restriction of L2 to only variables of L
: I! b7 r* I2 U+ v. }5 Z: z6 x        G2, L3, regular3 F( i# i3 _0 M4 j+ K( c
    else:2 L0 e! {$ T0 K- P6 k/ c
        let G1, L1, v = E(G, L, condition)+ ?- D9 T4 v9 ^, ~: {  ^- j
        if v is false:& t  I0 p5 g; P& ?4 W
            G1, L1, regular/ f7 Z3 A; m' Z! O% j# r
        else:! i& G( Y( E! X7 `9 I, {# N! c
            let G2, L2, mode = E(G1, L, body)- i7 G5 m) B! a" @- w/ w  `5 W8 e3 r
            if mode is break:' i8 A% H- X% U
                G2, L2, regular
& A4 ^9 [8 Z9 r# {+ d, @4 ]            else:
2 s: w# k4 _( |: V. N                G3, L3, mode = E(G2, L2, post), V  ^5 a1 Z3 S0 U  k2 F
                E(G3, L3, for {} condition post body)
: m, r* F+ v- Q& g6 [E(G, L, break: BreakContinue) =  H" q# ^( @- E3 L, ?
    G, L, break9 I. A9 A1 F; K# J: {1 e/ P
E(G, L, continue: BreakContinue) =2 X7 m7 a" e: H) }1 Y, M( f
    G, L, continue; R- \# c& M3 M6 F/ C( k2 t
E(G, L, : If) =" J" U/ P" D4 y( a5 f  E
    let G0, L0, v = E(G, L, condition)
. u- J9 L4 u8 E( r' W8 W    if v is true:
* ^* [  a9 Y: p4 \. E9 ]        E(G0, L0, body)
1 I( s- l8 u5 p* Y! l1 f* x    else:" w! p+ T9 b2 |0 n2 e
        G0, L0, regular5 X% G2 m9 |! a9 @
E(G, L, : Switch) =1 i3 S6 e) S1 q
    E(G, L, switch condition case l1:t1 st1 ... case ln:tn stn default {})
7 t0 b+ G1 r+ aE(G, L, : Switch) =/ |# Y! n8 ]" r
    let G0, L0, v = E(G, L, condition)  h5 {5 k3 Y* C
    // i = 1 .. n
* F" G# E5 h; u5 Y    // 对字面量求值,上下文无关
+ K% m& o! ?: L    let _, _, v1 = E(G0, L0, l1)
; {, f9 \0 E. L    ...
7 z) R3 |4 M' a# w  l% a    let _, _, vn = E(G0, L0, ln)
( u  a0 P0 i2 H3 s* {6 v: A    if there exists smallest i such that vi = v:! T6 |. C0 z$ ?! C
        E(G0, L0, sti)3 H& z  y( q; I  K7 c
    else:% \. v  C9 @$ \6 p! Z0 _
        E(G0, L0, st')
  n- R7 @0 b3 K9 C% TE(G, L, : Identifier) =
, ^+ v7 B) I- i$ l+ Q    G, L, L[$name]# Q. @4 w6 m, ~; f8 E: q- I
E(G, L, : FunctionCall) =! L$ ^2 T( K: h" u
    G1, L1, vn = E(G, L, argn)
3 R7 b2 p* ]" o, Q3 d0 o2 u    ...' Z3 ?. ]# M- ~' |, N
    G(n-1), L(n-1), v2 = E(G(n-2), L(n-2), arg2)
- x! U* I7 Y) t, d    Gn, Ln, v1 = E(G(n-1), L(n-1), arg1)  j+ U, B: q& ?% K# U, L6 _' N3 g
    Let  ret1, ..., retm block>5 h* z+ @/ A9 \! R& Y
    be the function of name $fname visible at the point of the call.4 @9 u. h! [6 z0 @
    Let L' be a new local state such that
9 Y9 z& q' i4 F" Y( G    L'[$parami] = vi and L'[$reti] = 0 for all i.3 I. i' @, g% |( W
    Let G'', L'', mode = E(Gn, L', block)4 r; w0 ^; ^$ C! S$ p7 z" ]: |
    G'', Ln, L''[$ret1], ..., L''[$retm]! q( g9 _5 z- v2 N8 p
E(G, L, l: HexLiteral) = G, L, hexString(l),3 q; n$ E) n% I* t' D! k1 h8 G: L, Z1 D
    where hexString decodes l from hex and left-aligns it into 32 bytes$ Z. u# {1 B% A* k# P1 X
E(G, L, l: StringLiteral) = G, L, utf8EncodeLeftAligned(l),9 \7 B+ I( F" m) Z. Q
    where utf8EncodeLeftAligned performs a utf8 encoding of l
5 K% B1 O2 W3 E8 A" h& u    and aligns it left into 32 bytes1 g. [3 I0 m* O; y8 K
E(G, L, n: HexNumber) = G, L, hex(n)/ ]& B/ v8 |' L# ~
    where hex is the hexadecimal decoding function
$ u$ Q/ J  k3 x4 r9 M6 q- IE(G, L, n: DecimalNumber) = G, L, dec(n),
5 Z$ t4 M: h3 x  J$ [: d    where dec is the decimal decoding function& ^* o* ?- c0 P* f' s/ k) L
类型转换函数: z8 P( E' G$ t$ H% y& N! f
Yul 不支持隐式类型转换,因此存在提供显式转换的函数。, g8 L6 T6 ^  j# ]
在将较大类型转换为较短类型时,如果发生溢出,则可能会发生运行时异常。4 z. X( E3 T3 F  X' T
下列类型的“截取式”转换是允许的:
0 Y4 }8 B- T) }8 C! D7 |6 f$ d
  • bool
  • u32
  • u64
  • u256
  • s256
    ! @& {+ a- w4 K% |& w

    # u9 }3 b, R4 ]# X这里的每种类型的转换函数都有一个格式为 to(x:) -> y: 的原型,8 P0 f. M9 o4 C) e- ^
    比如 u32tobool(x:u32) -> y:bool、u256tou32(x:u256) -> y:u32 或 s256tou256(x:s256) -> y:u256。" B7 t5 ?" u$ g- n9 |) i, R2 e
    … note::% k" G$ {" W0 B/ ^: B
    ``u32tobool(x:u32) -> y:bool`` 可以由 ``y := not(iszerou256(x))`` 实现,并且0 `6 A( @, _3 H
    ``booltou32(x:bool) -> y:u32`` 可以由 ``switch x case true:bool { y := 1:u32 } case false:bool { y := 0:u32 }`` 实现9 E& O& T* F1 r0 G+ f2 N; O
    低级函数
    7 b+ m3 @& f5 _* B! A3 h以下函数必须可用:
    . M+ r0 P% z, l±--------------------------------------------------------------------------------------------------------------+
    1 d6 u. i; M! h, h2 [& || 逻辑操作                                                                                                    |4 c, d. |4 L$ S4 C5 l
    ±--------------------------------------------±----------------------------------------------------------------+% N, I" N& j1 h+ a
    | not(x:bool) -> z:bool                       | 逻辑非                                                          |3 Q* ]* o* y+ B" ~
    ±--------------------------------------------±----------------------------------------------------------------+* D% q9 E9 W5 l: r% G
    | and(x:bool, y:bool) -> z:bool               | 逻辑与                                                          |( Y, \. g5 `1 L" T# S& V$ N
    ±--------------------------------------------±----------------------------------------------------------------+
    # `. j3 u- \6 H| or(x:bool, y:bool) -> z:bool                | 逻辑或                                                          |
    " m! P# l% E+ {" s6 r$ I±--------------------------------------------±----------------------------------------------------------------+5 V) N- e1 w! o  `5 A1 _% V
    | xor(x:bool, y:bool) -> z:bool               | 异或                                                            |
    * H! Y4 n( _5 V±--------------------------------------------±----------------------------------------------------------------+
    ( x& h( R' [, ^" V4 ~| 算术操作                                                                                                    |
    & p$ L' A2 u; ]# ^$ {' o+ M±--------------------------------------------±----------------------------------------------------------------+6 B/ T& R/ e" \4 B3 n! ~2 u) H
    | addu256(x:u256, y:u256) -> z:u256           | x + y                                                           |
    ; N) h) a- x4 R. _! u# s* p±--------------------------------------------±----------------------------------------------------------------+; u8 W$ ]# K1 X" h' M) z
    | subu256(x:u256, y:u256) -> z:u256           | x - y                                                           |3 o# j' t& A" e( F# x0 e2 f
    ±--------------------------------------------±----------------------------------------------------------------+" x- Y, z5 t6 w
    | mulu256(x:u256, y:u256) -> z:u256           | x * y                                                           |
    ' z9 Q8 q2 C/ F& o) `& r7 f±--------------------------------------------±----------------------------------------------------------------+
    - D0 t9 K$ T; P& X: F| divu256(x:u256, y:u256) -> z:u256           | x / y                                                           |
    : a+ I6 a+ q/ C/ c& s- i2 {±--------------------------------------------±----------------------------------------------------------------+
    9 m2 ~! o) |) h; l| divs256(x:s256, y:s256) -> z:s256           | x / y, 有符号数用补码形式                                       |
    5 }, E/ S6 j0 h2 a, F±--------------------------------------------±----------------------------------------------------------------+
    / M5 M* X2 h+ w" N| modu256(x:u256, y:u256) -> z:u256           | x % y                                                           |
      X* X% R3 N/ r* _; P±--------------------------------------------±----------------------------------------------------------------+* r" U/ W8 s7 _
    | mods256(x:s256, y:s256) -> z:s256           | x % y, 有符号数用补码形式                                       |
    " E" f% w; l5 a/ A/ X±--------------------------------------------±----------------------------------------------------------------+
    0 W% y( [+ l- z0 v  j9 g( {| signextendu256(i:u256, x:u256) -> z:u256    | 从第 (i*8+7) 位开始进行符号扩展,从最低符号位开始计算           |
    3 Y# s$ w4 Z8 }* @! {±--------------------------------------------±----------------------------------------------------------------+) H* f5 P* Z& o2 n! S3 ^
    | expu256(x:u256, y:u256) -> z:u256           | x 的 y 次方                                                     |$ g" {* S1 K2 t* }! @, B
    ±--------------------------------------------±----------------------------------------------------------------+% g; a$ a1 S5 M. B% N3 @" X. b
    | addmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x + y) % m                                |" z3 k2 g8 M5 h( w
    ±--------------------------------------------±----------------------------------------------------------------+
    ' {9 {; R1 h3 v  U$ @. i| mulmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x * y) % m                                |5 }8 T9 y  W$ ]5 q6 g/ E
    ±--------------------------------------------±----------------------------------------------------------------+# H; H9 }: F* H( V, P$ f
    | ltu256(x:u256, y:u256) -> z:bool            | 若 x  z:bool            | 若 x > y 为 true, 否则为 false                                  |: J' X8 I9 J0 s/ V6 H/ m5 _5 d
    ±--------------------------------------------±----------------------------------------------------------------+
    - |0 j: p2 u4 K" c| sltu256(x:s256, y:s256) -> z:bool           | 若 x  z:bool           | 若 x > y 为 true, 否则为 false                                  |5 W2 h' b6 G2 |( W2 q, ]
    |                                             | 有符号数用补码形式                                              |" j/ g, ]; j5 S: ~! {$ Q, L
    ±--------------------------------------------±----------------------------------------------------------------+; f+ O- C) k! B2 S! V4 T" I7 C
    | equ256(x:u256, y:u256) -> z:bool            | 若 x == y 为 true, 否则为 false                                 |
    % P. K+ a# {) J2 C1 d±--------------------------------------------±----------------------------------------------------------------+9 D* ^7 [; T/ i* g" \$ j0 G% s
    | iszerou256(x:u256) -> z:bool                | 若 x == 0 为 true, 否则为 false                                 |. L8 a, Q' ~% t$ ]; o! Q! l
    ±--------------------------------------------±----------------------------------------------------------------+
    7 s5 d3 y5 [5 m7 H5 Q| notu256(x:u256) -> z:u256                   | ~x, 对 x 按位非                                                 |
    ) A% T; @8 ?' H( R5 f6 \/ ^±--------------------------------------------±----------------------------------------------------------------+
    0 P0 q: E" s( P/ C: l% Q| andu256(x:u256, y:u256) -> z:u256           | x 和 y 按位与                                                   |, [% h, X9 v& j  U! D( O1 S2 W( {
    ±--------------------------------------------±----------------------------------------------------------------+
    : G! z9 o% l2 u; L/ X| oru256(x:u256, y:u256) -> z:u256            | x 和 y 按位或                                                   |
    , ?& ~  r3 I; h# c! G- i# Q6 F) l±--------------------------------------------±----------------------------------------------------------------+3 i* w( E% t: P) k) E
    | xoru256(x:u256, y:u256) -> z:u256           | x 和 y 按位异或                                                 |
    . \7 P2 W% F- W2 e% @: l+ V±--------------------------------------------±----------------------------------------------------------------+/ A6 J! i* g7 F) n7 z; h
    | shlu256(x:u256, y:u256) -> z:u256           | 将 x 逻辑左移 y 位                                              |
    7 R( `7 G/ n; q3 z; l: Q±--------------------------------------------±----------------------------------------------------------------+
    . i8 o* q. ]; s5 F( P; i5 U| shru256(x:u256, y:u256) -> z:u256           | 将 x 逻辑右移 y 位                                              |) X0 |0 ?0 U# i" ]% x+ q# `
    ±--------------------------------------------±----------------------------------------------------------------+; t( S6 p: h9 O' A. a
    | saru256(x:u256, y:u256) -> z:u256           | 将 x 算术右移 y 位                                              |: w6 |* Z( o0 V; F6 C; i  T( d. ~
    ±--------------------------------------------±----------------------------------------------------------------+
    3 C/ @& {9 l$ l& T$ I; m! k9 Y| byte(n:u256, x:u256) -> v:u256              | x 的第 n 字节,这里的索引位置是从 0 开始的;                    |
    4 c! G0 H2 w* {: v) e  d: y9 P! i|                                             | 能否用 and256(shr256(n, x), 0xff) 来替换它,                    |
    / ]. L: I' q( S  p# G|                                             | 并使它在 EVM 后端之外被优化呢?                                 |
    ; u: U) v4 X0 B  s" k±--------------------------------------------±----------------------------------------------------------------+8 r' f. ]1 P. x! ^
    | 内存和存储                                                                                                  |/ |3 s0 }2 @0 o( r' B& R
    ±--------------------------------------------±----------------------------------------------------------------+
    3 F$ `( ]# i2 K8 K2 `: {| mload(p:u256) -> v:u256                     | mem[p…(p+32))                                                  |
    1 Z! r5 _: w9 K" n9 D, w$ S±--------------------------------------------±----------------------------------------------------------------+; m3 x' t( _# p, Z3 e
    | mstore(p:u256, v:u256)                      | mem[p…(p+32)) := v                                             |
    4 J8 O" a& A* s. V±--------------------------------------------±----------------------------------------------------------------+
    - x" {5 i- D) C4 m+ a4 i: W| mstore8(p:u256, v:u256)                     | mem := v & 0xff    - 仅修改单个字节                          |* ~- j* D: j; ?4 M4 N
    ±--------------------------------------------±----------------------------------------------------------------+
    6 L! _  I: E1 Y( L  t" s7 @' `# i| sload(p:u256) -> v:u256                     | storage                                                      |
    7 w0 ~" X" T" c  X( n) b. D" m" h±--------------------------------------------±----------------------------------------------------------------+/ j% z# z1 a" N" H
    | sstore(p:u256, v:u256)                      | storage := v                                                 |' I+ x% R7 R. j
    ±--------------------------------------------±----------------------------------------------------------------+$ A& C6 o4 {- Z4 X5 d
    | msize() -> size:u256                        | 内存的大小, 即已访问过的内存的最大下标,                        |
    . X' c9 o/ X& k) C, a5 z|                                             | 因为内存扩展的限制(只能按字进行扩展)                          |6 H/ }, z1 V5 f; C# L
    |                                             | 返回值永远都是 32 字节的倍数                                    |. ~- Y/ M7 Q" b0 |% p1 U
    ±--------------------------------------------±----------------------------------------------------------------+
    9 L8 e0 T/ _/ x9 n* U| 执行控制                                                                                                    |
    ) K( s* E; _' O: z9 P4 s7 Z* Z0 U±--------------------------------------------±----------------------------------------------------------------+1 D$ v7 U9 j/ L" \: ]- ?
    | create(v:u256, p:u256, s:u256)              | 以 mem[p…(p+s)) 上的代码创建一个新合约,发送                   |
    # C) y! B; k1 \& r* D|                                             | v 个 wei,并返回一个新的地址                                    |
    0 R7 \# K  D" o  h1 u±--------------------------------------------±----------------------------------------------------------------+4 V/ b% G+ P/ h* y! H1 y. S& h
    | call(g:u256, a:u256, v:u256, in:u256,       | 调用地址 a 上的合约,以 mem[in…(in+insize)) 作为输入           |; G; O& X* S; J* l5 s3 P- H
    | insize:u256, out:u256,                      | 一并发送 g gas 和 v wei ,以 mem[out…(out+outsize))            |6 X6 g4 z# V5 v" L! a( @2 T
    | outsize:u256)                               | 作为输出空间。若错误,返回 0 (比如,gas 用光                   |; D# b- N5 X8 A0 t  @- \
    | -> r:u256                                   | 成功,返回 1                                                    |0 d  L& p3 n8 ^8 B- P
    ±--------------------------------------------±----------------------------------------------------------------+% _! N( _* Q$ P7 K# W
    | callcode(g:u256, a:u256, v:u256, in:u256,   | 相当于 call 但仅仅使用地址 a 上的代码,                     |
    3 g8 q& [) d9 k| insize:u256, out:u256,                      | 而留在当前合约的上下文当中                                      |
    & G# D7 h; B3 m, b; E| outsize:u256) -> r:u256                     |                                                                 |
    8 i. ^3 n3 E: i2 w$ P( _8 c±--------------------------------------------±----------------------------------------------------------------+8 Q+ E) o% i! v: O
    | delegatecall(g:u256, a:u256, in:u256,       | 相当于 callcode,                                           |
    6 t* Z, |  M! Y+ z" V& l| insize:u256, out:u256,                      | 但同时保留 caller                                           |& a3 D1 K2 z  W/ |+ M. l
    | outsize:u256) -> r:u256                     | 和 callvalue                                                |
    1 z+ J0 d1 j) Z. ?±--------------------------------------------±----------------------------------------------------------------+
    ( [1 m0 r0 X8 X5 U| abort()                                     | 终止 (相当于EVM上的非法指令)                                    |6 e% a. `& @. ^+ h
    ±--------------------------------------------±----------------------------------------------------------------+
    " c$ J2 n, p: C| return(p:u256, s:u256)                      | 终止执行,返回 mem[p…(p+s)) 上的数据                           |; B5 a/ c, M8 e1 c
    ±--------------------------------------------±----------------------------------------------------------------+
    : T3 k* |1 W  @% v& u  c| revert(p:u256, s:u256)                      | 终止执行,恢复状态变更,返回 mem[p…(p+s)) 上的数据             |
    3 P7 \: A& t" k- J: @+ ^3 @) X/ g) O1 Q±--------------------------------------------±----------------------------------------------------------------+
    . V: B* I7 q6 V5 D( _| selfdestruct(a:u256)                        | 终止执行,销毁当前合约,并且将余额发送到地址 a                  |
    * O6 ]" X/ J/ c3 y7 z. P±--------------------------------------------±----------------------------------------------------------------+- n. s/ s, U* ^0 N7 D& j5 J
    | log0(p:u256, s:u256)                        | 用 mem[p…(p+s)] 上的数据产生日志,但没有 topic                 |$ G( w9 j6 L; J& D# [: k0 Q2 r$ }- Q7 R
    ±--------------------------------------------±----------------------------------------------------------------+
    , Z$ Q+ E7 |/ l$ K$ ^3 P| log1(p:u256, s:u256, t1:u256)               | 用 mem[p…(p+s)] 上的数据和 topic t1 产生日志                   |
    2 x- a* b. i4 X, S  s4 H/ r8 G! K9 `±--------------------------------------------±----------------------------------------------------------------+6 }4 D$ X! q) q; N$ c  I) d2 J
    | log2(p:u256, s:u256, t1:u256, t2:u256)      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2 产生日志               |
    : w4 l; T. _& @! Z- J4 q±--------------------------------------------±----------------------------------------------------------------+
    1 V) x0 k- P8 e; [$ h6 _| log3(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3 产生日志           |
    , r8 s1 @8 E/ v% k. O$ || t3:u256)                                    |                                                                 |6 D$ H- V+ Q5 o1 \: b1 Q0 ?0 c- D0 l
    ±--------------------------------------------±----------------------------------------------------------------+
    6 T8 M6 f6 ^  R* T- \| log4(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3,t4                |$ S+ o5 [' B' U2 j( T; }% e
    | t3:u256, t4:u256)                           | 产生日志                                                        |
    , |. J- m) o+ o+ Y: C±--------------------------------------------±----------------------------------------------------------------+) T4 Z8 |# ~- }: Z0 x. w. t; t
    | 状态查询                                                                                                    |
      n  v2 Y9 P7 {( u) L±--------------------------------------------±----------------------------------------------------------------+
    ) N, Y' q4 v3 j& E5 d. E: S| blockcoinbase() -> address:u256             | 当前的矿工                                                      |
    ) \! M2 r% M5 ~# s±--------------------------------------------±----------------------------------------------------------------+
    - i0 p# f( j# x- [2 c$ x! Z- x& y| blockdifficulty() -> difficulty:u256        | 当前区块的难度                                                  |5 U, I8 R( C/ ]" A
    ±--------------------------------------------±----------------------------------------------------------------+
    # l) K5 d1 o7 L* e2 i* w' _| blockgaslimit() -> limit:u256               | 当前区块的区块 gas 限制                                         |2 o4 [! p9 Z7 i) C
    ±--------------------------------------------±----------------------------------------------------------------+
    9 Y9 k  I- E' `! {; f) B+ p" F- w| blockhash(b:u256) -> hash:u256              | 区块号为 b 的区块的哈希,                                       |) g) g; F4 b: K1 j7 z- T" C! `" q
    |                                             | 仅可用于最近的 256 个区块,不包含当前区块                       |2 T, f! k0 T# B8 P; g
    ±--------------------------------------------±----------------------------------------------------------------+7 T3 W) _  D' W+ J/ P0 Z0 k# t% r6 `7 E( `
    | blocknumber() -> block:u256                 | 当前区块号                                                      |" y' _: H. }' S  C
    ±--------------------------------------------±----------------------------------------------------------------+  @1 U/ @+ e6 t  R2 w, A/ @
    | blocktimestamp() -> timestamp:u256          | 自 epoch 开始的,当前块的时间戳,以秒为单位                     |$ c: k! V8 F, \4 S
    ±--------------------------------------------±----------------------------------------------------------------+
    & ]' m/ [. L: _- `2 x| txorigin() -> address:u256                  | 交易的发送方                                                    |- @+ h8 P9 ]( v
    ±--------------------------------------------±----------------------------------------------------------------+3 R, u$ s$ A3 M6 S/ o* x# L% i
    | txgasprice() -> price:u256                  | 交易中的 gas 价格                                               |
    $ M7 U0 T* V$ V4 E' A* }±--------------------------------------------±----------------------------------------------------------------+
    . _) [" H5 \3 A+ Q3 _% G| gasleft() -> gas:u256                       | 还可用于执行的 gas                                              |6 ?9 w) N# l$ q! M" P* G
    ±--------------------------------------------±----------------------------------------------------------------+
    ( O( L, p* m  X' }8 q+ F| balance(a:u256) -> v:u256                   | 地址 a 上的 wei 余额                                            |
    4 Q3 i( c4 T9 ~# t0 T- z" I±--------------------------------------------±----------------------------------------------------------------+
      X( H. o- B, Y  E, _; @| this() -> address:u256                      | 当前合约/执行上下文的地址                                      |0 h7 L% k9 e8 p$ {
    ±--------------------------------------------±----------------------------------------------------------------+
    ) K0 j! S. T: j| caller() -> address:u256                    | 调用的发送方 (不包含委托调用)                                   |
    5 x; ~1 m* g% S5 c, L±--------------------------------------------±----------------------------------------------------------------+( Y# G- B+ P- s, J, j/ l
    | callvalue() -> v:u256                       | 与当前调用一起发送的 wei                                        |- b% k& c; w* S2 A
    ±--------------------------------------------±----------------------------------------------------------------+
    : A. P$ n7 p; g: D/ I4 C| calldataload(p:u256) -> v:u256              | 从 position p 开始的 calldata (32 字节)                         |0 c/ D. r+ Z: L
    ±--------------------------------------------±----------------------------------------------------------------+
    0 d6 K* ]: W4 o0 d! x3 ]| calldatasize() -> v:u256                    | 以字节为单位的 calldata 的大小                                  |
    ' W% K& `) t, v. n1 R2 c±--------------------------------------------±----------------------------------------------------------------+
    1 J: _* v+ r! \  R- s| calldatacopy(t:u256, f:u256, s:u256)        | 从位置为 f 的 calldata 中,拷贝 s 字节到内存位置 t              |
    5 x# Y, ?+ ?" a' r1 Q, U& o±--------------------------------------------±----------------------------------------------------------------+3 K$ f* ^! t: `. D2 Y
    | codesize() -> size:u256                     | 当前合约/执行上下文的代码大小                                  |
    & z( r6 I  d3 [±--------------------------------------------±----------------------------------------------------------------+" `# O  |! u: Y' K! P
    | codecopy(t:u256, f:u256, s:u256)            | 从 code 位置 f 拷贝 s 字节到内存位置 t                          |
    ( g+ D  f9 V8 O6 B. E, l' O±--------------------------------------------±----------------------------------------------------------------+
    8 c. a4 a+ B; o+ l" k/ f# T# {) E+ z| extcodesize(a:u256) -> size:u256            | 地址 a 上的代码大小                                             |$ T" d: |" D3 n* j8 B& E) `
    ±--------------------------------------------±----------------------------------------------------------------+, F$ A; p) k, Z' f/ c. F
    | extcodecopy(a:u256, t:u256, f:u256, s:u256) | 相当于 codecopy(t, f, s),但从地址 a 获取代码                   |
    8 Z3 H  I' F( J$ u±--------------------------------------------±----------------------------------------------------------------+
    * M1 p. M/ y8 a+ M. u| 其他                                                                                                        |' L' M: r# z9 W- ^9 Y$ `* w
    ±--------------------------------------------±----------------------------------------------------------------+
      C, t! a4 n7 F| discard(unused:bool)                        | 丢弃值                                                          |
    * G$ E3 h8 |+ K) r6 T) E±--------------------------------------------±----------------------------------------------------------------+
    : Q$ n" q; T2 F) @) U0 g% L| discardu256(unused:u256)                    | 丢弃值                                                          |. X7 G4 b! g, \; _7 o
    ±--------------------------------------------±----------------------------------------------------------------+4 q4 ^% u8 U" ~6 N
    | splitu256tou64(x:u256) -> (x1:u64, x2:u64,  | 将一个 u256 拆分为四个 u64                                      |5 E& W( l' r2 @) Q
    |                            x3:u64, x4:u64)  |                                                                 |5 V8 X% Q- ]0 t8 ]1 S
    ±--------------------------------------------±----------------------------------------------------------------++ ^- o+ U' U7 |3 Y0 \' C+ r
    | combineu64tou256(x1:u64, x2:u64, x3:u64,    | 将四个 u64 组合为一个 u256                                      |
    8 d, o1 D! {* P1 W|                  x4:u64) -> (x:u256)        |                                                                 |
    ; w3 |8 r) n# }2 F9 x" I1 g±--------------------------------------------±----------------------------------------------------------------+
    % S: @  q/ E% L: H+ H8 p; || keccak256(p:u256, s:u256) -> v:u256         | keccak(mem[p…(p+s)))                                          |
    : k: r6 N. v* Z/ j$ }: x# X±--------------------------------------------±----------------------------------------------------------------+
    6 _1 Y( e1 Z' i7 s后端- N$ @4 y) g( m6 E5 m5 y0 Z$ _
    后端或目标负责将 Yul 翻译到特定字节码。 每个后端都可以暴露以后端名称为前缀的函数。 我们为两个建议的后端保留 evm_ 和 ewasm_ 前缀。
    8 P- F3 j8 r' T" g后端: EVM
    ' k  U4 {- j. y  e" P: y7 w; @目标 |evm| 将具有所有用 evm_ 前缀暴露的 |evm| 底层操作码。6 e7 s6 A' ^  o' P
    后端: “EVM 1.5”. @2 o% k7 }& e6 R
    TBD+ x- F  n0 f7 ^: ^" ?) b, h+ C) G
    后端: eWASM8 e0 O0 ^) t8 o( n# T) V: l
    TBD0 z3 k9 t+ J: u( P2 K
    Yul 对象说明+ M8 K; ~3 S  }1 D' J. L
    语法::
    - t  a+ t* q. d  a顶层对象 = 'object' '{' 代码? ( 对象 | 数据 )* '}'
    6 g0 R+ T/ U% r  ]对象 = 'object' 字符串字面量 '{' 代码? ( 对象 | 数据 )* '}'
    ! [, W/ w' ~; n% }. F3 G代码 = 'code' 代码块
    ) D, }5 t( g- M, B数据 = 'data' 字符串字面量 十六进制字面量, j: {: L1 v! w# p
    十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
    + |; c" N6 E# t! _字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"'! |0 A0 T# d  q6 {* s
    在上面,代码块 指的是前一章中解释的 Yul 代码语法中的 代码块。
    % s6 _$ K' I. |  N" BYul 对象示例如下:# F& _/ t( {5 X+ h
    …code::
    3 d2 q- Z+ m: }; j/ [// 代码由单个对象组成。 单个 “code” 节点是对象的代码。
      D. P# a9 k1 J  {) R: w// 每个(其他)命名的对象或数据部分都被序列化
    ' g1 h' M* \6 }- u  {; f; S// 并可供特殊内置函数:datacopy / dataoffset / datasize 用于访问# f% ?  n5 i, ~0 C, Y3 E
    object {" u4 w' r6 f4 I0 R
        code {) _. F5 q$ q: D
            let size = datasize("runtime")
    - g* c$ z% g( _2 U4 K( Z* Z        let offset = allocate(size)$ V2 {7 g/ H; q, B3 T
            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy* l. B# C# ?: j" `
            datacopy(dataoffset("runtime"), offset, size)
    " l/ R+ V; ^% d# y        // 这是一个构造函数,并且运行时代码会被返回6 H- ?& \) K: @5 j2 X! X6 x2 v
            return(offset, size)% p, ^) j* A3 r, p
        }
    1 n0 E, l6 a; W8 j, p    data "Table2" hex"4123"
    # M8 ?# K3 P% n5 D    object "runtime" {
    . l$ n5 K( p+ P* L3 d) ]* g  O        code {
    : Z- O4 z1 ^, F  x8 t" F" R            // 运行时代码. T; r4 @5 }1 O0 `# K% q0 V
                let size = datasize("Contract2")& {* ~8 t4 k) x& g+ c* U5 j0 p( t, F3 f
                let offset = allocate(size)
    5 N1 J' d- Y) L* d4 x! ~  W            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy
    ) T: Z) i2 s4 ^6 W7 m5 Z            datacopy(dataoffset("Contract2"), offset, size)# l* h5 [0 l# c8 b: g4 z# _
                // 构造函数参数是一个数字 0x1234+ U1 X0 R( z% A+ s$ B
                mstore(add(offset, size), 0x1234)
    9 H' |: E2 V/ T3 n$ E            create(offset, add(size, 32))
    5 c6 f* s9 U) O  d8 F        }; n5 p+ n3 m5 Z
            // 内嵌对象。使用场景是,外层是一个工厂合约,而 Contract2 将是由工厂生成的代码
    & Q7 g1 v& s1 R        object "Contract2" {/ G, o! V8 Q' W3 o
                code {
    % s! z& t: a7 d- t% l0 [7 e2 \                // 代码在这 ...- w+ b) @( q  ?( ]
                }
    # ?! S7 n, D- C: A: e            object "runtime" {
    0 x8 M9 }6 O/ Y9 f6 J/ l                code {1 ~$ ~% E, Y- c5 p0 }
                        // 代码在这 ...5 f+ u) a  }. K- p! ~- ?; ]. [$ Q
                    }
    6 R9 F# f, Y, \7 p" W# [0 P: ^* A             }# E0 T# J  G) p
                 data "Table1" hex"4123"
    : {' x3 F! A/ g) u. r9 Z        }) O) {/ I& x. V: {  L
        }" V. I3 h, ^( V
    }
  • BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
    声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    成为第一个吐槽的人