Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Yul 语言说明

一夜雨十年灯潞
632 0 0
Yul (先前被也被称为 JULIA 或 IULIA)是一种可以编译到各种不同后端的中间语言( |evm| 1.0,|evm| 1.5,而 eWASM 也在计划中)。
, \! Q* s, K0 _3 z正因为如此,它被设计成为这三种平台的可用的共同标准。7 J; R1 b$ C  i# j' k% E
它已经可以用于 Solidity 内部的“内联汇编”,并且未来版本的 Solidity 编译器甚至会将 Yul 用作中间语言。 为 Yul 构建高级的优化器阶段也将会很容易。
- R' j5 ^9 M0 G7 `7 d… note::; c% x; {, R6 A. G8 c  Y
请注意,用于“内联汇编”的书写风格是不带类型的(所有的都是 ``u256``),内置函数与 |evm| 操作码相同。
3 K2 \5 j7 c* d; W: C$ @有关详细信息,请参阅内联汇编文档。
; K% o; S1 S- b4 V. W" d/ tYul 的核心组件是函数,代码块,变量,字面量,for 循环,if 条件语句,switch 条件语句,表达式和变量赋值。
6 G4 q: O1 B* zYul 是强类型的,变量和字面量都需要通过前缀符号来指明类型。支持的类型有:bool, u8, s8, u32, s32,
+ l+ ^1 q; {1 Z0 |- m0 Wu64, s64, u128, s128, u256 和 s256。9 v2 a) x7 [. u3 N
Yul 本身甚至不提供操作符。如果目标平台是 |evm|,则操作码将作为内置函数提供,但如果后端平台发生了变化,则可以重新实现它们。
$ {- M8 F4 x9 r# w, |5 s2 f8 z有关强制性的内置函数的列表,请参阅下面的章节。$ v( P7 K+ `( [+ p* k$ A1 R! H
以下示例程序假定 |evm| 操作码 mul,div 和 mo 是原生支持或可以作为函数用以计算指数的。
6 Q9 S9 r- q- T… code::9 v' w* T  ~2 X4 n" V
{4 f5 j+ y* ]) q+ n& j) U
    function power(base:u256, exponent:u256) -> result:u256* e2 ^' B% a8 m, O4 [! ?$ F" x
    {/ {( G6 E" ?( m+ S' @2 ]& W9 h: b6 F
        switch exponent! j/ w! W- a- [( f* F- B+ r
        case 0:u256 { result := 1:u256 }
% {9 C3 {3 s) n: j' ]) {        case 1:u256 { result := base }# C" z1 }$ \$ t! A3 R
        default:; u2 u! Y$ E( T) U6 \% h
        {( R( T1 s% _/ i5 X' J7 M* i2 F
            result := power(mul(base, base), div(exponent, 2:u256))
" Y5 [) d- V7 w) ?( c            switch mod(exponent, 2:u256)& u, |5 s9 l( t, v5 t
                case 1:u256 { result := mul(base, result) }6 v' l, x: n! O. [- B5 B
        }$ H( @! z8 M- T' O# I
    }
; F% ]# V  A! Z/ Q" e}  H! ~& S# l. n$ H6 j( B* a: H
也可用 for 循环代替递归来实现相同的功能。这里,我们需要 |evm| 操作码 lt (小于)和 add 可用。
1 z8 a! l0 b1 z1 b) q% }… code::7 d& ^6 g# K) x1 q9 c- l
{$ G; O( X; n9 O
    function power(base:u256, exponent:u256) -> result:u256; a8 h/ l' j+ V
    {
5 b7 A4 E7 `7 c; \% y- R' \$ W        result := 1:u256- N4 o: O6 g+ x1 i1 D
        for { let i := 0:u256 } lt(i, exponent) { i := add(i, 1:u256) }2 I9 B2 T8 W+ N, c: C9 r! R2 [# u
        {
  N/ F( i2 m% s* \            result := mul(result, base)) V8 k; {0 S) ^8 e0 R+ e
        }
/ E5 r7 ?. N# a. F* X1 A- v* t    }! H6 B3 S, b% l8 G
}
, [$ G, Z# L9 U2 A/ mYul 语言说明
- Z) E7 I; {/ U% G本章介绍 Yul 代码。Yul 代码通常放置在一个 Yul 对象中,它将在下一节中介绍。
# \9 s8 r; |0 T2 _* H1 D4 ?# t语法::
" V+ }- Z9 j! ^1 I2 [代码块 = '{' 语句* '}'+ |% ]% ]: Z) m/ A0 C
语句 =( v6 ?$ `1 L) q
    代码块 |5 W" ~$ L' a1 m1 A. u' }
    函数定义 |/ D/ M  u# G0 \8 z
    变量声明 |
* h9 K5 B* o2 U8 }9 a    赋值 |
1 [/ ^2 |" t7 j) r8 O    表达式 |
7 F0 e8 S8 h1 p7 K- L    Switch |
, ~) |. J* _: `- I' F    For 循环 |
+ h7 L/ H! S& x3 W7 X    循环中断" }7 j+ `4 O7 F) j: G0 b1 R
函数定义 =
; F$ x3 O! ?+ ~3 K2 n    'function' 标识符 '(' 带类型的标识符列表? ')'+ K) R* s  }& S4 V; A
    ( '->' 带类型的标识符列表 )? 代码块
7 j- k$ n- \+ S; B% M* N变量声明 =
8 u- @/ J( f4 [, J0 P  O! \    'let' 带类型的标识符列表 ( ':=' 表达式 )?2 ]) z$ k3 E' _, s. z
赋值 =2 Z1 L7 o' H9 T/ o4 _
    标识符列表 ':=' 表达式
4 R' h; i% n& U9 }# Z$ k0 E表达式 =
: W5 E* b; X- T$ T$ l1 I  K1 f" \1 }    函数调用 | 标识符 | 字面量: X4 `4 W& u5 K0 q8 y# ~7 G
If 条件语句 =( n+ u0 l2 l. N8 I1 o9 J5 j! A
    'if' 表达式 代码块
, l* E2 W7 D$ o' `' sSwitch 条件语句 =: b2 h3 a: x! ~
    'switch' 表达式 Case* ( 'default' 代码块 )?; u5 p2 |( ?4 _
Case =
7 a8 }  Y3 `& {8 I' i    'case' 字面量 代码块
* d1 E5 O5 k8 y' K' h5 ^' u3 NFor 循环 =1 \$ u9 h% c1 j
    'for' 代码块 表达式 代码块 代码块  C9 G9 n2 o& z( g4 {
循环中断 =+ R* {4 n( ~9 M
    'break' | 'continue'
9 v8 ]' {' B1 {函数调用 =  W& ^& ^: T$ W) b- q3 U8 R
    标识符 '(' ( 表达式 ( ',' 表达式 )* )? ')'& ]7 Y- {$ @  J6 b+ ^( q3 k5 d
标识符 = [a-zA-Z_$] [a-zA-Z_0-9]*
7 H, |: P8 [6 G" m8 H, W) q9 _标识符列表 = 标识符 ( ',' 标识符)*
( h5 g' [+ N# M# Y类型名 = 标识符 | 内置的类型名
0 @* z: @# _5 M3 Q" X内置的类型名 = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )
7 g8 e) s8 p& ?  c带类型的标识符列表 = 标识符 ':' 类型名 ( ',' 标识符 ':' 类型名 )*6 _- w: g: v- Q5 I# u. E  p
字面量 =
' Y9 T. J" s/ ^5 [4 g. _- ^+ w- H    (数字字面量 | 字符串字面量 | 十六进制字面量 | True字面量 | False字面量) ':' 类型名
! [/ Z6 ^; a: x5 l7 a1 N数字字面量 = 十六进制数字 | 十进制数字8 T/ `- k6 u' j- z2 l
十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
; ~: L% _, U- U. w# \; h& p9 v; R字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"'$ Z' r( G% o' o. R  l1 K2 r
True字面量 = 'true'6 Q4 ~( x8 }% x7 A3 N0 ?8 \1 J5 K
False字面量 = 'false'* A' b$ g+ F- j& Z" a; Z$ B
十六进制数字 = '0x' [0-9a-fA-F]+
* M5 A, Y  T- w, J  ~( u十进制数字 = [0-9]+
- k: h9 |8 C" z& F( F1 W( E+ @语法层面的限制
- K1 e4 H; x7 j" bSwitches 必须至少有一个 case(包括 default )。
3 A  f& K2 w9 V2 j9 }/ k5 V如果表达式的所有可能值都被覆盖了,那么不应该允许使用 default. L0 k. L/ U: E* o* z( W+ @
(即带 bool 表达式的 switch 语句同时具有 true case 和 false case 的情况下不应再有 default 语句)。
  J) Z) O4 F& x3 R每个表达式都求值为零个或多个值。 标识符和字面量求值为一个值,函数调用求值为所调用函数的返回值。
; N, n+ b) S& a在变量声明和赋值中,右侧表达式(如果存在)求值后,必须得出与左侧变量数量相等的值。, x  {9 h' B4 m
这是唯一允许求值出多个值的表达式。
3 u: Z7 g0 F, T那种同时又是语句的表达式(即在代码块的层次)求值结果必须只有零个值。8 k9 s$ N! c0 C2 V' }' I8 ^. b
在其他所有情况中,表达式求值后必须仅有一个值。
: U: E5 k% m& M5 e  ncontinue 和 break 语句只能用在循环体中,并且必须与循环处于同一个函数中(或者两者都必须在顶层)。% F% g% @) H2 k& L) d
for 循环的条件部分的求值结果只能为一个值。8 s8 m5 E5 B. @' n
字面量不可以大于它们本身的类型。已定义的最大类型宽度为 256 比特。
& N, W2 T, T8 T; H+ |0 K" |作用域规则1 w" e$ v3 W* g. V3 ?+ L
Yul 中的作用域是与块(除了函数和 for 循环,如下所述)和所有引入新的标识符到作用域中的声明
0 b9 O, A  L3 ]6 \, q8 g( FunctionDefinition ,VariableDeclaration )紧密绑定的。
  H; h0 H7 y( ~) u标识符在将其定义的块中可见(包括所有子节点和子块)。
