Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Yul 语言说明

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

    本版积分规则

    成为第一个吐槽的人