Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Yul 语言说明

一夜雨十年灯潞
365 0 0
Yul (先前被也被称为 JULIA 或 IULIA)是一种可以编译到各种不同后端的中间语言( |evm| 1.0,|evm| 1.5,而 eWASM 也在计划中)。
! F* b' I) _8 O; o3 H正因为如此,它被设计成为这三种平台的可用的共同标准。* \! t- B- b1 d' f1 G" t& C
它已经可以用于 Solidity 内部的“内联汇编”,并且未来版本的 Solidity 编译器甚至会将 Yul 用作中间语言。 为 Yul 构建高级的优化器阶段也将会很容易。: ^, E7 u- U$ I1 r$ U. q
… note::: p" o7 P5 N" x# v
请注意,用于“内联汇编”的书写风格是不带类型的(所有的都是 ``u256``),内置函数与 |evm| 操作码相同。4 c5 m. `; w6 ]. C  P
有关详细信息,请参阅内联汇编文档。8 S- ~( a# s/ F! T, `" k
Yul 的核心组件是函数,代码块,变量,字面量,for 循环,if 条件语句,switch 条件语句,表达式和变量赋值。: n. \3 I* t% z4 `
Yul 是强类型的,变量和字面量都需要通过前缀符号来指明类型。支持的类型有:bool, u8, s8, u32, s32,
; Y. r0 T4 Z* gu64, s64, u128, s128, u256 和 s256。; y$ e" F8 `4 q6 t9 H2 O( w
Yul 本身甚至不提供操作符。如果目标平台是 |evm|,则操作码将作为内置函数提供,但如果后端平台发生了变化,则可以重新实现它们。
9 O, l2 U& C" Q  n有关强制性的内置函数的列表,请参阅下面的章节。
6 e, O: E7 |; c3 {  y. a' K$ k& |' J以下示例程序假定 |evm| 操作码 mul,div 和 mo 是原生支持或可以作为函数用以计算指数的。
" Y9 f$ I( ?8 O6 i… code::! m, i: G% ~6 T
{# e3 @; c7 W8 b9 T5 M8 }6 ~  H+ v
    function power(base:u256, exponent:u256) -> result:u256
7 ^4 O! r, h+ d. `! V2 b    {0 K% U5 ?# Y: `# J2 Y% S" z
        switch exponent
9 s3 c/ Q7 e' d$ H4 I7 q* c        case 0:u256 { result := 1:u256 }5 t" o, T6 Q; c  A1 J
        case 1:u256 { result := base }, r) P, z/ _0 W6 p: F1 i4 k. _
        default:
$ y0 C* R( D9 t5 y* v2 y        {+ `1 _! s% Y9 i! E
            result := power(mul(base, base), div(exponent, 2:u256))8 B# p. J( _4 V+ i4 d
            switch mod(exponent, 2:u256)" V( ]4 r8 X" ]  m
                case 1:u256 { result := mul(base, result) }2 O7 Y( ~5 f$ M; _( h4 Z+ p* g( [
        }" Z) {6 U7 g) M) e9 D
    }
2 f( V2 R) c2 j2 V}
& b1 ^9 R1 D1 n- A. [' y也可用 for 循环代替递归来实现相同的功能。这里,我们需要 |evm| 操作码 lt (小于)和 add 可用。
* r% q- M. k* _7 p" K… code::
3 h/ W6 G5 V2 j/ t; X/ {+ x% u{+ d) u7 W' C! n0 y
    function power(base:u256, exponent:u256) -> result:u256
' b% B7 }( j+ `3 k    {
' L' m; w- I: G+ M* I        result := 1:u256+ l0 e5 k; n) L7 X% O# D
        for { let i := 0:u256 } lt(i, exponent) { i := add(i, 1:u256) }) s8 a5 J( a/ t6 _' Y* U% J5 }
        {
" f, E2 a, V- P            result := mul(result, base)
3 U6 {2 @$ g3 w* u) d; d: T        }
, U! ?7 r- v2 x1 Z2 }: M    }
5 C- j+ h! M" `$ b8 i}# x: t# Z! D' E5 d: G
Yul 语言说明
$ M; j8 k; M; ]4 J7 E本章介绍 Yul 代码。Yul 代码通常放置在一个 Yul 对象中,它将在下一节中介绍。# O3 E- f" E/ t2 g
语法::8 e# g5 E0 F. X( V( D  ]
代码块 = '{' 语句* '}'
/ p" Y' X4 D0 s5 v, h- T; T9 L语句 =
. ~& x% ?5 o' M6 c2 D; C1 ~: G4 a    代码块 |7 }8 ^: C" H  G6 K0 o" B
    函数定义 |# z. T) ^8 E* d
    变量声明 |# h* @1 l& i/ L$ W; E6 E4 Q6 x
    赋值 |
! v* g/ d9 J( u: n# W9 \  f    表达式 |7 l) a) D; n, n- X; z) U
    Switch |8 w) }" K9 j( g- P7 `4 H- T1 h
    For 循环 |
, n* H5 T- O( c. o9 \    循环中断3 V$ ]# [- L' h4 u7 ^
函数定义 =
9 m8 ~1 s# f. |$ Z! I! ?# v2 c    'function' 标识符 '(' 带类型的标识符列表? ')'
$ r% _3 m* b5 e( V    ( '->' 带类型的标识符列表 )? 代码块
; C& n; S  a* }/ n变量声明 =) V5 v9 H% B  b+ q  }; g
    'let' 带类型的标识符列表 ( ':=' 表达式 )?