- N" U! D+ y. U作为例外,for 循环的 “init” 部分中(第一个块)定义的标识符在 for 循环的所有其他部分(但不在循环之外)中都是可见的。, ^  Q0 B+ Q5 W( H# F
在 for 循环的其他部分声明的标识符遵守常规的作用域语法规则。
8 Y; q. u1 p7 i. ~' e7 @函数的参数和返回参数在函数体中可见,并且它们的名称不能相同。3 ?6 _7 q- G& f( Q" p/ ?% A
变量只能在声明后引用。 尤其是,变量不能在它们自己的变量声明的右边被引用。. h' b" k2 H' K. }$ p' g' U/ j
函数可以在声明之前被引用(如果它们是可见的)。) Z. W& p9 b) {% e' ^
Shadowing 是不被允许的,即是说,你不能在同名标识符已经可见的情况下又定义该标识符,即使它是不可访问的。; E( \# A8 u8 \4 W) i2 [8 k5 y
在函数内,不可能访问声明在函数外的变量。  M. k4 o! f+ t
形式规范7 V/ d* l5 z5 ]2 ~; r3 W
我们通过在 AST 的各个节点上提供重载的求值函数 E 来正式指定 Yul。3 B+ U( h7 B7 R  j+ ?( x
任何函数都可能有副作用,所以 E 接受两个状态对象和 AST 节点作为它的参数,并返回两个新的状态对象和数量可变的其他值。: Z+ Z/ m( U3 ^, q' r$ U4 S
这两个状态对象是全局状态对象(在 |evm| 的上下文中是 |memory|,|storage| 和区块链的状态)和本地状态对象(局部变量的状态,即 |evm| 中堆栈的某个段)。
8 Q' j& d3 ^' n如果 AST 节点是一个语句,E 将返回两个状态对象和一个用于 break 和 continue 语句的 “mode”。' I. G# B) {$ Q
如果 AST 节点是表达式,则 E 返回两个状态对象,并返回与表达式求值结果相同数量的值。# b+ M* d1 G( L- u9 h: t# F$ J
在这份高层次的描述中,并没有对全局状态的确切本质进行说明。# m5 ?6 _( |' q4 c3 R5 m2 W
本地状态 L 是标识符 i 到值 v 的映射,表示为 L = v。
, k  f0 c# J% Q7 }7 i对于标识符 v, 我们用 $v 作为标识符的名字。
: \0 K) }, G7 V- B- h我们将为 AST 节点使用解构符号。
0 z) C% A" u5 U5 u& E… code::
5 r; o; c7 `: f" {; ^E(G, L, : Block) =  y$ o, h( [) n# g( ~
    let G1, L1, mode = E(G, L, St1, ..., Stn)
9 U+ b) |& S0 `. w" ?3 ~; z3 V    let L2 be a restriction of L1 to the identifiers of L2 h7 A3 m- L# E% Z' h) ^
    G1, L2, mode
8 p9 A  Z2 q$ S) c$ [6 eE(G, L, St1, ..., Stn: Statement) =
7 K" W! L. m1 F% S$ v    if n is zero:
9 O, G: J' _( S; L        G, L, regular
7 T% r9 _8 N; g9 Q    else:3 K' r( a/ [* v3 Q
        let G1, L1, mode = E(G, L, St1)' i7 l2 H7 I: o) N2 K  V* s, b0 q
        if mode is regular then! ~; N; A5 ]: H
            E(G1, L1, St2, ..., Stn)4 t( O7 b4 L; \) X0 D
        otherwise* A. [2 V/ W( D7 q
            G1, L1, mode8 I$ c) c# d, q8 V1 \2 N
E(G, L, FunctionDefinition) =' N( t3 c. q  b  c& p
    G, L, regular
$ r/ L' `0 a- f$ d7 ]) E1 I1 _5 JE(G, L, : VariableDeclaration) =
  m& E8 e9 `4 u    E(G, L, : Assignment)
' c2 r0 G* w8 h0 J0 N! pE(G, L, : VariableDeclaration) =
! S9 G7 k) }; b  `. E; Y3 c# V    let L1 be a copy of L where L1[$vari] = 0 for i = 1, ..., n1 m3 |2 s' H" h/ D2 w
    G, L1, regular9 t* e% @- B. o5 [+ Z
E(G, L, : Assignment) =
' Y: f4 \( ^$ D( o    let G1, L1, v1, ..., vn = E(G, L, rhs)- k- h' q: y4 @; l2 q0 y% \
    let L2 be a copy of L1 where L2[$vari] = vi for i = 1, ..., n3 h( L  ?7 C1 @4 v( i4 q0 p. D
    G, L2, regular
( b5 C, N+ B. S) _& ~3 V' h8 ^$ ~E(G, L, : ForLoop) =  f) w- ]* J; x
    if n >= 1:
6 }6 J* d2 ^+ U3 y% `, ^4 M        let G1, L1, mode = E(G, L, i1, ..., in): t0 `6 M' _6 t0 |2 n8 _5 r+ Y
        // 由于语法限制,mode 必须是规则的
- O3 e# R. U' l4 `" c- m        let G2, L2, mode = E(G1, L1, for {} condition post body)( n% S5 O2 x' k! ^# d# b
        // 由于语法限制,mode 必须是规则的
; X3 a% x5 J% z( L. T. s, D        let L3 be the restriction of L2 to only variables of L, m; W9 z- |3 q
        G2, L3, regular. m& O# _$ T/ }, Y/ v: Y4 U
    else:
8 E* {$ z' ?% \+ S8 V        let G1, L1, v = E(G, L, condition)
7 ?& U- Y+ w$ q" P, P6 j! m        if v is false:
2 Y. H& g- j) u) y: x* z4 p: s            G1, L1, regular/ L1 C! J/ U) e+ F! _4 C! K
        else:# q8 u, R1 I) A, X- C+ P
            let G2, L2, mode = E(G1, L, body)
  q1 M9 B; D5 ~* q8 r3 h            if mode is break:) v: t. {. E* v' s! l! k& w! @
                G2, L2, regular
! h2 S* S- u+ a, w, |            else:) v) Z9 \+ _- w8 m- d8 J! k
                G3, L3, mode = E(G2, L2, post)* \3 G6 G3 D# J3 u# D3 `  G6 r. E
                E(G3, L3, for {} condition post body)$ y  }0 p8 t' b& J7 R5 o" p' [
E(G, L, break: BreakContinue) =( J  p  F3 i& `$ x* @
    G, L, break0 |# f3 X; r" K
E(G, L, continue: BreakContinue) =2 x/ V1 F- B+ I6 u4 D& T5 f
    G, L, continue
1 f( E% y6 i! `( w$ p' r# `% eE(G, L, : If) =+ |$ `- H( ]; ~( Q" l8 E
    let G0, L0, v = E(G, L, condition); n- b1 b5 Y  M% |+ f+ M1 M
    if v is true:- i1 ^: B# l, V  ~
        E(G0, L0, body)
7 U4 N, Q) `6 z! C4 `1 [& D    else:
0 u: J# x1 E! `- @        G0, L0, regular; d; N9 C$ Y* v6 q- Y4 l9 u1 ?1 v
E(G, L, : Switch) =; y6 `) V" p- i2 o
    E(G, L, switch condition case l1:t1 st1 ... case ln:tn stn default {})# c4 p- h( k$ A5 Q8 s
E(G, L, : Switch) =' r2 n$ |& e2 R8 v4 @
    let G0, L0, v = E(G, L, condition)4 F4 t( d$ f* y; W+ ?
    // i = 1 .. n! S' Y  y' E& Q3 s+ ^
    // 对字面量求值,上下文无关" R, p( w) j' ]* l
    let _, _, v1 = E(G0, L0, l1)& D' k; d. f3 \; h' q- P
    ...; a2 e3 n' X1 @& L: r7 N
    let _, _, vn = E(G0, L0, ln)
0 A; ]6 g6 m/ r; s. V1 J" {7 `    if there exists smallest i such that vi = v:$ S* @8 m% k# j* r
        E(G0, L0, sti)
  F! e& M% G( o' a    else:- Y( g2 E4 J- t- x0 Y" v
        E(G0, L0, st')
& i5 j+ S& F1 S% qE(G, L, : Identifier) =
: q# T1 i" R( R: \  `    G, L, L[$name]
* ?5 L! f* c! ~/ F( Z1 p: ]# YE(G, L, : FunctionCall) =; [: K  H6 R, v" N
    G1, L1, vn = E(G, L, argn)
  ~" p$ s& _5 N5 b    ...
( e# a: I* q- J    G(n-1), L(n-1), v2 = E(G(n-2), L(n-2), arg2)
6 R4 Q; u4 V0 |' g; [( f$ h    Gn, Ln, v1 = E(G(n-1), L(n-1), arg1)
" ~8 _  q' o! o" n( ?+ e0 @1 r% Y6 [& t    Let  ret1, ..., retm block>: X* W  o' i. M. }
    be the function of name $fname visible at the point of the call.
& b" g; d  d" N9 N: c    Let L' be a new local state such that
0 [/ a2 o, T" ]  E2 a    L'[$parami] = vi and L'[$reti] = 0 for all i.
3 J8 A0 |! u% N  {# L6 R& g# b    Let G'', L'', mode = E(Gn, L', block)
- n- T3 t8 @) {; s    G'', Ln, L''[$ret1], ..., L''[$retm]
" C3 T. x( a9 o( ZE(G, L, l: HexLiteral) = G, L, hexString(l),: g, B( J- d" I0 V# e
    where hexString decodes l from hex and left-aligns it into 32 bytes
. _, m4 u; q  V4 u( k& d' TE(G, L, l: StringLiteral) = G, L, utf8EncodeLeftAligned(l),0 i. |, v" M& C
    where utf8EncodeLeftAligned performs a utf8 encoding of l* O0 k4 t9 j2 \; T) s
    and aligns it left into 32 bytes3 }# H! o. O9 k! @4 B
E(G, L, n: HexNumber) = G, L, hex(n)
4 P# V( @. k! i) l  \  p    where hex is the hexadecimal decoding function) E% X5 ~' i7 r. T, m+ w
E(G, L, n: DecimalNumber) = G, L, dec(n),, O' k$ `/ p2 V6 K2 ^9 ~4 f' r" u
    where dec is the decimal decoding function, m8 F+ T: H4 L1 P
类型转换函数# o5 u! g, t+ F6 G5 N
Yul 不支持隐式类型转换,因此存在提供显式转换的函数。9 l. ^/ u: H$ \) n- u. v- Y% g
在将较大类型转换为较短类型时,如果发生溢出,则可能会发生运行时异常。) t6 ~8 N# p( u- V) o" Z3 b
下列类型的“截取式”转换是允许的:! v6 J' H5 h! P& @
  • bool
  • u32
  • u64
  • u256
  • s256! Y- g& T& y" {/ d

    / @# m. |# ?" m& d5 f这里的每种类型的转换函数都有一个格式为 to(x:) -> y: 的原型,4 |6 v3 ]' X! }" y" a# a8 p
    比如 u32tobool(x:u32) -> y:bool、u256tou32(x:u256) -> y:u32 或 s256tou256(x:s256) -> y:u256。
    8 W/ l2 U9 N* K& t" {' S4 S… note::& h* F- d. M. G6 ^
    ``u32tobool(x:u32) -> y:bool`` 可以由 ``y := not(iszerou256(x))`` 实现,并且
    1 v. z% Z8 E% G* n0 ]' m``booltou32(x:bool) -> y:u32`` 可以由 ``switch x case true:bool { y := 1:u32 } case false:bool { y := 0:u32 }`` 实现, B/ Q) R6 y( U
    低级函数( I7 F0 x8 x' d& P# x. d, H9 [" ~
    以下函数必须可用:
    # r. k9 u  r0 E±--------------------------------------------------------------------------------------------------------------+& N  k  ]! O% b1 M0 A, n( b$ m9 j
    | 逻辑操作                                                                                                    |  U( s# d) D3 p+ p
    ±--------------------------------------------±----------------------------------------------------------------+$ d$ W: p1 E: s- f7 Z
    | not(x:bool) -> z:bool                       | 逻辑非                                                          |
    1 k, L1 T( C! b: O+ X% x±--------------------------------------------±----------------------------------------------------------------+
    8 J. s) _9 K3 F" v! {  \0 ]- Q| and(x:bool, y:bool) -> z:bool               | 逻辑与                                                          |; e/ A1 C3 Q3 W/ T) w$ Q
    ±--------------------------------------------±----------------------------------------------------------------+/ w: J5 }# Z+ Y, M# B
    | or(x:bool, y:bool) -> z:bool                | 逻辑或                                                          |7 u/ N/ J6 n% a
    ±--------------------------------------------±----------------------------------------------------------------+* Y) e& o' p0 |6 O3 X% P8 L& S' V
    | xor(x:bool, y:bool) -> z:bool               | 异或                                                            |/ X; o1 H$ z( B
    ±--------------------------------------------±----------------------------------------------------------------+! @' \# F: n' l' l. a% q  B- m5 S
    | 算术操作                                                                                                    |* N1 o* E8 H' F) X9 v  k7 ^4 K
    ±--------------------------------------------±----------------------------------------------------------------+0 m! [( o/ ~* k, a7 z! R
    | addu256(x:u256, y:u256) -> z:u256           | x + y                                                           |
    8 t: j# t# g2 }. `% Z8 n4 D( S±--------------------------------------------±----------------------------------------------------------------+8 U- n0 Y  E8 H" j+ P
    | subu256(x:u256, y:u256) -> z:u256           | x - y                                                           |* q) W5 ]  Z: g! q0 @
    ±--------------------------------------------±----------------------------------------------------------------+* ~5 G! w1 `0 L) F8 n. J: N
    | mulu256(x:u256, y:u256) -> z:u256           | x * y                                                           |
    8 B3 Z" v2 }( G  o±--------------------------------------------±----------------------------------------------------------------+5 a2 q1 H. a( D
    | divu256(x:u256, y:u256) -> z:u256           | x / y                                                           |# c4 [! N7 D$ O- m* t
    ±--------------------------------------------±----------------------------------------------------------------+, ?4 S1 c7 ?/ {& ~' y5 C% I
    | divs256(x:s256, y:s256) -> z:s256           | x / y, 有符号数用补码形式                                       |; o" o/ o( ?) c
    ±--------------------------------------------±----------------------------------------------------------------+
    6 f& w9 l: H5 S7 f! o| modu256(x:u256, y:u256) -> z:u256           | x % y                                                           |
    9 I  E9 M' T( y±--------------------------------------------±----------------------------------------------------------------+  {1 z* \/ J3 d: Q& ^% @
    | mods256(x:s256, y:s256) -> z:s256           | x % y, 有符号数用补码形式                                       |
    8 U. s( F" @$ P/ R, j! \7 H±--------------------------------------------±----------------------------------------------------------------+
    1 a0 V4 z  D: Y2 D| signextendu256(i:u256, x:u256) -> z:u256    | 从第 (i*8+7) 位开始进行符号扩展,从最低符号位开始计算           |' a! u3 m* }5 U! p: C) G+ s3 I
    ±--------------------------------------------±----------------------------------------------------------------+
    0 h4 H: C7 y5 ]* k| expu256(x:u256, y:u256) -> z:u256           | x 的 y 次方                                                     |+ h7 r" T4 J& x' V
    ±--------------------------------------------±----------------------------------------------------------------+
    2 Z0 r( P8 s  k* ~| addmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x + y) % m                                |( F) l* y) H- g0 U+ s+ S1 f
    ±--------------------------------------------±----------------------------------------------------------------+) l/ ], x/ d" D( Z5 B
    | mulmodu256(x:u256, y:u256, m:u256) -> z:u256| 任意精度的数学模运算 (x * y) % m                                |) Y8 [; q# e/ c9 i7 y2 H/ ~) ]' E
    ±--------------------------------------------±----------------------------------------------------------------+; P6 ]# s/ }( D* X9 D0 t
    | ltu256(x:u256, y:u256) -> z:bool            | 若 x  z:bool            | 若 x > y 为 true, 否则为 false                                  |
    ' H; S  [  m5 _& Y9 n±--------------------------------------------±----------------------------------------------------------------+
    & j/ M) J% [$ D( h) g% [- J0 e| sltu256(x:s256, y:s256) -> z:bool           | 若 x  z:bool           | 若 x > y 为 true, 否则为 false                                  |
    9 m9 ^+ ~7 |8 K; z|                                             | 有符号数用补码形式                                              |. _& K9 c9 {5 `$ W+ z" p& Z, u
    ±--------------------------------------------±----------------------------------------------------------------+- W7 {7 t$ p: \5 ?8 |% l
    | equ256(x:u256, y:u256) -> z:bool            | 若 x == y 为 true, 否则为 false                                 |
    . y$ e) z. y( ]$ M±--------------------------------------------±----------------------------------------------------------------+
    6 X& d8 I, I% u. v- C: R* H* b  c2 I| iszerou256(x:u256) -> z:bool                | 若 x == 0 为 true, 否则为 false                                 |- a+ U5 D# Z. E4 s
    ±--------------------------------------------±----------------------------------------------------------------+
    & S9 m$ o" n% G8 l6 Y3 l" k| notu256(x:u256) -> z:u256                   | ~x, 对 x 按位非                                                 |
    4 ~  |7 V1 m0 L1 P±--------------------------------------------±----------------------------------------------------------------+- }4 J; o8 D0 o
    | andu256(x:u256, y:u256) -> z:u256           | x 和 y 按位与                                                   |
    3 D. B+ w8 d4 B1 l& f±--------------------------------------------±----------------------------------------------------------------+
    $ m: f; Q2 {5 \5 C2 `& P| oru256(x:u256, y:u256) -> z:u256            | x 和 y 按位或                                                   |
    # ]4 l2 R& V. S±--------------------------------------------±----------------------------------------------------------------+
    7 ~. v! d& b7 e: i7 @  h| xoru256(x:u256, y:u256) -> z:u256           | x 和 y 按位异或                                                 |
    : E# ?& V) }$ y& y6 I# X* f  j±--------------------------------------------±----------------------------------------------------------------+3 P# Z  f" @) ^2 c: d/ |( C+ M
    | shlu256(x:u256, y:u256) -> z:u256           | 将 x 逻辑左移 y 位                                              |
      N  d' S& e9 t9 \4 N±--------------------------------------------±----------------------------------------------------------------+% t, l1 l9 Q# `8 V/ Q1 O" L7 Q
    | shru256(x:u256, y:u256) -> z:u256           | 将 x 逻辑右移 y 位                                              |& v4 R. s8 c/ G& A# h1 p( i* t
    ±--------------------------------------------±----------------------------------------------------------------+
    $ |. B& N/ q6 r+ x( M| saru256(x:u256, y:u256) -> z:u256           | 将 x 算术右移 y 位                                              |
    ) ^3 b0 o) w' Q2 c7 [±--------------------------------------------±----------------------------------------------------------------+
    ( P3 w% i4 i& ^| byte(n:u256, x:u256) -> v:u256              | x 的第 n 字节,这里的索引位置是从 0 开始的;                    |; y* M& \. X( H5 l
    |                                             | 能否用 and256(shr256(n, x), 0xff) 来替换它,                    |" ]4 N$ T; _( m2 `, u8 y
    |                                             | 并使它在 EVM 后端之外被优化呢?                                 |
    ) b8 |# J3 Q3 W1 ~' }6 g6 J±--------------------------------------------±----------------------------------------------------------------+% [' r6 i: a1 b( i) L: y0 d7 t
    | 内存和存储                                                                                                  |1 `  ]' ^  w3 V* C5 |
    ±--------------------------------------------±----------------------------------------------------------------+1 ~# g# A+ ?: e
    | mload(p:u256) -> v:u256                     | mem[p…(p+32))                                                  |' f5 P2 t; S* B5 V
    ±--------------------------------------------±----------------------------------------------------------------+0 c3 g6 x. {( _  ^2 k7 F! Y6 x9 i8 e3 a% ?
    | mstore(p:u256, v:u256)                      | mem[p…(p+32)) := v                                             |! g0 P* E( w3 B- t, ~* u( f" `
    ±--------------------------------------------±----------------------------------------------------------------+" I5 f) o( s: \+ r& b
    | mstore8(p:u256, v:u256)                     | mem := v & 0xff    - 仅修改单个字节                          |
    1 N7 k" i: s0 i( V& m±--------------------------------------------±----------------------------------------------------------------+
    & Z/ l& g! L* R. Y. y( V8 L1 ^: _| sload(p:u256) -> v:u256                     | storage                                                      |+ X. B1 M/ G3 e" X, j* R: A
    ±--------------------------------------------±----------------------------------------------------------------+
    ) x; h' Z1 a9 A  c. t| sstore(p:u256, v:u256)                      | storage := v                                                 |$ V6 X' C* H3 N: a0 g1 P
    ±--------------------------------------------±----------------------------------------------------------------+
    + v4 g# A+ E0 C! H( c$ O1 e| msize() -> size:u256                        | 内存的大小, 即已访问过的内存的最大下标,                        |$ F( U8 }0 s  U4 x) K$ O
    |                                             | 因为内存扩展的限制(只能按字进行扩展)                          |7 t, s2 p7 Z. u# z3 }: u
    |                                             | 返回值永远都是 32 字节的倍数                                    |
    8 p5 _# v  W+ }* Z) n; E2 j±--------------------------------------------±----------------------------------------------------------------+0 @# [- ?2 p3 w3 Y& p
    | 执行控制                                                                                                    |
    % m$ a8 M* v9 _* t±--------------------------------------------±----------------------------------------------------------------+
    $ V- c% ?  W0 e: o2 _| create(v:u256, p:u256, s:u256)              | 以 mem[p…(p+s)) 上的代码创建一个新合约,发送                   |7 }" b' a& x1 ~; k
    |                                             | v 个 wei,并返回一个新的地址                                    |
    6 R+ Z8 t5 L: R0 f5 T7 v2 Z/ t" z±--------------------------------------------±----------------------------------------------------------------+! t2 x1 G# t: P7 g, j( t& Q/ @8 x
    | call(g:u256, a:u256, v:u256, in:u256,       | 调用地址 a 上的合约,以 mem[in…(in+insize)) 作为输入           |0 o* o' X$ t( {' o9 [1 C1 e3 Q; o; ?& E. g
    | insize:u256, out:u256,                      | 一并发送 g gas 和 v wei ,以 mem[out…(out+outsize))            |' b. o/ }* L( W. _" X5 f# M1 I
    | outsize:u256)                               | 作为输出空间。若错误,返回 0 (比如,gas 用光                   |( j& l! U5 _# O( e7 r
    | -> r:u256                                   | 成功,返回 1                                                    |
    / O% c' B; j9 X: u+ X/ a* R# H±--------------------------------------------±----------------------------------------------------------------+0 r" V2 Q6 ]6 C) a0 T6 G. \% V
    | callcode(g:u256, a:u256, v:u256, in:u256,   | 相当于 call 但仅仅使用地址 a 上的代码,                     |. H( I  j! _3 G8 A
    | insize:u256, out:u256,                      | 而留在当前合约的上下文当中                                      |4 Y7 v: M* t7 _6 ]# e% U) t
    | outsize:u256) -> r:u256                     |                                                                 |
      b+ N8 f! e( \# O7 `±--------------------------------------------±----------------------------------------------------------------+
    " l! [5 q) i1 R' w| delegatecall(g:u256, a:u256, in:u256,       | 相当于 callcode,                                           |0 u4 k. p' K1 \. z  n1 x7 H: A' Z5 {. u
    | insize:u256, out:u256,                      | 但同时保留 caller                                           |( X& k! N! t0 d& n. S' C) {
    | outsize:u256) -> r:u256                     | 和 callvalue                                                |. }% U* E8 O7 _0 _% \3 Z# m/ a
    ±--------------------------------------------±----------------------------------------------------------------+
    6 ~) c' ~2 o$ W% ?| abort()                                     | 终止 (相当于EVM上的非法指令)                                    |
    * O; M7 k1 K/ r) e# }6 C) \±--------------------------------------------±----------------------------------------------------------------+
    6 h) r$ ^/ I- k0 m6 h* e' e| return(p:u256, s:u256)                      | 终止执行,返回 mem[p…(p+s)) 上的数据                           |
    8 i4 N* A6 E; d! G, W8 W5 k# E±--------------------------------------------±----------------------------------------------------------------+
    5 M  ?: P% `: s  A' z# p| revert(p:u256, s:u256)                      | 终止执行,恢复状态变更,返回 mem[p…(p+s)) 上的数据             |
    # I& o1 V* L! P1 I1 J# T% O±--------------------------------------------±----------------------------------------------------------------+
    1 T* D: Q: q, K- z. p, @; s) K| selfdestruct(a:u256)                        | 终止执行,销毁当前合约,并且将余额发送到地址 a                  |
      I3 A/ v* }0 T±--------------------------------------------±----------------------------------------------------------------+
    7 k8 c8 l' l. D& X9 X$ B1 U| log0(p:u256, s:u256)                        | 用 mem[p…(p+s)] 上的数据产生日志,但没有 topic                 |2 E& D2 h9 C$ J) T# @2 Q
    ±--------------------------------------------±----------------------------------------------------------------+$ b# [7 P! d  m* ]0 Y9 a4 A
    | log1(p:u256, s:u256, t1:u256)               | 用 mem[p…(p+s)] 上的数据和 topic t1 产生日志                   |
    " O! |* T% X9 z. {' \7 D2 M±--------------------------------------------±----------------------------------------------------------------+
    ) G4 f% T" s3 t0 M! `! P4 N3 @7 W| log2(p:u256, s:u256, t1:u256, t2:u256)      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2 产生日志               |
    4 P) L( \" [* A2 j0 |±--------------------------------------------±----------------------------------------------------------------+
    % q- _! }6 P' i2 R| log3(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3 产生日志           |1 t5 _+ I. g( n) J* H
    | t3:u256)                                    |                                                                 |
    6 F. {# L/ F$ i±--------------------------------------------±----------------------------------------------------------------+4 k9 f1 c" j2 K
    | log4(p:u256, s:u256, t1:u256, t2:u256,      | 用 mem[p…(p+s)] 上的数据和 topic t1,t2,t3,t4                |8 ^1 ^- {; ]6 H0 [6 A+ N. u& M
    | t3:u256, t4:u256)                           | 产生日志                                                        |; C8 \& o" E5 V8 g  l/ Q4 T
    ±--------------------------------------------±----------------------------------------------------------------+( f* h* t" }: r* [
    | 状态查询                                                                                                    |
    # l' H4 @* v  `$ O5 u& P6 h±--------------------------------------------±----------------------------------------------------------------+
    6 a6 q( i4 b" h, A# t| blockcoinbase() -> address:u256             | 当前的矿工                                                      |2 R: R. X) k* C: A/ p/ n0 H0 x$ x+ _
    ±--------------------------------------------±----------------------------------------------------------------+
    $ F) |) ]8 X! U: T  I9 a' w2 O| blockdifficulty() -> difficulty:u256        | 当前区块的难度                                                  |
    + g& f% w+ D$ \* d6 b±--------------------------------------------±----------------------------------------------------------------+
    - D3 U8 v% \3 q: l  m4 X( |. I; _| blockgaslimit() -> limit:u256               | 当前区块的区块 gas 限制                                         |
    7 a! q. E# V2 @+ {7 x( Y# B±--------------------------------------------±----------------------------------------------------------------+
    2 |- J# Y4 M4 }6 U| blockhash(b:u256) -> hash:u256              | 区块号为 b 的区块的哈希,                                       |4 q* e2 L' Y8 r1 M; V/ N  U. P
    |                                             | 仅可用于最近的 256 个区块,不包含当前区块                       |
    & y* q( G/ Y" v: M8 {! f2 J±--------------------------------------------±----------------------------------------------------------------+
    ) b/ T* A6 Q3 ^5 L| blocknumber() -> block:u256                 | 当前区块号                                                      |
    / |  E4 H6 X$ R4 I. W9 ?0 n±--------------------------------------------±----------------------------------------------------------------++ l; v4 W, Y% c$ E, z
    | blocktimestamp() -> timestamp:u256          | 自 epoch 开始的,当前块的时间戳,以秒为单位                     |
    # l6 q, {# K; y8 g2 K±--------------------------------------------±----------------------------------------------------------------+( G7 @3 i6 {5 [/ t( T# |. }
    | txorigin() -> address:u256                  | 交易的发送方                                                    |
    # e: f( ~7 |" m3 w±--------------------------------------------±----------------------------------------------------------------+
    / j3 a! p7 I4 k* i; D( X6 X8 V- ]| txgasprice() -> price:u256                  | 交易中的 gas 价格                                               |
    # w' o% o+ }4 l, ~( ]2 g±--------------------------------------------±----------------------------------------------------------------+
    . K" L  T, p  B| gasleft() -> gas:u256                       | 还可用于执行的 gas                                              |
    4 {6 m: P2 \9 y6 ^±--------------------------------------------±----------------------------------------------------------------+
    * {- A4 [' A* ]| balance(a:u256) -> v:u256                   | 地址 a 上的 wei 余额                                            |, O, j# e+ E* D' F
    ±--------------------------------------------±----------------------------------------------------------------+
    # Z0 L' c) j! ?5 |) T+ ]# j| this() -> address:u256                      | 当前合约/执行上下文的地址                                      |
      W, H8 C- h8 J- O) \* q9 q±--------------------------------------------±----------------------------------------------------------------+
    . [$ F, D: G  E- j! m, g3 B' d" _% a| caller() -> address:u256                    | 调用的发送方 (不包含委托调用)                                   |) @% k) Z- R( `
    ±--------------------------------------------±----------------------------------------------------------------+' |! _  i, |3 R: K& b$ u7 \: R
    | callvalue() -> v:u256                       | 与当前调用一起发送的 wei                                        |. V: V- q( v+ A7 s8 @
    ±--------------------------------------------±----------------------------------------------------------------+5 b$ [: L- B. D3 r" |; y9 X# q3 o
    | calldataload(p:u256) -> v:u256              | 从 position p 开始的 calldata (32 字节)                         |
    7 i/ E! c6 h$ v- Y  u0 H0 ?±--------------------------------------------±----------------------------------------------------------------+5 r8 i. V0 E. i: [# u% v+ B5 L
    | calldatasize() -> v:u256                    | 以字节为单位的 calldata 的大小                                  |* n$ @, P  ?  x+ h
    ±--------------------------------------------±----------------------------------------------------------------+
    . B$ C0 i  k1 I, M| calldatacopy(t:u256, f:u256, s:u256)        | 从位置为 f 的 calldata 中,拷贝 s 字节到内存位置 t              |. ]1 ?1 _8 c- }1 d* P! {, H
    ±--------------------------------------------±----------------------------------------------------------------+1 z/ p4 u2 t/ H5 X
    | codesize() -> size:u256                     | 当前合约/执行上下文的代码大小                                  |
    + g; f% O3 E* a/ Q±--------------------------------------------±----------------------------------------------------------------+
    " D! M$ K2 D) X8 E% G| codecopy(t:u256, f:u256, s:u256)            | 从 code 位置 f 拷贝 s 字节到内存位置 t                          |
    3 A7 b7 y& Q/ \±--------------------------------------------±----------------------------------------------------------------+
    4 v* R3 W$ x/ M! w  r| extcodesize(a:u256) -> size:u256            | 地址 a 上的代码大小                                             |; U9 l9 z; u* Z
    ±--------------------------------------------±----------------------------------------------------------------+5 K  r' h0 {6 |
    | extcodecopy(a:u256, t:u256, f:u256, s:u256) | 相当于 codecopy(t, f, s),但从地址 a 获取代码                   |( M; r2 h" t; \* \
    ±--------------------------------------------±----------------------------------------------------------------+
    7 q1 K" S: k3 x1 q2 I, U| 其他                                                                                                        |
    + X% w5 {9 B, P% f" v5 a" R7 \' ?8 P±--------------------------------------------±----------------------------------------------------------------+/ i; e% W0 v4 D1 j! y+ z" C3 G* h
    | discard(unused:bool)                        | 丢弃值                                                          |' b% Q; M8 n5 U5 ]! V+ d
    ±--------------------------------------------±----------------------------------------------------------------+1 o: c6 F* m1 U- F7 @
    | discardu256(unused:u256)                    | 丢弃值                                                          |6 W" ^; |2 D/ ^7 R- j) E
    ±--------------------------------------------±----------------------------------------------------------------+
    ) s# Y7 W) Y5 X* u+ T" H| splitu256tou64(x:u256) -> (x1:u64, x2:u64,  | 将一个 u256 拆分为四个 u64                                      |
      U3 y1 q( a$ e. M0 c: O$ c8 y. f|                            x3:u64, x4:u64)  |                                                                 |
    " b! I- w" @- Z& H±--------------------------------------------±----------------------------------------------------------------+
    " q8 w/ y' E% X| combineu64tou256(x1:u64, x2:u64, x3:u64,    | 将四个 u64 组合为一个 u256                                      |( y; h+ T/ G, W4 E* [
    |                  x4:u64) -> (x:u256)        |                                                                 |
    % m' N/ v0 g; g% J; a±--------------------------------------------±----------------------------------------------------------------+
    3 W# k$ ~7 I: A* A( w3 _" D| keccak256(p:u256, s:u256) -> v:u256         | keccak(mem[p…(p+s)))                                          |
    % ~1 S3 c: P( `6 [±--------------------------------------------±----------------------------------------------------------------+
    . L, N! v0 s& Z9 V0 {0 Y3 t2 A  m后端
    . |3 f( ^4 ]* k. o5 x后端或目标负责将 Yul 翻译到特定字节码。 每个后端都可以暴露以后端名称为前缀的函数。 我们为两个建议的后端保留 evm_ 和 ewasm_ 前缀。  G4 J1 [4 W; p$ F" I  H' o
    后端: EVM
    ) f7 _& J% D8 _目标 |evm| 将具有所有用 evm_ 前缀暴露的 |evm| 底层操作码。% i6 g6 {( B- D( |  P3 J3 I
    后端: “EVM 1.5”8 t( _) n; E6 B. Q* r
    TBD
    ! V0 V8 p5 o; Q3 ?- G后端: eWASM
    - q! N  i5 ]1 DTBD+ t# `9 F$ _3 Q4 P' d/ [, `1 }
    Yul 对象说明
    5 y7 H0 j/ H, ~2 D7 ]/ V语法::
    " f1 s* z$ Q% _4 M. `顶层对象 = 'object' '{' 代码? ( 对象 | 数据 )* '}'
    ( l8 L8 @1 `! |" q3 x对象 = 'object' 字符串字面量 '{' 代码? ( 对象 | 数据 )* '}'% Z" H/ L5 b0 n& s6 v/ ]& n
    代码 = 'code' 代码块9 ~5 }5 i7 ?: Y6 ]9 H
    数据 = 'data' 字符串字面量 十六进制字面量' s* N2 `* h2 R" n' ]
    十六进制字面量 = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')7 S- c( @) n6 u9 r
    字符串字面量 = '"' ([^"\r\n\\] | '\\' .)* '"'' n/ X0 E7 Q! c' t! p+ M/ i- o
    在上面,代码块 指的是前一章中解释的 Yul 代码语法中的 代码块。. \5 z$ _# y5 ?( @, u; B
    Yul 对象示例如下:5 B) M" H8 ~) h. f7 Z* |6 m
    …code::' S$ f, y" F( E* A
    // 代码由单个对象组成。 单个 “code” 节点是对象的代码。1 R/ _/ X8 b# Y, y/ }2 }/ A* @
    // 每个(其他)命名的对象或数据部分都被序列化
    1 Z1 m" d& j. n5 R- N8 U6 a// 并可供特殊内置函数:datacopy / dataoffset / datasize 用于访问3 o4 m8 J6 k: |7 h5 U) I
    object {6 a# N* {7 _* d$ s
        code {
    . m: u" L* L* t        let size = datasize("runtime")# E8 I3 I# W! V( ^
            let offset = allocate(size)+ p5 N) g; a' ~+ q2 M
            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy# G5 _9 }' [( A3 h, P0 z2 N3 o: W
            datacopy(dataoffset("runtime"), offset, size)
    & Y; q3 ~" m+ A6 L) x, n        // 这是一个构造函数,并且运行时代码会被返回
    ) f3 \/ `, r" Q        return(offset, size)( e/ X& B" P5 v4 Y& S% n0 w1 W& T
        }
    . O9 C. D4 N$ h2 n# v    data "Table2" hex"4123"- Z5 V6 L8 i# H) [* v5 w
        object "runtime" {6 _& J- {  s/ ?# c, n* }" X
            code {
    8 v+ D/ i$ N& z4 u6 O2 G! Q            // 运行时代码( N4 V4 t: v6 e* o
                let size = datasize("Contract2")
    ' X: j, R( R" g# r            let offset = allocate(size)
    & h7 W% c1 u% _  o; ~  L# B: k5 B            // 这里,对于 eWASM 变为一个内存到内存的拷贝,对于 EVM 则相当于 codecopy4 [+ j9 f3 z- V7 i, A
                datacopy(dataoffset("Contract2"), offset, size)5 G/ s& g& o0 _9 d; t, ?! W7 y6 y
                // 构造函数参数是一个数字 0x1234
    # f1 n9 R* i" n( Q) }1 q. a            mstore(add(offset, size), 0x1234)
    5 f6 _- z4 C. e  Q# M# B            create(offset, add(size, 32))
    " n3 @- U- G. p( T        }
    ! U& t3 o5 n: x& O* a2 q' z6 N: z/ ?  c        // 内嵌对象。使用场景是,外层是一个工厂合约,而 Contract2 将是由工厂生成的代码$ L1 ]! o  m3 `+ ]- A6 F) Q
            object "Contract2" {
    5 Y' N0 a: m4 x' |  }            code {, @$ d6 f. ]# N
                    // 代码在这 ...% K3 P2 W5 v" f3 X
                }
    : C8 Y! [' {. I# d            object "runtime" {
    1 t; W# q, F5 \% Y- A                code {
    3 d+ ?% l4 o8 T+ L% r7 d, }                    // 代码在这 ...
    5 j  R( [6 V# \                }
    & f# q& @0 v" h- ]             }
    ! T4 Q& _1 y6 ^: S- }. h0 ~9 B             data "Table1" hex"4123"( Z7 h& y$ B$ k. m% T3 M+ k6 Y
            }" P# m! O+ A. f5 {
        }5 |. }7 c* V. p
    }
  • BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
    声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    成为第一个吐槽的人