@@ -131,6 +131,14 @@ set flags by appending a “set flags” modifier to them, like that:
131
131
sub! r1, r2, r3 ; r3 <- (r1 - r2); EQ = 1
132
132
```
133
133
134
+ Most instructions with “set flags” modifier set the flags as follows:
135
+
136
+ - ` EQ ` - if result is zero
137
+ - ` LT ` - if overflow occurs (result is "less" than zero)
138
+ - ` GT ` - if not ` EQ ` and not ` LT ` (result is "greater" than zero)
139
+
140
+ Note that the details of the behavior may vary depending on which instruction is used.
141
+
134
142
You can learn more in the
135
143
[ formal specification] ( ./formal-spec.md ) .
136
144
@@ -144,27 +152,28 @@ Recall the three flags: LT, EQ and GT.
144
152
For example, this ` sub ` instruction is only executed if EQ is set:
145
153
146
154
``` nasm
147
- sub.if_eq r1, r2, r5
155
+ sub.eq r1, r2, r5
148
156
```
149
157
150
158
Here is how we can execute ` jump ` to a label ` .label_if_equals ` only if ` r1 == r2 ` :
151
159
152
160
``` nasm
153
161
sub! r1, r2, r3 ; r3 <- (r1 - r2); EQ = 1 if r1 == r2
154
- jump.if_eq .label_if_equals
162
+ jump.eq .label_if_equals
155
163
```
156
164
157
165
If the condition is not satisfied, we skip the instruction, but still pay its basic cost in gas.
158
166
159
167
Here is a full list of available predicates:
160
168
161
- - ` if_gt `
162
- - ` if_eq `
163
- - ` if_lt `
164
- - ` if_ge ` (short for “GT or EQ”)
165
- - ` if_le ` (short for “LT or EQ”)
166
- - ` if_not_eq `
167
- - ` if_gt_or_eq `
169
+ - ` gt `
170
+ - ` eq `
171
+ - ` lt `
172
+ - ` ge ` (short for “GT or EQ”)
173
+ - ` le ` (short for “LT or EQ”)
174
+ - ` ne ` (short for "not EQ")
175
+ - ` gtlt ` (short for "GT" or "LT")
176
+ - ` of ` (synonym for "LT")
168
177
169
178
You can learn more in the
170
179
[ formal specification] ( ./formal-spec.md ) .
@@ -188,12 +197,12 @@ sub.s r1, r2, r3 ; r3 <- r2 - r1
188
197
Finally, here is an example of an instruction adorned with all possible modifiers:
189
198
190
199
``` nasm
191
- sub.s.if_lt ! r8, r4, r12
200
+ sub.s.lt ! r8, r4, r12
192
201
```
193
202
194
203
Here is a breakdown of modifiers:
195
204
196
- - ` .if_lt ` : is only executed if the LT flag is set
205
+ - ` .lt ` : is only executed if the LT flag is set
197
206
- ` .s ` : computes ` r4 - r8 ` instead of ` r8 - r4 `
198
207
- ` ! ` : sets flags
199
208
@@ -221,8 +230,8 @@ Each call gets its own stack, heap, code memories, and allocated gas.
221
230
222
231
It is impossible to allocate more than 63/64 of the currently available gas to a far call.
223
232
224
- Calls can revert or panic (on executing an illegal instruction for example), which undoes all the changes to storage and
225
- events emitted during the call, and burns all remaining gas allocated to this call .
233
+ Calls can revert or panic (on executing an illegal instruction for example), which undoes all the changes to storage, transient storage and
234
+ events emitted during the call, and returns unspent gas to the caller .
226
235
227
236
Suppose we far called a contract $C$. After the execution of $C$, the register ` r1 ` holds a pointer to the return value,
228
237
allowing a read-only access to a fragment of $C$’s heap. Alternatively, ` r1 ` can hold a pointer to the heap of some
@@ -249,7 +258,7 @@ There are three types of situations where control returns to the caller:
249
258
- Return: a normal way of returning to the caller when no errors occurred. The instruction is ` ret ` .
250
259
- Revert: a recoverable error happened. Unspent gas is returned to the caller, which will execute the exception handler.
251
260
The instruction is ` revert ` .
252
- - Panic: an irrecoverable error happened. Same as revert, but unspent gas is burned . The instruction is ` ret.panic ` .
261
+ - Panic: an irrecoverable error happened. Same as revert, but ` LT ` flag is set . The instruction is ` ret.panic ` .
253
262
254
263
### Near calls
255
264
@@ -284,11 +293,8 @@ Additional two arguments:
284
293
As we see, zkEVM supports allocating ergs not only for far calls, but also for near calls. Passing zero will allocate
285
294
all available gas. Unlike in far calls, near calls do not limit the amount of gas passed to 63/64 of available gas.
286
295
287
- - On revert, unspent gas of the function is ** returned**
288
- - On panic, unspent gas of the function is ** lost**
289
-
290
296
All near calls inside the contract are sharing the same memory space (heap, stack), and do not roll back the changes to
291
- this memory if they fail. They do, however, roll back the changes to storage and events.
297
+ this memory if they fail. They do, however, roll back the changes to storage, transient storage and events.
292
298
293
299
Near calls cannot be used from Solidity to their full extent. Compiler generates them, but makes sure that if functions
294
300
revert or panic, the whole contract reverts of panics. Explicit exception handlers and allocating just a portion of
@@ -486,7 +492,7 @@ Only special instructions can manipulate fat pointers without automatically clea
486
492
pass to another contract B up the call chain, again without copying data.
487
493
- ` ptr.pack ` allows putting data in the top 128 bit of the pointer value without clearing the pointer tag.
488
494
489
- Doing e.g. ` add r1, 0, r2 ` on a pointer in ` r1 ` clears its tag, and it is now considered as a raw integer.
495
+ Doing e.g. ` add r1, 0, r1 ` on a pointer in ` r1 ` clears its tag, and it is now considered as a raw integer.
490
496
491
497
Instructions ` ld ` and ` [ld.inc](http://ld.inc) ` (without indices 1 or 2) allow loading data by fat pointers, possibly
492
498
incrementing the pointer. It is impossible to write by a fat pointer.
0 commit comments