Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Yul 语言说明

一夜雨十年灯潞
261 0 0
Yul (先前被也被称为 JULIA 或 IULIA)是一种可以编译到各种不同后端的中间语言( |evm| 1.0,|evm| 1.5,而 eWASM 也在计划中)。7 `' l0 p& t, I; ^- w
正因为如此,它被设计成为这三种平台的可用的共同标准。
9 K' n) }; R6 C它已经可以用于 Solidity 内部的“内联汇编”,并且未来版本的 Solidity 编译器甚至会将 Yul 用作中间语言。 为 Yul 构建高级的优化器阶段也将会很容易。! G- C9 l- X( d. P
… note::3 k" Q" z" j$ B& |+ D1 p
请注意,用于“内联汇编”的书写风格是不带类型的(所有的都是 ``u256``),内置函数与 |evm| 操作码相同。( d+ h7 [; \  X
有关详细信息,请参阅内联汇编文档。* c; Q. W( Q1 x
Yul 的核心组件是函数,代码块,变量,字面量,for 循环,if 条件语句,switch 条件语句,表达式和变量赋值。
: L: I9 M+ v" dYul 是强类型的,变量和字面量都需要通过前缀符号来指明类型。支持的类型有:bool, u8, s8, u32, s32,% e' _8 r( @6 @6 P( z
u64, s64, u128, s128, u256 和 s256。
/ S- B4 c/ W+ ]  S* v; QYul 本身甚至不提供操作符。如果目标平台是 |evm|,则操作码将作为内置函数提供,但如果后端平台发生了变化,则可以重新实现它们。3 B& T  \1 O8 S8 e: g) K7 }" }8 Y
有关强制性的内置函数的列表,请参阅下面的章节。/ o5 F( g2 G* @% s
以下示例程序假定 |evm| 操作码 mul,div 和 mo 是原生支持或可以作为函数用以计算指数的。
6 t1 t4 H+ ]) m# \* J… code::- n1 j7 V0 K  c3 Y' E5 t
{. N' r6 |, c- e- p$ n1 g. K
    function power(base:u256, exponent:u256) -> result:u256
- Y' i% y# F" h, y    {
6 h6 n2 w5 _! o! j        switch exponent
" u! W0 ]3 {5 s5 \; G' a        case 0:u256 { result := 1:u256 }
( v2 I9 `2 X# [! B3 P" Q/ y" u        case 1:u256 { result := base }  ]/ F+ {) P3 ]
        default:' b2 H( ~3 Y3 ^' B+ h
        {
4 f; i6 Z+ o$ o- O1 ~            result := power(mul(base, base), div(exponent, 2:u256))1 M  `7 c* O! \6 F0 e* \
            switch mod(exponent, 2:u256)
7 v* [7 J. H4 X                case 1:u256 { result := mul(base, result) }1 |: s5 m* P; L# ~" {
        }
# e9 k" J4 r- y8 y0 d9 |    }: r5 g9 \, P' m  L
}
5 l, D0 B- F1 \  f' |6 O, M5 N也可用 for 循环代替递归来实现相同的功能。这里,我们需要 |evm| 操作码 lt (小于)和 add 可用。' g! a- A6 {9 x7 H0 N6 {# h
… code::/ a& m7 p  s: A6 T
{
$ J3 F: S+ V- ^0 F' C" Q! e    function power(base:u256, exponent:u256) -> result:u256. S3 B" L% b. s8 @
    {
8 Y) h7 X' I$ I* D% k; \6 L        result := 1:u256" Q! Z8 w2 n# y7 a
        for { let i := 0:u256 } lt(i, exponent) { i := add(i, 1:u256) }
8 S9 n! e1 u+ ]7 z        {
5 c" s  ]; ^4 @5 {% ?            result := mul(result, base)
5 k6 t( T; O, j2 A$ ]        }
0 o  Y2 c  n& Z7 Y" N    }! W8 c, g1 I6 C3 F$ F; U
}0 {: ~& |) M, k" X& ~
Yul 语言说明
, i( A9 I& V; h! S) i本章介绍 Yul 代码。Yul 代码通常放置在一个 Yul 对象中,它将在下一节中介绍。! r) k. o: l3 Z
语法::
4 U7 e! h; V5 z* M代码块 = '{' 语句* '}'
" n6 \# F! Z/ ]语句 =9 z8 r, T, f+ g9 S
    代码块 |- ~1 D. z8 Y( \* O( y+ U5 F$ v
    函数定义 |
: W/ d$ [2 M' D- B7 n; @" D) t    变量声明 |
4 e! @1 V) C& l% v. I  X# d7 z, \    赋值 |9 j8 p" ~) u. _4 H" g
    表达式 |
& f0 y7 M- v' l' I$ ^6 ~9 e, p    Switch |# u# j3 S! ?: B# U  q
    For 循环 |
1 W8 w* W7 Z  }6 `! B% f( n    循环中断5 k( [9 _( X% S0 i  n! g* c; f0 s  Y; I
函数定义 =( J& N' j$ [3 r4 h. r1 S& A
    'function' 标识符 '(' 带类型的标识符列表? ')'
; j) H& _) l9 m8 S5 z0 d- O" E    ( '->' 带类型的标识符列表 )? 代码块- B5 Z; N$ `$ b. r- {
变量声明 =
6 g  z% \5 B- _; B    'let' 带类型的标识符列表 ( ':=' 表达式 )?
  R7 j/ P7 I0 b- _1 @: \赋值 =
+ ?& c* Z- P4 h# j& u    标识符列表 ':=' 表达式2 T5 X2 Q/ q) b, G2 l: c4 H; c
表达式 =
0 G# p1 N7 b& G# g/ I    函数调用 | 标识符 | 字面量5 Y4 z% j1 b& u' M
If 条件语句 =, D5 }* U- r6 P0 l
    'if' 表达式 代码块
3 e" o! |* A/ d" JSwitch 条件语句 =6 H- w0 ^  D/ T8 _9 D
    'switch' 表达式 Case* ( 'default' 代码块 )?
- f5 }( u9 b3 n  ECase =
/ K. _% h  Q+ t+ X5 Z$ s    'case' 字面量 代码块1 ?+ ~, G$ ?' S5 V! s3 K
For 循环 =+ a5 l. n( x6 Z- P
    'for' 代码块 表达式 代码块 代码块
- s9 s2 H. h0 w( ^6 ]循环中断 =- m' t$ E# R. |" l) D( X$ B
    'break' | 'continue'! {7 o3 a+ G/ w; u% u6 d% n
函数调用 =" P1 ~- E- R: O4 B
    标识符 '(' ( 表达式 ( ',' 表达式 )* )? ')'& a: u9 H& Q, X* I; n
标识符 = [a-zA-Z_$] [a-zA-Z_0-9]*
5 r( j0 C4 h6 W& e  n标识符列表 = 标识符 ( ',' 标识符)*5 ?- @' G! x; j
类型名 = 标识符 | 内置的类型名+ l3 A. y, g) T7 i! T5 W
内置的类型名 = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )3 ?9 ~5 `2 A$ B' Z7 L
带类型的标识符列表 = 标识符 ':' 类型名 ( ',' 标识符 ':' 类型名 )*
0 t) F/ y+ ~+ O, S2 X字面量 =6 f, b# q+ J, T  r! D- e! w4 D
    (数字字面量 | 字符串字面量 | 十六进制字面量 | True字面量 | False字面量) ':' 类型名" y% A' f+ J5 m! R1 f" u; |4 L
数字字面量 = 十六进制数字 | 十进制数字
" P! T, q: V( G) T. N7 f2 j% O6 B十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
" |. m5 ?/ _6 Y字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"'5 t( f/ d' i2 D* A& x) Q
True字面量 = 'true'' P! b1 t8 f; q: s2 E  j3 a! x
False字面量 = 'false'9 E- D* k$ v4 e& H0 J
十六进制数字 = '0x' [0-9a-fA-F]+
' S; e8 K. y! J4 T" m' [" n& A十进制数字 = [0-9]+$ U; O7 m4 p  R$ P
语法层面的限制& l' Q1 c% e2 z7 \! U
Switches 必须至少有一个 case(包括 default )。
5 B, i/ e5 B1 V  x' f' i) ~+ \如果表达式的所有可能值都被覆盖了,那么不应该允许使用 default
: _4 p6 I! r( ]( A- f4 m/ R(即带 bool 表达式的 switch 语句同时具有 true case 和 false case 的情况下不应再有 default 语句)。
9 i7 M" b* m3 J0 J, Q, k: d1 L每个表达式都求值为零个或多个值。 标识符和字面量求值为一个值,函数调用求值为所调用函数的返回值。
! o. L% ^1 |0 s( {( y% V在变量声明和赋值中,右侧表达式(如果存在)求值后,必须得出与左侧变量数量相等的值。
& i- W+ [7 ]: }* j6 _5 B这是唯一允许求值出多个值的表达式。: p/ M  h% `6 x4 p, T
那种同时又是语句的表达式(即在代码块的层次)求值结果必须只有零个值。
9 s' M& x/ `5 V# R7 r1 c在其他所有情况中,表达式求值后必须仅有一个值。
& r, o' }" \5 |continue 和 break 语句只能用在循环体中,并且必须与循环处于同一个函数中(或者两者都必须在顶层)。+ Z9 ~% X1 R: \2 [% s; _9 G; @
for 循环的条件部分的求值结果只能为一个值。( x' @( c- Y2 T
字面量不可以大于它们本身的类型。已定义的最大类型宽度为 256 比特。% D( [. i2 l3 h$ f' I4 k- u' {. _
作用域规则
: w! T+ |' [7 vYul 中的作用域是与块(除了函数和 for 循环,如下所述)和所有引入新的标识符到作用域中的声明: p" z! d5 H7 D& p8 y
( FunctionDefinition ,VariableDeclaration )紧密绑定的。0 n& X) Y) S& d2 H8 n0 `
标识符在将其定义的块中可见(包括所有子节点和子块)。- f6 p) i3 K  H! a; ^6 ?) `
作为例外,for 循环的 “init” 部分中(第一个块)定义的标识符在 for 循环的所有其他部分(但不在循环之外)中都是可见的。1 l4 ^8 p, b( u$ N, H- D- K( X! w
在 for 循环的其他部分声明的标识符遵守常规的作用域语法规则。& m% _3 d- }3 k+ T% e2 E/ h
函数的参数和返回参数在函数体中可见,并且它们的名称不能相同。' d; e' T$ Q' t, _& O# [
变量只能在声明后引用。 尤其是,变量不能在它们自己的变量声明的右边被引用。% t- c2 a, E1 ^; f" D8 J- n# }2 u
函数可以在声明之前被引用(如果它们是可见的)。+ h. C% w. f+ o% X1 b1 Z) m% f9 r
Shadowing 是不被允许的,即是说,你不能在同名标识符已经可见的情况下又定义该标识符,即使它是不可访问的。& m) b# B1 {( t" J
在函数内,不可能访问声明在函数外的变量。
4 g8 S* p8 l% ?9 G5 o) z形式规范3 D% v- z. O( G, y; l) ?
我们通过在 AST 的各个节点上提供重载的求值函数 E 来正式指定 Yul。
3 ^2 b& R; d) F/ A2 k+ Q# a任何函数都可能有副作用,所以 E 接受两个状态对象和 AST 节点作为它的参数,并返回两个新的状态对象和数量可变的其他值。
1 y; K3 q$ `! A3 ^8 u3 }5 l$ {: n这两个状态对象是全局状态对象(在 |evm| 的上下文中是 |memory|,|storage| 和区块链的状态)和本地状态对象(局部变量的状态,即 |evm| 中堆栈的某个段)。
3 i$ m8 R9 i7 {  I) Q/ D如果 AST 节点是一个语句,E 将返回两个状态对象和一个用于 break 和 continue 语句的 “mode”。
% o+ Z2 I7 M  J+ x如果 AST 节点是表达式,则 E 返回两个状态对象,并返回与表达式求值结果相同数量的值。* w/ I' O. U( o$ \6 V5 C& G
在这份高层次的描述中,并没有对全局状态的确切本质进行说明。
- Z& l2 }) ~. ^) r本地状态 L 是标识符 i 到值 v 的映射,表示为 L = v。0 R) N. Y% f+ Q, G5 K, t
对于标识符 v, 我们用 $v 作为标识符的名字。
& [: K/ Z3 g% r1 L) {) }6 M. e我们将为 AST 节点使用解构符号。3 b* F' e. i; t/ _+ m; K2 v
… code::. d- @( @8 J: ^* @, |
E(G, L, : Block) =
. m" X  {# h7 G, K% Q7 n2 _0 S    let G1, L1, mode = E(G, L, St1, ..., Stn)0 g# `" ]+ T9 h( J2 x
    let L2 be a restriction of L1 to the identifiers of L( Q+ s. A9 x4 ^4 L, H/ u8 j1 F
    G1, L2, mode
3 X8 O( n" E" J$ o% q( U" eE(G, L, St1, ..., Stn: Statement) =* t: B- ~6 r- O8 v8 _8 x0 n
    if n is zero:2 ?" c. y5 E! k& z& \
        G, L, regular5 g) q) P1 V/ @- q0 E, s+ i
    else:
7 Z3 S3 N3 r! x        let G1, L1, mode = E(G, L, St1)6 V, ^5 |/ s4 r5 G# L0 I
        if mode is regular then
$ l* z1 K, L' O2 }, y0 {9 `            E(G1, L1, St2, ..., Stn)
& G- K( i4 b3 |( m- J5 D5 |  |( r        otherwise, N( u4 t. x/ m% F! v2 F* C5 |
            G1, L1, mode
) |5 w8 m, S" D0 b( E8 dE(G, L, FunctionDefinition) =$ S' ]! L  B$ ~# ?) @/ ^
    G, L, regular
$ V1 H# _) J" wE(G, L, : VariableDeclaration) =, j: F: S; ^6 K0 ]
    E(G, L, : Assignment)
0 x" e2 R. X- t) e; J2 `4 QE(G, L, : VariableDeclaration) =- [3 T7 H1 d5 _+ N7 u5 u
    let L1 be a copy of L where L1[$vari] = 0 for i = 1, ..., n
; e0 u! c& o2 \' C- K* {" R$ Z    G, L1, regular
2 |8 w/ h8 L* a8 a( a; v  g/ LE(G, L, : Assignment) =
1 ^3 K7 @9 L/ {; P2 o- h6 |    let G1, L1, v1, ..., vn = E(G, L, rhs)
- D$ X# \8 E' D, y+ V    let L2 be a copy of L1 where L2[$vari] = vi for i = 1, ..., n
2 b/ Q7 [, `  {- A8 Q: \    G, L2, regular" h! V& P! L* @4 M3 b; l
E(G, L, : ForLoop) =
' }- H8 F$ F- y% b    if n >= 1:3 u  o$ d5 G  M2 `7 l0 a- Y8 q
        let G1, L1, mode = E(G, L, i1, ..., in); t/ D( y8 ]5 l7 L
        // 由于语法限制,mode 必须是规则的
$ W/ ~! N/ U% ?. j4 ^( t/ J        let G2, L2, mode = E(G1, L1, for {} condition post body)
5 f/ T" \2 y" o8 p* O9 f+ ^% y4 o2 O        // 由于语法限制,mode 必须是规则的5 C- w/ ]) _2 k: A4 r! Z3 {
        let L3 be the restriction of L2 to only variables of L- x  K& a8 N) t/ O
        G2, L3, regular2 ^: \! H' x: `$ s( E5 E$ Y
    else:
- l/ k! G* P' d. U# j        let G1, L1, v = E(G, L, condition)! {2 w2 k& y- H8 s; o6 @
        if v is false:# _) n" f! K# S
            G1, L1, regular
3 @0 e. V4 v; o( l7 y        else:
% F: I/ ]/ R8 b& E            let G2, L2, mode = E(G1, L, body)
7 Q. R; J$ }& C* {8 E  b# ~            if mode is break:4 B4 d) S3 t6 D  |8 M+ L
                G2, L2, regular. ~$ C* H6 G- m6 P
            else:8 ^. ]8 `+ [, q+ q- \5 c, w
                G3, L3, mode = E(G2, L2, post)
1 h2 |& M+ T! W3 r4 e! c  ]                E(G3, L3, for {} condition post body)
" i: l$ ]3 Z: [6 q+ K' k8 bE(G, L, break: BreakContinue) =
' L, L5 S0 R6 N; j6 Z    G, L, break
0 `$ U$ \) c7 ?- c! n, e' Y6 U& CE(G, L, continue: BreakContinue) =
$ B* Y8 l! t0 R) W    G, L, continue2 ~% E' E+ d9 c0 V" V" I
E(G, L, : If) =- {5 x- z" |$ j1 M. j5 m
    let G0, L0, v = E(G, L, condition)
6 `# c# }% ?% k/ H& d    if v is true:
3 J* X. l3 Y# u& r4 C* f8 o' X* A        E(G0, L0, body)
. Y2 p% D" B. g/ w- }  f    else:. _3 o) Z* W" M* r
        G0, L0, regular
1 I$ p, l, q- oE(G, L, : Switch) =, k# J4 i% C3 n) l& {# W
    E(G, L, switch condition case l1:t1 st1 ... case ln:tn stn default {})7 f, H; _8 \7 f4 R% ]% E6 p. q
E(G, L, : Switch) =
4 R  K$ y! _" [; P/ ?6 J& @    let G0, L0, v = E(G, L, condition)
* o3 a6 s% H) {" K& L  g8 r6 R4 V    // i = 1 .. n& B) ?3 q! K/ i2 h
    // 对字面量求值,上下文无关4 r' @/ H9 q$ @6 D4 ]" {
    let _, _, v1 = E(G0, L0, l1)* _* A$ q4 j' _, j* n
    .../ H! F$ z7 h' N0 H
    let _, _, vn = E(G0, L0, ln)7 }1 S: Q4 c/ C% H
    if there exists smallest i such that vi = v:/ S$ o$ c" N$ Z$ G
        E(G0, L0, sti)
+ l, X3 \% C5 _    else:* J7 R/ }* x2 r( P2 D
        E(G0, L0, st')
2 g2 q6 Z4 `1 [) L" _% f0 d6 t1 Z2 nE(G, L, : Identifier) =
- F3 z" j) c& i( p    G, L, L[$name]
+ @) K. k' v% b; m& a/ ?9 _, v3 P- fE(G, L, : FunctionCall) =( b3 r/ V; g; ], L. C8 G
    G1, L1, vn = E(G, L, argn)
; l/ F* I; V4 H/ a8 b' T    ...
3 |$ E' j( O0 q6 i    G(n-1), L(n-1), v2 = E(G(n-2), L(n-2), arg2)/ i) Y$ P0 J9 K3 b/ u1 C( K
    Gn, Ln, v1 = E(G(n-1), L(n-1), arg1)4 D2 o/ C3 q5 v- V% l. o7 a
    Let  ret1, ..., retm block>
# I$ A5 l1 e' v- l    be the function of name $fname visible at the point of the call.1 y. k4 \5 I  }! ?
    Let L' be a new local state such that
, Y& J9 a6 s; l, q3 @; V    L'[$parami] = vi and L'[$reti] = 0 for all i.
) k+ B1 ], I' E. X  w! c    Let G'', L'', mode = E(Gn, L', block)7 a4 g9 [7 r$ u3 ^9 Q: c: n; g
    G'', Ln, L''[$ret1], ..., L''[$retm]
* @( I, {  Q% j+ A: u4 SE(G, L, l: HexLiteral) = G, L, hexString(l),5 ]3 N2 [9 B' k) h& p
    where hexString decodes l from hex and left-aligns it into 32 bytes2 X, b( T3 o, l4 L* M
E(G, L, l: StringLiteral) = G, L, utf8EncodeLeftAligned(l),
5 ?1 }0 \/ G( v) Q& ~    where utf8EncodeLeftAligned performs a utf8 encoding of l& _! U, B2 U) }7 ?1 n. w, R' ]
    and aligns it left into 32 bytes( B! {6 J3 B$ U) g
E(G, L, n: HexNumber) = G, L, hex(n)
' p% z: D6 S- ]0 f6 Q& b5 S  p# N7 K& N    where hex is the hexadecimal decoding function3 P0 Q+ d1 |2 v* H8 b
E(G, L, n: DecimalNumber) = G, L, dec(n),
& I9 I4 Q8 @* H, l  O    where dec is the decimal decoding function
6 U' ?3 z$ R; J8 }  {3 U类型转换函数( q. E* W9 C) Z! m* w; q6 h
Yul 不支持隐式类型转换,因此存在提供显式转换的函数。0 s1 _# V. f! s: t7 \
在将较大类型转换为较短类型时,如果发生溢出,则可能会发生运行时异常。
' I" S' |$ B9 @* ]1 b下列类型的“截取式”转换是允许的:. o9 I5 I# Q2 S9 F# R
  • bool
  • u32
  • u64
  • u256
  • s256
    3 y8 w0 \, D# e& {# g# M, M0 |
    . i, y8 }0 l, U+ I2 {
    这里的每种类型的转换函数都有一个格式为 to(x:) -> y: 的原型,
    # A3 k* @" z) n比如 u32tobool(x:u32) -> y:bool、u256tou32(x:u256) -> y:u32 或 s256tou256(x:s256) -> y:u256。- c' N/ D, N; J: {5 r! G$ J' o
    … note::+ g6 h, g& N* g  I6 C9 C9 s& B0 x
    ``u32tobool(x:u32) -> y:bool`` 可以由 ``y := not(iszerou256(x))`` 实现,并且! |- ]2 d9 A& H+ A$ ?. e- Z1 r8 ^
    ``booltou32(x:bool) -> y:u32`` 可以由 ``switch x case true:bool { y := 1:u32 } case false:bool { y := 0:u32 }`` 实现, J. s# ?# \' I, Q, K) i
    低级函数6 z* o; }8 W; g  Z: q/ o5 a9 o
    以下函数必须可用:5 z& l! H1 T% U: N
    ±--------------------------------------------------------------------------------------------------------------+
    : C: ~9 W2 Y; _1 w4 o* c. X| 逻辑操作                                                                                                    |3 S; i2 D4 a9 [% }% a; H! ]
    ±--------------------------------------------±----------------------------------------------------------------+% D. V6 |& L0 {0 y; j& q; u
    | not(x:bool) -> z:bool                       | 逻辑非                                                          |
    0 _# s2 i8 l/ D- B1 k- e±--------------------------------------------±----------------------------------------------------------------+- L$ ~0 s* H. W
    | and(x:bool, y:bool) -> z:bool               | 逻辑与                                                          |
    3 O4 v9 s+ [- a4 k/ N$ ~±--------------------------------------------±----------------------------------------------------------------+
    , {; l8 C6 {. G9 ^( q| or(x:bool, y:bool) -> z:bool                | 逻辑或                                                          |4 k! y( o( c$ c  l, K
    ±--------------------------------------------±----------------------------------------------------------------+* c3 H* m% O( d9 z
    | xor(x:bool, y:bool) -> z:bool               | 异或                                                            |" w' @5 b% I2 v9 P: b
    ±--------------------------------------------±----------------------------------------------------------------+' W$ R$ H. l' D$ n; I+ a0 m9 Z
    | 算术操作                                                                                                    |' ~" S8 Z+ f% y+ b; ?# X8 I
    ±--------------------------------------------±----------------------------------------------------------------+$ }/ B3 q! E" T) y
    | addu256(x:u256, y:u256) -> z:u256           | x + y                                                           |
    7 W+ a$ v7 u3 M9 [5 F; S±--------------------------------------------±----------------------------------------------------------------+( W2 M  M* O* f! X/ k3 w
    | subu256(x:u256, y:u256) -> z:u256           | x - y                                                           |
    - W, N9 \2 s; P1 n5 H/ p5 z: }±--------------------------------------------±----------------------------------------------------------------+" a3 h. S0 `8 \  U' \& [. U
    | mulu256(x:u256, y:u256) -> z:u256           | x * y                                                           |
    # P2 }/ i; f& f& C) b* y4 |! |. x$ N±--------------------------------------------±----------------------------------------------------------------+
    * X- f; Z9 b9 k| divu256(x:u256, y:u256) -> z:u256           | x / y                                                           |% f) F2 A7 s! I! K. N
    ±--------------------------------------------±----------------------------------------------------------------+# G; b% g( X* W9 K+ ~* P
    | divs256(x:s256, y:s256) -> z:s256           | x / y, 有符号数用补码形式                                       |* E; C* P  u, V4 v; ^$ h2 f
    ±--------------------------------------------±----------------------------------------------------------------+5 W6 V& q  ?, r- u: f4 s4 T
    | modu256(x:u256, y:u256) -> z:u256           | x % y                                                           |% N5 R2 z( Y  C  V1 G
    ±--------------------------------------------±----------------------------------------------------------------+
    1 o& N  T/ a! g3 e8 o* r* ^: a4 r| mods256(x:s256, y:s256) -> z:s256           | x % y, 有符号数用补码形式                                       |0 r9 p  B2 R) o" a, u( r
    ±--------------------------------------------±----------------------------------------------------------------+
    * I+ ~% K& `# Q5 y2 J7 o0 K| signextendu256(i:u256, x:u256) -> z:u256    | 从第 (i*8+7) 位开始进行符号扩展,从最低符号位开始计算           |, ^1 O. W! Q3 `
    ±--------------------------------------------±----------------------------------------------------------------+3 K3 ]; {) f2 K" d4 |9 O
    | expu256(x:u256, y:u256) -> z:u256           | x 的 y 次方                                                     |
    $ Y; S) U, p; f# @' j' Y2 Q$ W! T4 z' U0 u±--------------------------------------------±----------------------------------------------------------------+! h$ D" @0 m$ G# _% b
    | addmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x + y) % m                                |
    4 z5 A: h2 t! v5 k±--------------------------------------------±----------------------------------------------------------------+! G0 e% I3 x' c! C& A8 `
    | mulmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x * y) % m                                |" [/ m+ }3 Y$ I/ b
    ±--------------------------------------------±----------------------------------------------------------------+) s3 X! S% {1 N- p
    | ltu256(x:u256, y:u256) -> z:bool            | 若 x  z:bool            | 若 x > y 为 true, 否则为 false                                  |
    0 i8 e# C' D$ ?; T±--------------------------------------------±----------------------------------------------------------------+/ E6 o2 C; u6 x$ Q7 U
    | sltu256(x:s256, y:s256) -> z:bool           | 若 x  z:bool           | 若 x > y 为 true, 否则为 false                                  |
    3 E% _& j7 R% A; S8 M& ]7 F|                                             | 有符号数用补码形式                                              |9 t( R' t* n$ {5 D) `3 B
    ±--------------------------------------------±----------------------------------------------------------------+
    4 j7 _' D( f: w| equ256(x:u256, y:u256) -> z:bool            | 若 x == y 为 true, 否则为 false                                 |4 K3 b! W  e) j$ e' ]0 j
    ±--------------------------------------------±----------------------------------------------------------------+
    : Z! ]4 b" |' F9 d: {| iszerou256(x:u256) -> z:bool                | 若 x == 0 为 true, 否则为 false                                 |
    ! z* `+ b, D# C2 ?±--------------------------------------------±----------------------------------------------------------------+
      j" l5 u! y4 e) M9 u| notu256(x:u256) -> z:u256                   | ~x, 对 x 按位非                                                 |/ K1 ?' k) q% U7 [1 ?) \5 ~
    ±--------------------------------------------±----------------------------------------------------------------+) }7 V0 E$ a2 U3 q
    | andu256(x:u256, y:u256) -> z:u256           | x 和 y 按位与                                                   |- I3 ~- H1 I) o' a
    ±--------------------------------------------±----------------------------------------------------------------+1 E" L( V  B( u% v6 B: \& M
    | oru256(x:u256, y:u256) -> z:u256            | x 和 y 按位或                                                   |
    $ g$ `0 a. g9 K! V±--------------------------------------------±----------------------------------------------------------------+
    + t3 M4 U2 }  v; o# D+ ]  c  p| xoru256(x:u256, y:u256) -> z:u256           | x 和 y 按位异或                                                 |  o& V( w6 S: ?+ |7 N: U
    ±--------------------------------------------±----------------------------------------------------------------+
    / M1 r0 Z$ L4 q& e| shlu256(x:u256, y:u256) -> z:u256           | 将 x 逻辑左移 y 位                                              |2 D. E2 S1 h4 @" @
    ±--------------------------------------------±----------------------------------------------------------------+
    7 P$ G# w" \. Y1 i% A! ^| shru256(x:u256, y:u256) -> z:u256           | 将 x 逻辑右移 y 位                                              |$ ?# H; u/ X( t1 b) I' J
    ±--------------------------------------------±----------------------------------------------------------------+& c, e  b7 `/ R
    | saru256(x:u256, y:u256) -> z:u256           | 将 x 算术右移 y 位                                              |! P/ @+ x: j$ n
    ±--------------------------------------------±----------------------------------------------------------------+
    # w) M' B% `' ]; `9 [, e| byte(n:u256, x:u256) -> v:u256              | x 的第 n 字节,这里的索引位置是从 0 开始的;                    |7 e- v/ L% m* u* d
    |                                             | 能否用 and256(shr256(n, x), 0xff) 来替换它,                    |
    ; B# h4 }4 [& n' m|                                             | 并使它在 EVM 后端之外被优化呢?                                 |, M$ N5 l# Y% H- S2 _& m4 N
    ±--------------------------------------------±----------------------------------------------------------------+9 X. ?  Y/ ~  L$ n' Y! E. `
    | 内存和存储                                                                                                  |
    + n0 ^) m0 L. f7 u# V±--------------------------------------------±----------------------------------------------------------------+7 x6 Q) o( N- y1 {' S, {* U0 q
    | mload(p:u256) -> v:u256                     | mem[p…(p+32))                                                  |
    6 M4 ?2 P  r& p* Y, g2 p; F) M±--------------------------------------------±----------------------------------------------------------------+
    , c; S' F* J5 P| mstore(p:u256, v:u256)                      | mem[p…(p+32)) := v                                             |
    ( x+ L' R/ Y8 `7 A. h0 I' R; f±--------------------------------------------±----------------------------------------------------------------+
    & s/ D% h7 B$ r| mstore8(p:u256, v:u256)                     | mem := v & 0xff    - 仅修改单个字节                          |
    4 \2 w; S6 I' n1 p; e6 e±--------------------------------------------±----------------------------------------------------------------+& \' S2 W, Y. U' H, J! f+ Z1 d
    | sload(p:u256) -> v:u256                     | storage                                                      |; N7 r$ U) u' O3 e9 M- Z" t0 t
    ±--------------------------------------------±----------------------------------------------------------------+
    . ~( F2 m+ T) \$ }# w# @1 m| sstore(p:u256, v:u256)                      | storage := v                                                 |
    3 b6 W5 U* ~# X) c5 G±--------------------------------------------±----------------------------------------------------------------+
    & U8 `% T+ F  v( X4 W| msize() -> size:u256                        | 内存的大小, 即已访问过的内存的最大下标,                        |7 y' `, ?3 W: X! Q' O- a3 ~9 b
    |                                             | 因为内存扩展的限制(只能按字进行扩展)                          |5 y5 f2 D9 ]4 P
    |                                             | 返回值永远都是 32 字节的倍数                                    |
    ; k5 t/ U7 }& `/ W$ p& h±--------------------------------------------±----------------------------------------------------------------+% \# I1 |1 z8 K
    | 执行控制                                                                                                    |
    : m) o( s1 F8 G! M±--------------------------------------------±----------------------------------------------------------------+. f/ Y2 G( R  e6 i8 ~: d
    | create(v:u256, p:u256, s:u256)              | 以 mem[p…(p+s)) 上的代码创建一个新合约,发送                   |
    8 m- F5 Q7 f- D|                                             | v 个 wei,并返回一个新的地址                                    |
    ; B1 y9 a( d* N1 ~, ?±--------------------------------------------±----------------------------------------------------------------+
    5 p# g. a2 l% G: m- u3 U$ ]. F2 L| call(g:u256, a:u256, v:u256, in:u256,       | 调用地址 a 上的合约,以 mem[in…(in+insize)) 作为输入           |
    3 s9 B( F, z+ ~) u3 p| insize:u256, out:u256,                      | 一并发送 g gas 和 v wei ,以 mem[out…(out+outsize))            |
      ~6 v! T- {# m/ W, ?/ ~& V| outsize:u256)                               | 作为输出空间。若错误,返回 0 (比如,gas 用光                   |
    1 Q- N8 l7 Y3 y| -> r:u256                                   | 成功,返回 1                                                    |
    & b6 J. H; F( p0 I" w±--------------------------------------------±----------------------------------------------------------------+# J+ [0 k/ ]% r
    | callcode(g:u256, a:u256, v:u256, in:u256,   | 相当于 call 但仅仅使用地址 a 上的代码,                     |! M$ O4 x6 x% ~4 c
    | insize:u256, out:u256,                      | 而留在当前合约的上下文当中                                      |
    + V* x* X  K. H$ g4 Y| outsize:u256) -> r:u256                     |                                                                 |. n4 w& l5 W. n" `3 E; @( b
    ±--------------------------------------------±----------------------------------------------------------------+
    # q" K/ x6 F4 @+ `| delegatecall(g:u256, a:u256, in:u256,       | 相当于 callcode,                                           |; l1 u% }+ l" `- H% B
    | insize:u256, out:u256,                      | 但同时保留 caller                                           |) E# v: R5 a2 k1 v6 p! W
    | outsize:u256) -> r:u256                     | 和 callvalue                                                |
    8 V) B7 v# O. E. v3 Q±--------------------------------------------±----------------------------------------------------------------+8 B8 a+ B! m7 |! q- e! J
    | abort()                                     | 终止 (相当于EVM上的非法指令)                                    |; B, B& w1 B! W' b
    ±--------------------------------------------±----------------------------------------------------------------+: q; {; [. x" H2 l; h- {
    | return(p:u256, s:u256)                      | 终止执行,返回 mem[p…(p+s)) 上的数据                           |! b/ w# q+ S2 Q0 _- \2 ]
    ±--------------------------------------------±----------------------------------------------------------------+
    " Y9 {/ N1 Z; Z: u1 r1 }2 b| revert(p:u256, s:u256)                      | 终止执行,恢复状态变更,返回 mem[p…(p+s)) 上的数据             |4 W1 ^  D8 t  Y2 U
    ±--------------------------------------------±----------------------------------------------------------------+
    / G& H* r5 g1 L' \| selfdestruct(a:u256)                        | 终止执行,销毁当前合约,并且将余额发送到地址 a                  |9 J$ Y9 S9 ]" V2 A% p) W
    ±--------------------------------------------±----------------------------------------------------------------+
    : \9 Z* i# S/ H3 l| log0(p:u256, s:u256)                        | 用 mem[p…(p+s)] 上的数据产生日志,但没有 topic                 |
    : r8 G1 ~2 ?4 Z0 I! m4 Q±--------------------------------------------±----------------------------------------------------------------+
    * ^7 k* f! y+ h| log1(p:u256, s:u256, t1:u256)               | 用 mem[p…(p+s)] 上的数据和 topic t1 产生日志                   |
    - d7 ^  o7 K7 R( ]. M±--------------------------------------------±----------------------------------------------------------------+
    . C# N" d/ t% R' B1 J+ f| log2(p:u256, s:u256, t1:u256, t2:u256)      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2 产生日志               |
    2 w* S* j; i2 R( C- n5 q! U±--------------------------------------------±----------------------------------------------------------------+& Y9 l3 h" o4 D" \% p: F% c1 p
    | log3(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3 产生日志           |
    / u( a- k2 A# T1 e& J/ N$ i8 z8 }| t3:u256)                                    |                                                                 |& P$ w* W3 d% G& ^$ _0 v
    ±--------------------------------------------±----------------------------------------------------------------+
    $ s. m: n: {) y| log4(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3,t4                |9 ^6 h0 ]4 m4 o) ^: h0 P
    | t3:u256, t4:u256)                           | 产生日志                                                        |
    7 d$ [9 G! L( `8 r) S3 p±--------------------------------------------±----------------------------------------------------------------+
    # |5 Y8 t5 ]9 S; n/ S4 n2 y| 状态查询                                                                                                    |
    5 m# e% Y* z( W( G5 S±--------------------------------------------±----------------------------------------------------------------+$ l6 ]3 F/ B! V3 u$ K* k! M5 }
    | blockcoinbase() -> address:u256             | 当前的矿工                                                      |+ l, s$ A# ?7 F
    ±--------------------------------------------±----------------------------------------------------------------+9 v, Q! b; L/ b, a+ U* C
    | blockdifficulty() -> difficulty:u256        | 当前区块的难度                                                  |6 N  J2 {) x- q, Z6 c# Q( L
    ±--------------------------------------------±----------------------------------------------------------------+
    , ]4 `( R; t" j| blockgaslimit() -> limit:u256               | 当前区块的区块 gas 限制                                         |
    * i! V7 ]+ G! U  T* R  d$ [±--------------------------------------------±----------------------------------------------------------------+# |  {. V' M/ K' [
    | blockhash(b:u256) -> hash:u256              | 区块号为 b 的区块的哈希,                                       |6 f2 B& z; V) F; ~4 R9 \+ Y
    |                                             | 仅可用于最近的 256 个区块,不包含当前区块                       |
    ; o& p7 N, ^2 |& P9 v& d±--------------------------------------------±----------------------------------------------------------------+
    9 N8 p+ z$ ]: [( b% c8 C| blocknumber() -> block:u256                 | 当前区块号                                                      |9 z& ~* e2 I" A0 p; c; @- p
    ±--------------------------------------------±----------------------------------------------------------------+5 N) \! Z2 ~9 {, H
    | blocktimestamp() -> timestamp:u256          | 自 epoch 开始的,当前块的时间戳,以秒为单位                     |
    % n7 d! S4 ?# x% ~6 s+ {+ C! E# j8 s±--------------------------------------------±----------------------------------------------------------------+
    4 S/ G: O5 A, O" U& N/ _+ f| txorigin() -> address:u256                  | 交易的发送方                                                    |
    2 ^( z/ {/ q# E# A) ^±--------------------------------------------±----------------------------------------------------------------+
    / |& M* y  D9 |% _/ t( g% p| txgasprice() -> price:u256                  | 交易中的 gas 价格                                               |# R; Q5 l, b, m
    ±--------------------------------------------±----------------------------------------------------------------+
    3 T7 ?  z! W: d% j4 F6 [! G# R2 c; d| gasleft() -> gas:u256                       | 还可用于执行的 gas                                              |
    : U1 q# y3 N- h" c; D3 i: P±--------------------------------------------±----------------------------------------------------------------+9 Q* Z4 l/ ^' H2 M. y# X/ [  C/ T
    | balance(a:u256) -> v:u256                   | 地址 a 上的 wei 余额                                            |6 U$ F- s3 a' s4 W. F4 Q
    ±--------------------------------------------±----------------------------------------------------------------+4 B4 \* w4 R4 {0 k* N4 P6 Y
    | this() -> address:u256                      | 当前合约/执行上下文的地址                                      |
    2 b9 {: h. w8 m6 ~, c) H* m  s7 T±--------------------------------------------±----------------------------------------------------------------+0 {- V6 ]$ @6 y! u+ Y4 u- R- A1 ?  H
    | caller() -> address:u256                    | 调用的发送方 (不包含委托调用)                                   |' k: T3 h/ G& W& F4 r& T
    ±--------------------------------------------±----------------------------------------------------------------+
    ' W# O* p# h) X- T5 h| callvalue() -> v:u256                       | 与当前调用一起发送的 wei                                        |
    7 n( ], Z  O: I# Y±--------------------------------------------±----------------------------------------------------------------+
    7 ^. x7 K7 q2 k9 f5 ~| calldataload(p:u256) -> v:u256              | 从 position p 开始的 calldata (32 字节)                         |
    8 Y5 M1 l1 V  H. p±--------------------------------------------±----------------------------------------------------------------+
    + `. ]0 R1 \" z; }& x, U% F| calldatasize() -> v:u256                    | 以字节为单位的 calldata 的大小                                  |
    0 `6 u! \% v% t- q% T9 o±--------------------------------------------±----------------------------------------------------------------+
    : }3 y/ I# [& E# K" o4 Y, W: l* i| calldatacopy(t:u256, f:u256, s:u256)        | 从位置为 f 的 calldata 中,拷贝 s 字节到内存位置 t              |
    9 J' _! {, {, B& j) E±--------------------------------------------±----------------------------------------------------------------+& o1 I7 O. N/ L* a
    | codesize() -> size:u256                     | 当前合约/执行上下文的代码大小                                  |
    # ?$ E' Z# {. C! Z±--------------------------------------------±----------------------------------------------------------------+2 s6 c: O3 R7 d
    | codecopy(t:u256, f:u256, s:u256)            | 从 code 位置 f 拷贝 s 字节到内存位置 t                          |8 F, o' h& Z2 c
    ±--------------------------------------------±----------------------------------------------------------------+& ^& s; D" W' P
    | extcodesize(a:u256) -> size:u256            | 地址 a 上的代码大小                                             |4 J/ E* ~. S+ E- e2 }1 \: j
    ±--------------------------------------------±----------------------------------------------------------------+  J2 Y, J- }+ J" ~; A0 R
    | extcodecopy(a:u256, t:u256, f:u256, s:u256) | 相当于 codecopy(t, f, s),但从地址 a 获取代码                   |  ^8 O) j" P% c+ r5 P
    ±--------------------------------------------±----------------------------------------------------------------+
    0 P+ g$ W4 \+ V' h0 [& E/ g7 M- H| 其他                                                                                                        |+ b2 T6 P0 d, S9 F
    ±--------------------------------------------±----------------------------------------------------------------+
    & n( G- ~4 g' z  W- z) _| discard(unused:bool)                        | 丢弃值                                                          |1 M1 T) [6 A4 g3 ~# Y8 ^; ?
    ±--------------------------------------------±----------------------------------------------------------------+
    . q, }! G+ D* j+ u| discardu256(unused:u256)                    | 丢弃值                                                          |
    9 p7 l4 d9 D3 _2 n$ w±--------------------------------------------±----------------------------------------------------------------+9 H  ]5 J7 z$ o: z, [
    | splitu256tou64(x:u256) -> (x1:u64, x2:u64,  | 将一个 u256 拆分为四个 u64                                      |& J) l0 m7 r/ p! b
    |                            x3:u64, x4:u64)  |                                                                 |
    6 p$ o0 G5 E+ {1 {) t±--------------------------------------------±----------------------------------------------------------------+8 D4 c% r9 E, c4 O4 M7 v+ R
    | combineu64tou256(x1:u64, x2:u64, x3:u64,    | 将四个 u64 组合为一个 u256                                      |7 N+ X2 J. W- U0 H
    |                  x4:u64) -> (x:u256)        |                                                                 |( t! d" r5 c: o% w# b1 T; [% F
    ±--------------------------------------------±----------------------------------------------------------------+5 Q# B" J4 K; B$ ~: r  N
    | keccak256(p:u256, s:u256) -> v:u256         | keccak(mem[p…(p+s)))                                          |
    0 y- v. V; L  [' V±--------------------------------------------±----------------------------------------------------------------+
    : _" U! T' O3 u, }+ S1 S后端1 s7 ]7 ?# H. e; q7 m' T8 W
    后端或目标负责将 Yul 翻译到特定字节码。 每个后端都可以暴露以后端名称为前缀的函数。 我们为两个建议的后端保留 evm_ 和 ewasm_ 前缀。' G9 x+ `  g  S7 l  z. L
    后端: EVM+ s0 s+ v* K0 C- j! l
    目标 |evm| 将具有所有用 evm_ 前缀暴露的 |evm| 底层操作码。
    % C& K- ?2 D( V) H后端: “EVM 1.5”! W1 s2 ~- ]) c/ q
    TBD, x) a3 ]8 A2 H4 j1 _
    后端: eWASM9 Z3 l( L# n. f% e
    TBD
    8 `$ r5 I2 x* ]& |- E* `* Q( I0 @Yul 对象说明  f  }% A2 o9 x5 y+ [
    语法::
    4 S8 M. q9 U. e; r: Q$ @顶层对象 = 'object' '{' 代码? ( 对象 | 数据 )* '}'
    ! \  C4 y+ J8 s2 w8 J' t对象 = 'object' 字符串字面量 '{' 代码? ( 对象 | 数据 )* '}': J1 i5 r2 @" [5 ]! p
    代码 = 'code' 代码块  `+ U% M# a5 K! Q/ |' p0 _* h
    数据 = 'data' 字符串字面量 十六进制字面量  p; K' U5 y1 u7 C
    十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')& g0 ]& r1 |/ w& K
    字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"'7 h4 C$ e0 d1 ?; X
    在上面,代码块 指的是前一章中解释的 Yul 代码语法中的 代码块。2 }0 \4 T" m) s8 T* }/ m0 |
    Yul 对象示例如下:1 q  Z. x) {1 I% O' [1 y3 ~! f
    …code::1 g7 z' \% g$ w
    // 代码由单个对象组成。 单个 “code” 节点是对象的代码。
    4 `8 T& t# h- U& F5 `: y// 每个(其他)命名的对象或数据部分都被序列化  V0 P$ t+ {. u3 ?2 k
    // 并可供特殊内置函数:datacopy / dataoffset / datasize 用于访问
    # y+ s$ K! y. }# S2 Fobject {. O1 ~  o3 {2 h! N5 {: y
        code {* s1 F" i, {6 A  I
            let size = datasize("runtime")
    - U; b* F: ~# W; ^$ S, b        let offset = allocate(size)  p0 T+ r6 t, s* L6 H  f
            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy) U9 c6 g/ c5 ?( k+ K$ i
            datacopy(dataoffset("runtime"), offset, size): ?, L$ I( ~4 S$ }# h: S
            // 这是一个构造函数,并且运行时代码会被返回6 j- u4 I( v0 G' U. ~) U6 d7 W' d5 m
            return(offset, size)
    $ s8 U" j( S; j( R5 b( {+ O    }
    ; {9 d4 [$ }% E5 T, b6 p. U    data "Table2" hex"4123"
    ! h1 i: q6 y$ u- b4 U    object "runtime" {' }# l' q( m" L4 t/ `  v
            code {0 k+ w! W7 R( Q: d+ M
                // 运行时代码- o) f* e0 n8 ?+ H
                let size = datasize("Contract2")
    ) t6 B, e$ Q- Z& q5 j9 e            let offset = allocate(size)
    & @7 n& h; ?) f; x            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy
    : {6 f' C& b# Y            datacopy(dataoffset("Contract2"), offset, size)
    ) L3 R. m) H, J) J1 a: G. \            // 构造函数参数是一个数字 0x1234
    " e* y( Z$ K1 {" U8 k: C# L            mstore(add(offset, size), 0x1234)8 N/ e- `: l; g) u5 ~. P
                create(offset, add(size, 32))8 I9 P# k7 r8 n2 P7 Z$ W. J
            }
    ' @) i" t; N1 z) O; O7 h: @        // 内嵌对象。使用场景是,外层是一个工厂合约,而 Contract2 将是由工厂生成的代码
    2 j+ B5 p$ e% r6 J        object "Contract2" {1 W4 K/ M# N7 Q% _. u6 U
                code {
    , W6 W8 J5 L7 B2 u                // 代码在这 ...
    & @& |3 a! c+ ^' }6 p( E# L, Q            }
    0 {9 e2 d8 [- o! }+ o            object "runtime" {' b+ g' I  {' D  Q5 ^  }" l
                    code {
    8 g% x; R; G4 G2 x- P; T9 v4 |                    // 代码在这 ...5 c7 |% G7 \! r% W
                    }
    # P0 i! L- ~7 W( i2 j- f             }
    ! h! g  R0 m) p+ t9 s9 H             data "Table1" hex"4123"2 g! S! q( \% A
            }
    ' X" I; J) @9 O9 y    }$ H: j" t  p3 t2 V/ V' Y- n0 r
    }
  • BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
    声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    成为第一个吐槽的人