4 H6 ^2 Y! l* u3 q6 {* ^1 z" K/ a赋值 =
, t  f" G; d5 f; ?    标识符列表 ':=' 表达式
$ g/ W, V# U3 n! A6 R表达式 =" I" b) Y+ W0 S4 S: l$ o" q
    函数调用 | 标识符 | 字面量6 W* z; |, X/ R8 m
If 条件语句 =
3 A. ?8 s. y, D' D& Q  m% \    'if' 表达式 代码块
/ [, A3 U2 u6 Y$ ^$ _. xSwitch 条件语句 =
! c3 m2 O% O' B6 A  G8 P' p, L4 w    'switch' 表达式 Case* ( 'default' 代码块 )?
- `; u& D* f3 C/ U/ y5 [$ r) f' rCase =
+ U. K  A0 K5 j) r, Y5 X9 U    'case' 字面量 代码块
; @7 T# d, ~7 @: hFor 循环 =
6 K- ^4 a- p0 Q7 E0 P    'for' 代码块 表达式 代码块 代码块7 [, i) E( U9 `$ k
循环中断 =
$ r3 c6 P2 q8 F+ k    'break' | 'continue'1 T! S& M8 _$ e/ F* [% d
函数调用 =6 }4 T0 {1 T4 u
    标识符 '(' ( 表达式 ( ',' 表达式 )* )? ')'
; G6 s2 ^. g3 }+ J  P: `* f# p标识符 = [a-zA-Z_$] [a-zA-Z_0-9]*
/ s1 `! C  A3 Y/ [8 p1 Y& L标识符列表 = 标识符 ( ',' 标识符)*
. Z4 S& L0 E# W3 Z8 s* d  _类型名 = 标识符 | 内置的类型名
  E4 N* ^4 G2 x内置的类型名 = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )0 v8 C# X9 s6 ]# F
带类型的标识符列表 = 标识符 ':' 类型名 ( ',' 标识符 ':' 类型名 )*
# ^- r; R' E) E8 M0 D字面量 =
/ K- m% l6 C4 B3 H- W' Y    (数字字面量 | 字符串字面量 | 十六进制字面量 | True字面量 | False字面量) ':' 类型名1 y9 s4 g8 w7 `, {$ m: }
数字字面量 = 十六进制数字 | 十进制数字
7 Z) L$ n% ^  t6 S+ h$ E% d十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\''), J+ H! D3 K% l3 n
字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"'; Q- h$ Q5 L9 R) |, H4 [
True字面量 = 'true'1 Q7 a% j" h# S: Z5 Y2 i7 ~% @& y
False字面量 = 'false'
' ?" d0 I" N: A' W  c十六进制数字 = '0x' [0-9a-fA-F]+
) F( O8 v2 v; _1 b十进制数字 = [0-9]+
# h0 }7 N5 F- z0 Y) ?语法层面的限制
% x9 n/ v* @- hSwitches 必须至少有一个 case(包括 default )。
! d  @: V3 a; g4 @( N如果表达式的所有可能值都被覆盖了,那么不应该允许使用 default$ G1 [0 k* c) g4 ^! o. i' c
(即带 bool 表达式的 switch 语句同时具有 true case 和 false case 的情况下不应再有 default 语句)。
' A+ i7 C% ~  ?2 R8 ~每个表达式都求值为零个或多个值。 标识符和字面量求值为一个值,函数调用求值为所调用函数的返回值。
9 v5 O/ n# a- \+ y# F  Z在变量声明和赋值中,右侧表达式(如果存在)求值后,必须得出与左侧变量数量相等的值。2 v! W" O" l! e' P7 N0 W0 o
这是唯一允许求值出多个值的表达式。; o" S( M% X5 w" b$ O
那种同时又是语句的表达式(即在代码块的层次)求值结果必须只有零个值。
7 Q$ O% @, G" G* V在其他所有情况中,表达式求值后必须仅有一个值。
1 }0 j  t" n; e, M: D- Z' ycontinue 和 break 语句只能用在循环体中,并且必须与循环处于同一个函数中(或者两者都必须在顶层)。# B6 V( @. }* c* \2 v
for 循环的条件部分的求值结果只能为一个值。
0 U- X' Z1 @3 T字面量不可以大于它们本身的类型。已定义的最大类型宽度为 256 比特。
' m1 Y5 c9 R6 j作用域规则
/ S  U2 z% U- P5 v# yYul 中的作用域是与块(除了函数和 for 循环,如下所述)和所有引入新的标识符到作用域中的声明9 F, h! v3 b& z' V4 ^8 p
( FunctionDefinition ,VariableDeclaration )紧密绑定的。; S1 j# F5 P( f5 F
标识符在将其定义的块中可见(包括所有子节点和子块)。+ C' M1 i1 b; Z+ n- H/ S) D
作为例外,for 循环的 “init” 部分中(第一个块)定义的标识符在 for 循环的所有其他部分(但不在循环之外)中都是可见的。
- C) d1 d* W9 E( c7 ^) U+ o- }* q在 for 循环的其他部分声明的标识符遵守常规的作用域语法规则。2 u4 ?; }$ x; U% O
函数的参数和返回参数在函数体中可见,并且它们的名称不能相同。
) c/ B. a! |/ h5 W# Y3 T3 Z) D变量只能在声明后引用。 尤其是,变量不能在它们自己的变量声明的右边被引用。
: g4 }, [7 i0 k2 q  n函数可以在声明之前被引用(如果它们是可见的)。
# P" U+ q# x1 E8 E- ^2 m- I/ TShadowing 是不被允许的,即是说,你不能在同名标识符已经可见的情况下又定义该标识符,即使它是不可访问的。" H+ ]* V; r, s
在函数内,不可能访问声明在函数外的变量。* _9 T2 S: T% r' h9 L1 b5 s
形式规范
  `' Q5 x3 `$ o我们通过在 AST 的各个节点上提供重载的求值函数 E 来正式指定 Yul。
6 G8 m. d( `5 l任何函数都可能有副作用,所以 E 接受两个状态对象和 AST 节点作为它的参数,并返回两个新的状态对象和数量可变的其他值。. u5 W) _3 i3 Q
这两个状态对象是全局状态对象(在 |evm| 的上下文中是 |memory|,|storage| 和区块链的状态)和本地状态对象(局部变量的状态,即 |evm| 中堆栈的某个段)。% S' C/ z! f+ Z* ~, _. S. {1 F
如果 AST 节点是一个语句,E 将返回两个状态对象和一个用于 break 和 continue 语句的 “mode”。/ i0 d% j, t9 `
如果 AST 节点是表达式,则 E 返回两个状态对象,并返回与表达式求值结果相同数量的值。
: y; t, U/ ~  ?& ~# K在这份高层次的描述中,并没有对全局状态的确切本质进行说明。
+ B" q+ h; L% o本地状态 L 是标识符 i 到值 v 的映射,表示为 L = v。
" L- L0 i4 p6 G9 o% b; B8 Z9 L对于标识符 v, 我们用 $v 作为标识符的名字。& x/ t0 Z$ a: A0 Q, h/ Q
我们将为 AST 节点使用解构符号。
( A/ m! f/ L9 r* J# `… code::% j" r2 t3 a6 h2 F% i! R* b# u
E(G, L, : Block) =
: |3 G' ], q+ f  T& R+ w    let G1, L1, mode = E(G, L, St1, ..., Stn)
9 |8 O3 L. }$ r& ^3 {- y3 R8 L, n    let L2 be a restriction of L1 to the identifiers of L# W* z% n" {% ?1 J+ {3 v
    G1, L2, mode* A( h  g+ Y, H. X! h$ O
E(G, L, St1, ..., Stn: Statement) =- G/ N8 M9 F6 c( {' v0 T- g
    if n is zero:* ]  }7 F8 S, t0 k  z; u9 d
        G, L, regular" M3 I, s* B7 o5 ?+ d; Q
    else:% C' F( V4 t& R* c2 T
        let G1, L1, mode = E(G, L, St1): l5 C$ E% Q/ g* T7 L; b
        if mode is regular then
; A* v: l- s$ F            E(G1, L1, St2, ..., Stn)
" |% \+ x0 Q! Y& t- i$ R( f& x        otherwise
7 m9 t2 p* c/ P/ i; A2 E2 |            G1, L1, mode; @9 ]) `3 Z) o4 y
E(G, L, FunctionDefinition) =
5 N4 ?& X5 L1 q    G, L, regular' d$ }7 R; R) l! e* U2 o* p
E(G, L, : VariableDeclaration) =
! q9 P; N% Y: ~8 \' ?/ a( _& y! y    E(G, L, : Assignment)
# ^- S+ n2 @! z+ nE(G, L, : VariableDeclaration) =
# C+ k# A7 K) R4 N; _    let L1 be a copy of L where L1[$vari] = 0 for i = 1, ..., n
& I" |! Q6 ^! R! i    G, L1, regular
" z# h1 y/ \% y- W' I7 Y3 fE(G, L, : Assignment) =
, d/ g* p1 p6 [4 u+ _. Z    let G1, L1, v1, ..., vn = E(G, L, rhs)
* }: [1 U; m1 t- g0 I$ F0 A    let L2 be a copy of L1 where L2[$vari] = vi for i = 1, ..., n) f) q0 j9 m3 j9 {3 V7 D
    G, L2, regular: m; n% U& s5 y" \
E(G, L, : ForLoop) =
, b$ e3 [' @$ G9 ~    if n >= 1:7 E$ y- h( O7 V
        let G1, L1, mode = E(G, L, i1, ..., in)" y# T- Y2 h! \2 S7 }
        // 由于语法限制,mode 必须是规则的7 X- `6 f) k" f
        let G2, L2, mode = E(G1, L1, for {} condition post body)
/ t6 z, z  w3 ^        // 由于语法限制,mode 必须是规则的
% G% l2 ?0 n$ @/ P2 ~        let L3 be the restriction of L2 to only variables of L
  A: w' S4 m' E        G2, L3, regular
0 U4 ^- u( v- s    else:
3 \- p' D5 N1 W! U! {% ?        let G1, L1, v = E(G, L, condition)
$ E9 `" l/ t- g/ i5 J4 T% P        if v is false:5 N! h# Z/ z5 x5 u
            G1, L1, regular! \2 |" ]2 I" u
        else:3 O9 r" n+ w/ S! M
            let G2, L2, mode = E(G1, L, body)# C( N, O$ p' e
            if mode is break:
! X0 z: [( _* O! @( T                G2, L2, regular
3 y1 h( `) a" T8 W% b            else:4 _2 p# H( K  U! y1 @1 _: i
                G3, L3, mode = E(G2, L2, post)
, q& {* S$ d$ }  C                E(G3, L3, for {} condition post body)
7 _  y  A1 t9 m$ c! ~E(G, L, break: BreakContinue) =3 O  I& V% ]5 V& o( ]! T
    G, L, break& F) j7 [/ Z2 M8 R+ m
E(G, L, continue: BreakContinue) =
* G+ C( r: Z$ K  V; x    G, L, continue
( U/ D& |8 n) [: U/ G9 N- I4 SE(G, L, : If) =7 D, R; Z5 B6 R! n6 r' f( h: G
    let G0, L0, v = E(G, L, condition)2 `) b  n8 L4 k& |! K8 c7 x( p
    if v is true:
% u, h/ ^% U/ G* e4 [+ I2 ~" h. k4 e6 j        E(G0, L0, body)
/ G! _7 M3 v, l, b6 l# X) Q$ t    else:, c4 i4 D9 ?8 K0 `
        G0, L0, regular; d* |: ?/ H# @1 t9 Q
E(G, L, : Switch) =, i  _: b& J2 v; u3 r
    E(G, L, switch condition case l1:t1 st1 ... case ln:tn stn default {})8 @2 P2 k/ k- b8 i5 m3 i$ T: [
E(G, L, : Switch) =! B# r' {) p7 F" ?
    let G0, L0, v = E(G, L, condition)
$ ^8 w2 t' N& u0 V    // i = 1 .. n( B! a% d8 F3 r6 N  W$ D5 k) i
    // 对字面量求值,上下文无关
$ m: T* y) t" T) f9 \    let _, _, v1 = E(G0, L0, l1)0 {! Y5 [' h1 J% b
    ...
, K2 k. B& s  F/ y    let _, _, vn = E(G0, L0, ln)  X) d) h8 x0 _3 i3 p. k* D
    if there exists smallest i such that vi = v:
: O! G* f* _7 _+ U9 b, c        E(G0, L0, sti)
/ e0 C% ], h! m    else:( [7 _; F% m% d6 W4 w
        E(G0, L0, st')$ E, |8 Y5 Z( M! C( q: z: ?. l
E(G, L, : Identifier) =9 v; X8 @0 O& p% B' q# [
    G, L, L[$name]
5 f' A# E) q4 ?! m" XE(G, L, : FunctionCall) =% h% \( h( v$ @% K% K
    G1, L1, vn = E(G, L, argn)7 q8 Z4 o0 H: d6 X1 T( X/ X4 N, k
    ...! d2 }# y, v7 ?' Q# }
    G(n-1), L(n-1), v2 = E(G(n-2), L(n-2), arg2)
7 \" ^9 q2 w8 ^2 M- K4 b0 ~    Gn, Ln, v1 = E(G(n-1), L(n-1), arg1)
1 j7 h- v' j1 z! G, n* C7 Y! \1 [    Let  ret1, ..., retm block>  ]8 _9 O# @9 g; D
    be the function of name $fname visible at the point of the call.' B4 Y7 C" ?/ W% V
    Let L' be a new local state such that
2 e4 w. [- j7 Q    L'[$parami] = vi and L'[$reti] = 0 for all i.2 f& V9 I% W- C. _$ r$ W
    Let G'', L'', mode = E(Gn, L', block)
  y& S; w' t6 P; F- x- i1 X    G'', Ln, L''[$ret1], ..., L''[$retm]+ e# w! Y4 [% i! d/ [: H; e% t  G
E(G, L, l: HexLiteral) = G, L, hexString(l),& J8 V( W: x( [! z6 G1 |
    where hexString decodes l from hex and left-aligns it into 32 bytes. b2 G( {' g' p# `
E(G, L, l: StringLiteral) = G, L, utf8EncodeLeftAligned(l),- f! G% u" R! p& V( f. U" {
    where utf8EncodeLeftAligned performs a utf8 encoding of l9 }5 E2 m' |8 [* n9 p0 `# E5 m. ?3 z
    and aligns it left into 32 bytes0 {+ H- d# u" i2 P
E(G, L, n: HexNumber) = G, L, hex(n)6 s  q. j5 Z8 D$ a
    where hex is the hexadecimal decoding function
8 O5 e6 M- R. u" m: P  |% U- ^" CE(G, L, n: DecimalNumber) = G, L, dec(n),4 x# L& o. `/ v, c! f; B$ P" k
    where dec is the decimal decoding function; g, y0 J9 J; ^: c
类型转换函数
& A1 n& j3 O5 X+ rYul 不支持隐式类型转换,因此存在提供显式转换的函数。
' e! w/ M* f" n' j( E5 I在将较大类型转换为较短类型时,如果发生溢出,则可能会发生运行时异常。
) v. K# ]1 @/ {0 Q. P下列类型的“截取式”转换是允许的:
- j: M$ [; Z2 b6 y: U
  • bool
  • u32
  • u64
  • u256
  • s2568 x4 @  H7 R2 W& x5 m) b7 x

    - n( Y1 d% u) v3 I8 E/ P1 G. Q+ J这里的每种类型的转换函数都有一个格式为 to(x:) -> y: 的原型,; Z% }8 }. W: l$ E2 L! a2 _
    比如 u32tobool(x:u32) -> y:bool、u256tou32(x:u256) -> y:u32 或 s256tou256(x:s256) -> y:u256。' f: Q1 N1 ^% `$ E1 r
    … note::7 U1 p* D" V! I4 G$ @5 n
    ``u32tobool(x:u32) -> y:bool`` 可以由 ``y := not(iszerou256(x))`` 实现,并且! g  u9 l8 x+ D" m) J0 m: B. Q/ t
    ``booltou32(x:bool) -> y:u32`` 可以由 ``switch x case true:bool { y := 1:u32 } case false:bool { y := 0:u32 }`` 实现8 Q9 c) s0 l) {% Q# Q
    低级函数; g4 D  M! J! k; H: g" C
    以下函数必须可用:
    ; |' P: {8 [0 J6 x0 l, @±--------------------------------------------------------------------------------------------------------------+
    $ W4 @7 h" m3 O  ]| 逻辑操作                                                                                                    |
    ! m8 y; @% J* I0 P  e, u±--------------------------------------------±----------------------------------------------------------------+4 N6 t9 t5 B( E
    | not(x:bool) -> z:bool                       | 逻辑非                                                          |
    2 E! j& j" S0 g& T2 @& S. h$ V±--------------------------------------------±----------------------------------------------------------------+& h  k, K' d4 @' s& W4 y
    | and(x:bool, y:bool) -> z:bool               | 逻辑与                                                          |( \# E0 w# n& N$ L( [4 W3 u
    ±--------------------------------------------±----------------------------------------------------------------++ b3 C/ I# i5 h0 A4 E+ B
    | or(x:bool, y:bool) -> z:bool                | 逻辑或                                                          |* f. I+ A5 Q( H, N1 z  o3 I
    ±--------------------------------------------±----------------------------------------------------------------+
    6 X% A1 l9 z$ X' I& s| xor(x:bool, y:bool) -> z:bool               | 异或                                                            |
    2 l7 g: d; J2 K3 G: a# A±--------------------------------------------±----------------------------------------------------------------+- o" w" R1 [" b0 o7 @
    | 算术操作                                                                                                    |7 T8 u0 m: P; @
    ±--------------------------------------------±----------------------------------------------------------------+
    * f" z6 E% y  B| addu256(x:u256, y:u256) -> z:u256           | x + y                                                           |6 }& X$ M( n( S6 c6 J9 l
    ±--------------------------------------------±----------------------------------------------------------------+, ?- A2 U3 s5 K7 G% ^  {) s
    | subu256(x:u256, y:u256) -> z:u256           | x - y                                                           |/ E& ~  w7 g, G6 q
    ±--------------------------------------------±----------------------------------------------------------------+
    : x2 u0 U4 y: o" p| mulu256(x:u256, y:u256) -> z:u256           | x * y                                                           |% W( Z  l- ]& c0 M
    ±--------------------------------------------±----------------------------------------------------------------+
    ' T, B: q: c! L' j5 @$ B5 `| divu256(x:u256, y:u256) -> z:u256           | x / y                                                           |
    , O/ ?( C; @2 _8 i( x±--------------------------------------------±----------------------------------------------------------------+
    4 k& F! A: T0 d- J! r| divs256(x:s256, y:s256) -> z:s256           | x / y, 有符号数用补码形式                                       |
    & y7 E7 L5 ]  Z& H±--------------------------------------------±----------------------------------------------------------------+
    2 C5 r7 V  K% p! V' B| modu256(x:u256, y:u256) -> z:u256           | x % y                                                           |' g4 Q: s4 K* q$ h. ?
    ±--------------------------------------------±----------------------------------------------------------------+
    6 A& F1 t% \0 F$ [| mods256(x:s256, y:s256) -> z:s256           | x % y, 有符号数用补码形式                                       |
    ! B+ q. ]# T! S" N# A7 N±--------------------------------------------±----------------------------------------------------------------+3 n6 [- K6 _. I) a9 {
    | signextendu256(i:u256, x:u256) -> z:u256    | 从第 (i*8+7) 位开始进行符号扩展,从最低符号位开始计算           |
    ( ^$ D. b& N' Z# ]6 @. z±--------------------------------------------±----------------------------------------------------------------+0 ~' E8 e1 }9 p1 t7 c
    | expu256(x:u256, y:u256) -> z:u256           | x 的 y 次方                                                     |
    ' p9 H2 u. F* x0 _& W  v/ Z9 e±--------------------------------------------±----------------------------------------------------------------+
    ! p  O! n7 L/ a5 a1 e$ I| addmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x + y) % m                                |( B! r8 N" E9 U
    ±--------------------------------------------±----------------------------------------------------------------+
    - ^5 d$ ]% F' ~5 I4 V4 K| mulmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x * y) % m                                |4 N& H. A* N; v% J! T* H
    ±--------------------------------------------±----------------------------------------------------------------+
    & w- F5 j0 J3 Q2 Y+ C: i2 K| ltu256(x:u256, y:u256) -> z:bool            | 若 x  z:bool            | 若 x > y 为 true, 否则为 false                                  |
    ( {* ~2 f: o' h, z6 _8 f9 f±--------------------------------------------±----------------------------------------------------------------+
    6 O9 ~, m- ?* n+ y| sltu256(x:s256, y:s256) -> z:bool           | 若 x  z:bool           | 若 x > y 为 true, 否则为 false                                  |( P/ |. u/ ?6 M; g/ P- g
    |                                             | 有符号数用补码形式                                              |* V# ^# Z5 Q% C) K+ g  J/ K1 z0 `
    ±--------------------------------------------±----------------------------------------------------------------+: A! Y' y- S  @  p2 E
    | equ256(x:u256, y:u256) -> z:bool            | 若 x == y 为 true, 否则为 false                                 |  a7 D  |0 D0 r" [4 B
    ±--------------------------------------------±----------------------------------------------------------------+
    ' u) R0 ~. ~  r+ N" F# `9 x: W& m| iszerou256(x:u256) -> z:bool                | 若 x == 0 为 true, 否则为 false                                 |* J- d- e; l" e
    ±--------------------------------------------±----------------------------------------------------------------+
    7 T) b9 w5 X' a| notu256(x:u256) -> z:u256                   | ~x, 对 x 按位非                                                 |
    + o7 F1 K% j) O8 I  s. w±--------------------------------------------±----------------------------------------------------------------+7 [: n$ t+ i0 H7 B2 V8 S2 e
    | andu256(x:u256, y:u256) -> z:u256           | x 和 y 按位与                                                   |* y0 @2 g: U4 ?( a: P
    ±--------------------------------------------±----------------------------------------------------------------+, b  x0 q. Q( ~+ y# j0 o
    | oru256(x:u256, y:u256) -> z:u256            | x 和 y 按位或                                                   |6 H& O: {2 q5 L) \( q; x7 F# U
    ±--------------------------------------------±----------------------------------------------------------------+
    % e6 Q5 W% y: a3 W- m& q% j9 H3 s| xoru256(x:u256, y:u256) -> z:u256           | x 和 y 按位异或                                                 |
    3 w# {5 x$ q8 U±--------------------------------------------±----------------------------------------------------------------+
    2 B9 e/ y) {& n. L( L1 n| shlu256(x:u256, y:u256) -> z:u256           | 将 x 逻辑左移 y 位                                              |. ^2 E; f8 s; x4 X2 k( F
    ±--------------------------------------------±----------------------------------------------------------------+/ @3 j* C! d6 M& N$ b* D
    | shru256(x:u256, y:u256) -> z:u256           | 将 x 逻辑右移 y 位                                              |
    ) R: m7 i7 U4 E4 s±--------------------------------------------±----------------------------------------------------------------+
    8 J  q$ {, m, C* O  \| saru256(x:u256, y:u256) -> z:u256           | 将 x 算术右移 y 位                                              |
    + p9 s& x  V2 d" ~1 H( j0 Q0 c4 u±--------------------------------------------±----------------------------------------------------------------+8 K: ~9 `! k6 E+ W. O$ M5 Y
    | byte(n:u256, x:u256) -> v:u256              | x 的第 n 字节,这里的索引位置是从 0 开始的;                    |- o+ C" h5 E$ T) @" q0 ^
    |                                             | 能否用 and256(shr256(n, x), 0xff) 来替换它,                    |
    4 @- X( Q. x; Y|                                             | 并使它在 EVM 后端之外被优化呢?                                 |
    % F1 F  E7 T/ U' y- N3 t0 P! K2 O±--------------------------------------------±----------------------------------------------------------------+5 S! ^7 R7 z; [1 v9 A. F5 J1 }, k
    | 内存和存储                                                                                                  |
    3 t6 N/ }9 j, S4 T" d±--------------------------------------------±----------------------------------------------------------------+
    8 ]2 X. [0 z5 m| mload(p:u256) -> v:u256                     | mem[p…(p+32))                                                  |* e, G  }# b0 r1 L2 d. a
    ±--------------------------------------------±----------------------------------------------------------------+8 }, U5 e7 y$ d  T0 i+ m
    | mstore(p:u256, v:u256)                      | mem[p…(p+32)) := v                                             |
    # Y4 ]2 y9 `! S) n+ F- A±--------------------------------------------±----------------------------------------------------------------+, m* X  _- m5 k# O* I
    | mstore8(p:u256, v:u256)                     | mem := v & 0xff    - 仅修改单个字节                          |
    , U$ F9 N  `: m! }2 V4 P±--------------------------------------------±----------------------------------------------------------------+
    ' W, [9 d" r  L" d) B4 |# a" N# }9 T2 T| sload(p:u256) -> v:u256                     | storage                                                      |* C4 B. V3 v) D4 W: T( u4 y0 B6 S
    ±--------------------------------------------±----------------------------------------------------------------++ l1 ]& e' U0 v( V
    | sstore(p:u256, v:u256)                      | storage := v                                                 |9 B) \. \* }  W+ s" e' L4 c
    ±--------------------------------------------±----------------------------------------------------------------+, C# b1 z2 l2 I( a, ~3 f: v" o
    | msize() -> size:u256                        | 内存的大小, 即已访问过的内存的最大下标,                        |! `8 `! Z: K% D6 h! t
    |                                             | 因为内存扩展的限制(只能按字进行扩展)                          |
    6 Z# }" v8 o# I+ M4 k& }|                                             | 返回值永远都是 32 字节的倍数                                    |2 w* |$ P3 K/ |* A
    ±--------------------------------------------±----------------------------------------------------------------+3 j( w1 P1 X( X8 Q5 a, O0 v
    | 执行控制                                                                                                    |
    ( b9 s9 U6 l4 g# ^' x±--------------------------------------------±----------------------------------------------------------------+
    " X( Z$ {) q6 V) P| create(v:u256, p:u256, s:u256)              | 以 mem[p…(p+s)) 上的代码创建一个新合约,发送                   |5 _# p: a/ R4 _/ w! e5 S) Y: s3 C
    |                                             | v 个 wei,并返回一个新的地址                                    |. ]  E) A- K. P! }2 Y( D% i2 Q
    ±--------------------------------------------±----------------------------------------------------------------+/ Y) t4 x" a8 ^
    | call(g:u256, a:u256, v:u256, in:u256,       | 调用地址 a 上的合约,以 mem[in…(in+insize)) 作为输入           |6 Z. ]3 p3 m$ R9 W4 |) x
    | insize:u256, out:u256,                      | 一并发送 g gas 和 v wei ,以 mem[out…(out+outsize))            |
    6 p0 z2 l+ C% j| outsize:u256)                               | 作为输出空间。若错误,返回 0 (比如,gas 用光                   |7 Q$ r$ D! k8 S' P2 c8 B
    | -> r:u256                                   | 成功,返回 1                                                    |" {6 S/ J4 o1 T7 N2 q4 |
    ±--------------------------------------------±----------------------------------------------------------------+
    4 {* I; l4 k! K' t. M% K| callcode(g:u256, a:u256, v:u256, in:u256,   | 相当于 call 但仅仅使用地址 a 上的代码,                     |
    ) V+ N# K; f- _' s| insize:u256, out:u256,                      | 而留在当前合约的上下文当中                                      |) d  |) z' k+ J# b- H. Y. }6 r3 b
    | outsize:u256) -> r:u256                     |                                                                 |: z% n3 x- v- r! p: Q# ^" u
    ±--------------------------------------------±----------------------------------------------------------------+* a) i2 c) s9 y6 H
    | delegatecall(g:u256, a:u256, in:u256,       | 相当于 callcode,                                           |
    9 A3 Q4 ]4 D. X8 d| insize:u256, out:u256,                      | 但同时保留 caller                                           |
    4 Q0 h/ c; b: G' f9 N" d| outsize:u256) -> r:u256                     | 和 callvalue                                                |: _9 ?5 O1 N9 D( }9 r: Q
    ±--------------------------------------------±----------------------------------------------------------------+# O0 e/ h4 p1 W1 R1 r7 s9 {
    | abort()                                     | 终止 (相当于EVM上的非法指令)                                    |
    $ W4 b1 J# T5 T. u±--------------------------------------------±----------------------------------------------------------------+
    6 c& t- u) i; N0 v| return(p:u256, s:u256)                      | 终止执行,返回 mem[p…(p+s)) 上的数据                           |
    - o6 I5 t5 a3 z, o# }±--------------------------------------------±----------------------------------------------------------------+
    9 v5 x+ e' F: E1 V| revert(p:u256, s:u256)                      | 终止执行,恢复状态变更,返回 mem[p…(p+s)) 上的数据             |3 `( x4 u0 U$ t7 X
    ±--------------------------------------------±----------------------------------------------------------------+
    ; i  ~( T$ g4 y# E$ C| selfdestruct(a:u256)                        | 终止执行,销毁当前合约,并且将余额发送到地址 a                  |. h$ L! R: g, I: P
    ±--------------------------------------------±----------------------------------------------------------------+
    ) S3 i; c: V' I- s| log0(p:u256, s:u256)                        | 用 mem[p…(p+s)] 上的数据产生日志,但没有 topic                 |
    , E, K! G5 _$ |4 O- e8 ]! V7 ^±--------------------------------------------±----------------------------------------------------------------+
    6 V/ s2 v9 j2 S) W# o8 X; d7 G| log1(p:u256, s:u256, t1:u256)               | 用 mem[p…(p+s)] 上的数据和 topic t1 产生日志                   |4 b7 T: K$ ~# p0 K2 R; d/ _6 T
    ±--------------------------------------------±----------------------------------------------------------------+" w( J7 @% E' G1 o9 u+ _+ t9 m+ K
    | log2(p:u256, s:u256, t1:u256, t2:u256)      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2 产生日志               |, x" V0 U% \4 p& v
    ±--------------------------------------------±----------------------------------------------------------------+. w  \: b2 }8 V. c7 m/ a6 C
    | log3(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3 产生日志           |
    + w0 H4 v/ b5 K& `| t3:u256)                                    |                                                                 |
    8 \! X0 |1 d' I" R1 h  M±--------------------------------------------±----------------------------------------------------------------+
    3 [2 R: V0 U: W: I. b9 N( z8 Y| log4(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3,t4                |
    / O4 p& A9 e9 I) {9 @) T| t3:u256, t4:u256)                           | 产生日志                                                        |! v& V, Z3 A) \  |
    ±--------------------------------------------±----------------------------------------------------------------+( r+ i) h9 F5 m& J( @
    | 状态查询                                                                                                    |
    - b  ^- K+ b2 k& {2 l±--------------------------------------------±----------------------------------------------------------------+# ^  t: y6 H2 p5 s& w  y+ T
    | blockcoinbase() -> address:u256             | 当前的矿工                                                      |2 R' @( Q' ^+ v) r0 @
    ±--------------------------------------------±----------------------------------------------------------------+
    & ]9 v) G! X0 \% U; @$ _: Z| blockdifficulty() -> difficulty:u256        | 当前区块的难度                                                  |+ @' c0 n* G$ A: ~$ Z1 w! m% a
    ±--------------------------------------------±----------------------------------------------------------------+
    . S# m4 e3 F& Y| blockgaslimit() -> limit:u256               | 当前区块的区块 gas 限制                                         |. U/ Y% {$ D- B$ V9 k9 t' r
    ±--------------------------------------------±----------------------------------------------------------------+
    , [- ^; E# C5 s- M| blockhash(b:u256) -> hash:u256              | 区块号为 b 的区块的哈希,                                       |7 J  p! g: U% H& g7 V
    |                                             | 仅可用于最近的 256 个区块,不包含当前区块                       |
    2 T3 [$ I' x5 D' Y5 f±--------------------------------------------±----------------------------------------------------------------+1 t# \& q. W% k' g- u# e: ~+ S
    | blocknumber() -> block:u256                 | 当前区块号                                                      |6 i9 c$ ?9 a( u4 j8 k) Z  M9 d
    ±--------------------------------------------±----------------------------------------------------------------+, C' A2 _  q- z# ~
    | blocktimestamp() -> timestamp:u256          | 自 epoch 开始的,当前块的时间戳,以秒为单位                     |
    + j1 G; Y1 }* \9 H±--------------------------------------------±----------------------------------------------------------------+
    8 r( k! L/ d% G1 j! `| txorigin() -> address:u256                  | 交易的发送方                                                    |: w+ W4 }5 w9 o2 t
    ±--------------------------------------------±----------------------------------------------------------------+
      E9 |5 c5 V4 a0 \+ t$ r| txgasprice() -> price:u256                  | 交易中的 gas 价格                                               |+ t4 `$ H1 v9 p2 B: v5 D! d
    ±--------------------------------------------±----------------------------------------------------------------+
    . X4 N. E. c7 S8 X  D- ]| gasleft() -> gas:u256                       | 还可用于执行的 gas                                              |/ K$ s% K7 L& T' x
    ±--------------------------------------------±----------------------------------------------------------------+5 n3 U+ z5 d4 q  `
    | balance(a:u256) -> v:u256                   | 地址 a 上的 wei 余额                                            |) W& ^$ {! A/ D9 Q
    ±--------------------------------------------±----------------------------------------------------------------+  E' W# I; O' z% |7 A
    | this() -> address:u256                      | 当前合约/执行上下文的地址                                      |
    - p$ G/ y. l6 q4 ?3 `. B. b* b±--------------------------------------------±----------------------------------------------------------------+8 |0 N9 q+ b! s6 o7 B1 m; y
    | caller() -> address:u256                    | 调用的发送方 (不包含委托调用)                                   |
    & J. u2 P4 r" V  v0 l) _2 f5 c±--------------------------------------------±----------------------------------------------------------------+
    . C; J& _' B0 }7 v' G+ v| callvalue() -> v:u256                       | 与当前调用一起发送的 wei                                        |
    8 M# b# m; C! R! L  K/ g2 b& q±--------------------------------------------±----------------------------------------------------------------+
    9 X' b! ]/ X1 o3 E8 Q. M| calldataload(p:u256) -> v:u256              | 从 position p 开始的 calldata (32 字节)                         |
    9 g% l& m+ V3 W. N±--------------------------------------------±----------------------------------------------------------------+
    0 _# f0 E3 a- T' S| calldatasize() -> v:u256                    | 以字节为单位的 calldata 的大小                                  |
    % X1 C; k7 `9 H/ A0 B# X: ^1 x±--------------------------------------------±----------------------------------------------------------------+) H. `- f" a$ L0 g; S+ T& u
    | calldatacopy(t:u256, f:u256, s:u256)        | 从位置为 f 的 calldata 中,拷贝 s 字节到内存位置 t              |
      a: \. t: B  D±--------------------------------------------±----------------------------------------------------------------+: E0 t5 V3 r) _1 z! ?
    | codesize() -> size:u256                     | 当前合约/执行上下文的代码大小                                  |
      N0 g1 ~& \0 V' w% O$ O5 d±--------------------------------------------±----------------------------------------------------------------+( B" {1 L; j. A4 ^$ }% y' _
    | codecopy(t:u256, f:u256, s:u256)            | 从 code 位置 f 拷贝 s 字节到内存位置 t                          |4 ~- z& i: J, L1 I; h
    ±--------------------------------------------±----------------------------------------------------------------+  I! j- M$ @9 G7 Y# _
    | extcodesize(a:u256) -> size:u256            | 地址 a 上的代码大小                                             |! z: [, B3 F4 \" t" m% o
    ±--------------------------------------------±----------------------------------------------------------------+
    % S- \7 l( P  o, w| extcodecopy(a:u256, t:u256, f:u256, s:u256) | 相当于 codecopy(t, f, s),但从地址 a 获取代码                   |
    % }, M4 z9 P9 G# |±--------------------------------------------±----------------------------------------------------------------+
    - g1 ]+ z! y3 w3 Y! i% U6 j| 其他                                                                                                        |3 q; ]1 R0 o2 S9 M' H# N
    ±--------------------------------------------±----------------------------------------------------------------+
    - Z5 h1 @5 h& [( C| discard(unused:bool)                        | 丢弃值                                                          |
    2 f/ b* ]9 E% y; S6 ^8 ]±--------------------------------------------±----------------------------------------------------------------+
    6 T7 k( t& l$ J5 `* k2 k- v: d0 }| discardu256(unused:u256)                    | 丢弃值                                                          |1 l) T4 X& `; U3 Y' W! B2 y' {  Y3 v
    ±--------------------------------------------±----------------------------------------------------------------+
    # z, m: s6 @! c( m- \9 O| splitu256tou64(x:u256) -> (x1:u64, x2:u64,  | 将一个 u256 拆分为四个 u64                                      |, o1 U! c3 A, U' G
    |                            x3:u64, x4:u64)  |                                                                 |% V9 z/ \0 i% o6 l& t
    ±--------------------------------------------±----------------------------------------------------------------+
    9 G1 w0 w' z, e! _9 P: p5 L. N+ A8 d| combineu64tou256(x1:u64, x2:u64, x3:u64,    | 将四个 u64 组合为一个 u256                                      |, x% g. M- V# u1 Q: y
    |                  x4:u64) -> (x:u256)        |                                                                 |
    7 ^9 C# B" ~' P2 U3 I! h/ i* [7 e±--------------------------------------------±----------------------------------------------------------------+
    ! l7 Y: E. C9 a# p; Y| keccak256(p:u256, s:u256) -> v:u256         | keccak(mem[p…(p+s)))                                          |
    " L; X) u/ m0 S4 d) `4 Y( p±--------------------------------------------±----------------------------------------------------------------+: [; k+ I- I3 ?$ l) t( e
    后端8 B( |; D4 j- G2 r
    后端或目标负责将 Yul 翻译到特定字节码。 每个后端都可以暴露以后端名称为前缀的函数。 我们为两个建议的后端保留 evm_ 和 ewasm_ 前缀。
    ) t+ P. v. \+ U0 S& P6 o7 o) n9 U后端: EVM7 n' \# p: S! `6 ^$ e# A
    目标 |evm| 将具有所有用 evm_ 前缀暴露的 |evm| 底层操作码。
    : N1 A7 _5 a4 y' {2 k' ~- i, ]$ [后端: “EVM 1.5”
    5 `; J' M9 k, H: NTBD; L1 t6 p" ~: _: |( n$ ^
    后端: eWASM
    . u/ m4 y6 c7 Y% ?TBD' }* T+ s* c; B8 G* i- ^
    Yul 对象说明8 ?. X& W: B! w. l- z# O1 Y% p
    语法::
    * `/ @% N5 B3 o顶层对象 = 'object' '{' 代码? ( 对象 | 数据 )* '}'$ w7 I. r& ]) R& Q
    对象 = 'object' 字符串字面量 '{' 代码? ( 对象 | 数据 )* '}'
    $ u. \6 a; `( a9 k代码 = 'code' 代码块
    5 A, F6 b+ M0 Z数据 = 'data' 字符串字面量 十六进制字面量
    - E# I' x' z! I. {+ T十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
    ) L# L$ n( g: m5 h+ a- o字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"'
    ( Q) r" z, O& B+ Q在上面,代码块 指的是前一章中解释的 Yul 代码语法中的 代码块。
    ' `6 j% U7 ]& F* SYul 对象示例如下:" v8 a" h2 ]+ B4 p. ?, M
    …code::  V7 s, a$ H3 n1 S
    // 代码由单个对象组成。 单个 “code” 节点是对象的代码。
    : A9 p( D  ^1 _; f7 }' d& l// 每个(其他)命名的对象或数据部分都被序列化  b% ?  P4 N# b/ v9 A
    // 并可供特殊内置函数:datacopy / dataoffset / datasize 用于访问/ o5 i& J$ p9 V) u1 Y
    object {- N( d' N) E0 ^, r
        code {; Q4 O& a9 Z9 N$ c6 p# m; c
            let size = datasize("runtime")% m0 A& {& t- o8 H
            let offset = allocate(size)% t3 V1 N7 I0 Q3 f
            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy
    1 M# t; \! P- ^; V$ n        datacopy(dataoffset("runtime"), offset, size)1 l0 J, g# P; \
            // 这是一个构造函数,并且运行时代码会被返回# B3 K7 F) n4 ]4 \4 Z
            return(offset, size)
    $ _6 w) i8 K0 H+ O, E* u: G    }) f% n, M, M8 N- ^/ d
        data "Table2" hex"4123"1 x3 @. h7 v4 r+ C3 R
        object "runtime" {
    - A, F5 v$ v$ g# w8 H; x# g1 n        code {! D0 V" Y$ e0 Z2 s. u; I4 V4 W
                // 运行时代码
    - K% U& T/ N. u* D% U3 f            let size = datasize("Contract2")0 R7 I9 h% i8 R$ p
                let offset = allocate(size)
    & w/ |/ T3 r9 x5 X            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy  k/ Q7 a$ W! q& V. V" t- N1 x3 Z9 G
                datacopy(dataoffset("Contract2"), offset, size)
    / n9 _. A  f0 d# y            // 构造函数参数是一个数字 0x1234. o$ y7 M  ]: A4 m  W
                mstore(add(offset, size), 0x1234)
    % ?% E, s) Z7 n2 |0 C3 z: H            create(offset, add(size, 32))/ w3 R+ w( Z4 p& R
            }
    % m6 c8 y# a% U  Z, C3 G        // 内嵌对象。使用场景是,外层是一个工厂合约,而 Contract2 将是由工厂生成的代码
    0 }/ N$ H+ E+ B* g: I' ?! `        object "Contract2" {
    + E  U. b! z9 j4 \            code {
    # k' T+ Z1 g2 y( _& u8 x                // 代码在这 ...  P9 `" ?/ `3 Y  G
                }
    6 I- h2 r+ {+ X! X# l( V            object "runtime" {; ?4 H3 j7 r3 E  p# {5 d# ~; H1 A
                    code {
    & B1 p0 b4 F# h( X# }0 h                    // 代码在这 ...
    # _# l+ t; o: [5 x7 U                }! a  ?) t/ D, A# Q" f
                 }
    4 l& s* P+ h( p8 F. G- `9 j- h7 H             data "Table1" hex"4123"& x+ X' q7 i0 B# d) W0 M' _
            }' K) [: a! v# ]; M
        }
    8 U+ ^0 T3 ~6 I2 l0 l}
  • BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
    声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    成为第一个吐槽的人