Ton

Форк
0
624 строки · 34.6 Кб
1
;; Standard library for funC
2
;;
3

4
{-
5
  # Tuple manipulation primitives
6
  The names and the types are mostly self-explaining.
7
  See [polymorhism with forall](https://ton.org/docs/#/func/functions?id=polymorphism-with-forall)
8
  for more info on the polymorphic functions.
9

10
  Note that currently values of atomic type `tuple` can't be cast to composite tuple type (e.g. `[int, cell]`)
11
  and vise versa.
12
-}
13

14
{-
15
  # Lisp-style lists
16

17
  Lists can be represented as nested 2-elements tuples.
18
  Empty list is conventionally represented as TVM `null` value (it can be obtained by calling [null()]).
19
  For example, tuple `(1, (2, (3, null)))` represents list `[1, 2, 3]`. Elements of a list can be of different types.
20
-}
21

22
;;; Adds an element to the beginning of lisp-style list.
23
forall X -> tuple cons(X head, tuple tail) asm "CONS";
24

25
;;; Extracts the head and the tail of lisp-style list.
26
forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
27

28
;;; Extracts the tail and the head of lisp-style list.
29
forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
30

31
;;; Returns the head of lisp-style list.
32
forall X -> X car(tuple list) asm "CAR";
33

34
;;; Returns the tail of lisp-style list.
35
tuple cdr(tuple list) asm "CDR";
36

37
;;; Creates tuple with zero elements.
38
tuple empty_tuple() asm "NIL";
39

40
;;; Appends a value `x` to a `Tuple t = (x1, ..., xn)`, but only if the resulting `Tuple t' = (x1, ..., xn, x)`
41
;;; is of length at most 255. Otherwise throws a type check exception.
42
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
43
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
44

45
;;; Creates a tuple of length one with given argument as element.
46
forall X -> [X] single(X x) asm "SINGLE";
47

48
;;; Unpacks a tuple of length one
49
forall X -> X unsingle([X] t) asm "UNSINGLE";
50

51
;;; Creates a tuple of length two with given arguments as elements.
52
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
53

54
;;; Unpacks a tuple of length two
55
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
56

57
;;; Creates a tuple of length three with given arguments as elements.
58
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
59

60
;;; Unpacks a tuple of length three
61
forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
62

63
;;; Creates a tuple of length four with given arguments as elements.
64
forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
65

66
;;; Unpacks a tuple of length four
67
forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
68

69
;;; Returns the first element of a tuple (with unknown element types).
70
forall X -> X first(tuple t) asm "FIRST";
71

72
;;; Returns the second element of a tuple (with unknown element types).
73
forall X -> X second(tuple t) asm "SECOND";
74

75
;;; Returns the third element of a tuple (with unknown element types).
76
forall X -> X third(tuple t) asm "THIRD";
77

78
;;; Returns the fourth element of a tuple (with unknown element types).
79
forall X -> X fourth(tuple t) asm "3 INDEX";
80

81
;;; Returns the first element of a pair tuple.
82
forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
83

84
;;; Returns the second element of a pair tuple.
85
forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
86

87
;;; Returns the first element of a triple tuple.
88
forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
89

90
;;; Returns the second element of a triple tuple.
91
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
92

93
;;; Returns the third element of a triple tuple.
94
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
95

96

97
;;; Push null element (casted to given type)
98
;;; By the TVM type `Null` FunC represents absence of a value of some atomic type.
99
;;; So `null` can actually have any atomic type.
100
forall X -> X null() asm "PUSHNULL";
101

102
;;; Moves a variable [x] to the top of the stack
103
forall X -> (X, ()) ~impure_touch(X x) impure asm "NOP";
104

105

106

107
;;; Returns the current Unix time as an Integer
108
int now() asm "NOW";
109

110
;;; Returns the internal address of the current smart contract as a Slice with a `MsgAddressInt`.
111
;;; If necessary, it can be parsed further using primitives such as [parse_std_addr].
112
slice my_address() asm "MYADDR";
113

114
;;; Returns the balance of the smart contract as a tuple consisting of an int
115
;;; (balance in nanotoncoins) and a `cell`
116
;;; (a dictionary with 32-bit keys representing the balance of "extra currencies")
117
;;; at the start of Computation Phase.
118
;;; Note that RAW primitives such as [send_raw_message] do not update this field.
119
[int, cell] get_balance() asm "BALANCE";
120

121
;;; Returns the logical time of the current transaction.
122
int cur_lt() asm "LTIME";
123

124
;;; Returns the starting logical time of the current block.
125
int block_lt() asm "BLOCKLT";
126

127
;;; Computes the representation hash of a `cell` [c] and returns it as a 256-bit unsigned integer `x`.
128
;;; Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.
129
int cell_hash(cell c) asm "HASHCU";
130

131
;;; Computes the hash of a `slice s` and returns it as a 256-bit unsigned integer `x`.
132
;;; The result is the same as if an ordinary cell containing only data and references from `s` had been created
133
;;; and its hash computed by [cell_hash].
134
int slice_hash(slice s) asm "HASHSU";
135

136
;;; Computes sha256 of the data bits of `slice` [s]. If the bit length of `s` is not divisible by eight,
137
;;; throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer `x`.
138
int string_hash(slice s) asm "SHA256U";
139

140
{-
141
  # Signature checks
142
-}
143

144
;;; Checks the Ed25519-`signature` of a `hash` (a 256-bit unsigned integer, usually computed as the hash of some data)
145
;;; using [public_key] (also represented by a 256-bit unsigned integer).
146
;;; The signature must contain at least 512 data bits; only the first 512 bits are used.
147
;;; The result is `−1` if the signature is valid, `0` otherwise.
148
;;; Note that `CHKSIGNU` creates a 256-bit slice with the hash and calls `CHKSIGNS`.
149
;;; That is, if [hash] is computed as the hash of some data, these data are hashed twice,
150
;;; the second hashing occurring inside `CHKSIGNS`.
151
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
152

153
;;; Checks whether [signature] is a valid Ed25519-signature of the data portion of `slice data` using `public_key`,
154
;;; similarly to [check_signature].
155
;;; If the bit length of [data] is not divisible by eight, throws a cell underflow exception.
156
;;; The verification of Ed25519 signatures is the standard one,
157
;;; with sha256 used to reduce [data] to the 256-bit number that is actually signed.
158
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
159

160
{---
161
  # Computation of boc size
162
  The primitives below may be useful for computing storage fees of user-provided data.
163
-}
164

165
;;; Returns `(x, y, z, -1)` or `(null, null, null, 0)`.
166
;;; Recursively computes the count of distinct cells `x`, data bits `y`, and cell references `z`
167
;;; in the DAG rooted at `cell` [c], effectively returning the total storage used by this DAG taking into account
168
;;; the identification of equal cells.
169
;;; The values of `x`, `y`, and `z` are computed by a depth-first traversal of this DAG,
170
;;; with a hash table of visited cell hashes used to prevent visits of already-visited cells.
171
;;; The total count of visited cells `x` cannot exceed non-negative [max_cells];
172
;;; otherwise the computation is aborted before visiting the `(max_cells + 1)`-st cell and
173
;;; a zero flag is returned to indicate failure. If [c] is `null`, returns `x = y = z = 0`.
174
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
175

176
;;; Similar to [compute_data_size?], but accepting a `slice` [s] instead of a `cell`.
177
;;; The returned value of `x` does not take into account the cell that contains the `slice` [s] itself;
178
;;; however, the data bits and the cell references of [s] are accounted for in `y` and `z`.
179
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
180

181
;;; A non-quiet version of [compute_data_size?] that throws a cell overflow exception (`8`) on failure.
182
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
183

184
;;; A non-quiet version of [slice_compute_data_size?] that throws a cell overflow exception (8) on failure.
185
(int, int, int, int) slice_compute_data_size?(cell c, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
186

187
;;; Throws an exception with exit_code excno if cond is not 0 (commented since implemented in compilator)
188
;; () throw_if(int excno, int cond) impure asm "THROWARGIF";
189

190
{--
191
  # Debug primitives
192
  Only works for local TVM execution with debug level verbosity
193
-}
194
;;; Dumps the stack (at most the top 255 values) and shows the total stack depth.
195
() dump_stack() impure asm "DUMPSTK";
196

197
{-
198
  # Persistent storage save and load
199
-}
200

201
;;; Returns the persistent contract storage cell. It can be parsed or modified with slice and builder primitives later.
202
cell get_data() asm "c4 PUSH";
203

204
;;; Sets `cell` [c] as persistent contract data. You can update persistent contract storage with this primitive.
205
() set_data(cell c) impure asm "c4 POP";
206

207
{-
208
  # Continuation primitives
209
-}
210
;;; Usually `c3` has a continuation initialized by the whole code of the contract. It is used for function calls.
211
;;; The primitive returns the current value of `c3`.
212
cont get_c3() impure asm "c3 PUSH";
213

214
;;; Updates the current value of `c3`. Usually, it is used for updating smart contract code in run-time.
215
;;; Note that after execution of this primitive the current code
216
;;; (and the stack of recursive function calls) won't change,
217
;;; but any other function call will use a function from the new code.
218
() set_c3(cont c) impure asm "c3 POP";
219

220
;;; Transforms a `slice` [s] into a simple ordinary continuation `c`, with `c.code = s` and an empty stack and savelist.
221
cont bless(slice s) impure asm "BLESS";
222

223
{---
224
  # Gas related primitives
225
-}
226

227
;;; Sets current gas limit `gl` to its maximal allowed value `gm`, and resets the gas credit `gc` to zero,
228
;;; decreasing the value of `gr` by `gc` in the process.
229
;;; In other words, the current smart contract agrees to buy some gas to finish the current transaction.
230
;;; This action is required to process external messages, which bring no value (hence no gas) with themselves.
231
;;;
232
;;; For more details check [accept_message effects](https://ton.org/docs/#/smart-contracts/accept).
233
() accept_message() impure asm "ACCEPT";
234

235
;;; Sets current gas limit `gl` to the minimum of limit and `gm`, and resets the gas credit `gc` to zero.
236
;;; If the gas consumed so far (including the present instruction) exceeds the resulting value of `gl`,
237
;;; an (unhandled) out of gas exception is thrown before setting new gas limits.
238
;;; Notice that [set_gas_limit] with an argument `limit ≥ 2^63 − 1` is equivalent to [accept_message].
239
() set_gas_limit(int limit) impure asm "SETGASLIMIT";
240

241
;;; Commits the current state of registers `c4` (“persistent data”) and `c5` (“actions”)
242
;;; so that the current execution is considered “successful” with the saved values even if an exception
243
;;; in Computation Phase is thrown later.
244
() commit() impure asm "COMMIT";
245

246
;;; Not implemented
247
;;() buy_gas(int gram) impure asm "BUYGAS";
248

249
;;; Computes the amount of gas that can be bought for `amount` nanoTONs,
250
;;; and sets `gl` accordingly in the same way as [set_gas_limit].
251
() buy_gas(int amount) impure asm "BUYGAS";
252

253
;;; Computes the minimum of two integers [x] and [y].
254
int min(int x, int y) asm "MIN";
255

256
;;; Computes the maximum of two integers [x] and [y].
257
int max(int x, int y) asm "MAX";
258

259
;;; Sorts two integers.
260
(int, int) minmax(int x, int y) asm "MINMAX";
261

262
;;; Computes the absolute value of an integer [x].
263
int abs(int x) asm "ABS";
264

265
{-
266
  # Slice primitives
267

268
  It is said that a primitive _loads_ some data,
269
  if it returns the data and the remainder of the slice
270
  (so it can also be used as [modifying method](https://ton.org/docs/#/func/statements?id=modifying-methods)).
271

272
  It is said that a primitive _preloads_ some data, if it returns only the data
273
  (it can be used as [non-modifying method](https://ton.org/docs/#/func/statements?id=non-modifying-methods)).
274

275
  Unless otherwise stated, loading and preloading primitives read the data from a prefix of the slice.
276
-}
277

278

279
;;; Converts a `cell` [c] into a `slice`. Notice that [c] must be either an ordinary cell,
280
;;; or an exotic cell (see [TVM.pdf](https://ton-blockchain.github.io/docs/tvm.pdf), 3.1.2)
281
;;; which is automatically loaded to yield an ordinary cell `c'`, converted into a `slice` afterwards.
282
slice begin_parse(cell c) asm "CTOS";
283

284
;;; Checks if [s] is empty. If not, throws an exception.
285
() end_parse(slice s) impure asm "ENDS";
286

287
;;; Loads the first reference from the slice.
288
(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF";
289

290
;;; Preloads the first reference from the slice.
291
cell preload_ref(slice s) asm "PLDREF";
292

293
  {- Functions below are commented because are implemented on compilator level for optimisation -}
294

295
;;; Loads a signed [len]-bit integer from a slice [s].
296
;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX";
297

298
;;; Loads an unsigned [len]-bit integer from a slice [s].
299
;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX";
300

301
;;; Preloads a signed [len]-bit integer from a slice [s].
302
;; int preload_int(slice s, int len) asm "PLDIX";
303

304
;;; Preloads an unsigned [len]-bit integer from a slice [s].
305
;; int preload_uint(slice s, int len) asm "PLDUX";
306

307
;;; Loads the first `0 ≤ len ≤ 1023` bits from slice [s] into a separate `slice s''`.
308
;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX";
309

310
;;; Preloads the first `0 ≤ len ≤ 1023` bits from slice [s] into a separate `slice s''`.
311
;; slice preload_bits(slice s, int len) asm "PLDSLICEX";
312

313
;;; Loads serialized amount of TonCoins (any unsigned integer up to `2^128 - 1`).
314
(slice, int) load_grams(slice s) asm( -> 1 0) "LDGRAMS";
315
(slice, int) load_coins(slice s) asm( -> 1 0) "LDGRAMS";
316

317
;;; Returns all but the first `0 ≤ len ≤ 1023` bits of `slice` [s].
318
slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
319
(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST";
320

321
;;; Returns the first `0 ≤ len ≤ 1023` bits of `slice` [s].
322
slice first_bits(slice s, int len) asm "SDCUTFIRST";
323

324
;;; Returns all but the last `0 ≤ len ≤ 1023` bits of `slice` [s].
325
slice skip_last_bits(slice s, int len) asm "SDSKIPLAST";
326
(slice, ()) ~skip_last_bits(slice s, int len) asm "SDSKIPLAST";
327

328
;;; Returns the last `0 ≤ len ≤ 1023` bits of `slice` [s].
329
slice slice_last(slice s, int len) asm "SDCUTLAST";
330

331
;;; Loads a dictionary `D` (HashMapE) from `slice` [s].
332
;;; (returns `null` if `nothing` constructor is used).
333
(slice, cell) load_dict(slice s) asm( -> 1 0) "LDDICT";
334

335
;;; Preloads a dictionary `D` from `slice` [s].
336
cell preload_dict(slice s) asm "PLDDICT";
337

338
;;; Loads a dictionary as [load_dict], but returns only the remainder of the slice.
339
slice skip_dict(slice s) asm "SKIPDICT";
340

341
;;; Loads (Maybe ^Cell) from `slice` [s].
342
;;; In other words loads 1 bit and if it is true
343
;;; loads first ref and return it with slice remainder
344
;;; otherwise returns `null` and slice remainder
345
(slice, cell) load_maybe_ref(slice s) asm( -> 1 0) "LDOPTREF";
346

347
;;; Preloads (Maybe ^Cell) from `slice` [s].
348
cell preload_maybe_ref(slice s) asm "PLDOPTREF";
349

350

351
;;; Returns the depth of `cell` [c].
352
;;; If [c] has no references, then return `0`;
353
;;; otherwise the returned value is one plus the maximum of depths of cells referred to from [c].
354
;;; If [c] is a `null` instead of a cell, returns zero.
355
int cell_depth(cell c) asm "CDEPTH";
356

357

358
{-
359
  # Slice size primitives
360
-}
361

362
;;; Returns the number of references in `slice` [s].
363
int slice_refs(slice s) asm "SREFS";
364

365
;;; Returns the number of data bits in `slice` [s].
366
int slice_bits(slice s) asm "SBITS";
367

368
;;; Returns both the number of data bits and the number of references in `slice` [s].
369
(int, int) slice_bits_refs(slice s) asm "SBITREFS";
370

371
;;; Checks whether a `slice` [s] is empty (i.e., contains no bits of data and no cell references).
372
int slice_empty?(slice s) asm "SEMPTY";
373

374
;;; Checks whether `slice` [s] has no bits of data.
375
int slice_data_empty?(slice s) asm "SDEMPTY";
376

377
;;; Checks whether `slice` [s] has no references.
378
int slice_refs_empty?(slice s) asm "SREMPTY";
379

380
;;; Returns the depth of `slice` [s].
381
;;; If [s] has no references, then returns `0`;
382
;;; otherwise the returned value is one plus the maximum of depths of cells referred to from [s].
383
int slice_depth(slice s) asm "SDEPTH";
384

385
{-
386
  # Builder size primitives
387
-}
388

389
;;; Returns the number of cell references already stored in `builder` [b]
390
int builder_refs(builder b) asm "BREFS";
391

392
;;; Returns the number of data bits already stored in `builder` [b].
393
int builder_bits(builder b) asm "BBITS";
394

395
;;; Returns the depth of `builder` [b].
396
;;; If no cell references are stored in [b], then returns 0;
397
;;; otherwise the returned value is one plus the maximum of depths of cells referred to from [b].
398
int builder_depth(builder b) asm "BDEPTH";
399

400
{-
401
  # Builder primitives
402
  It is said that a primitive _stores_ a value `x` into a builder `b`
403
  if it returns a modified version of the builder `b'` with the value `x` stored at the end of it.
404
  It can be used as [non-modifying method](https://ton.org/docs/#/func/statements?id=non-modifying-methods).
405

406
  All the primitives below first check whether there is enough space in the `builder`,
407
  and only then check the range of the value being serialized.
408
-}
409

410
;;; Creates a new empty `builder`.
411
builder begin_cell() asm "NEWC";
412

413
;;; Converts a `builder` into an ordinary `cell`.
414
cell end_cell(builder b) asm "ENDC";
415

416
;;; Stores a reference to `cell` [c] into `builder` [b].
417
builder store_ref(builder b, cell c) asm(c b) "STREF";
418

419
;;; Stores an unsigned [len]-bit integer `x` into `b` for `0 ≤ len ≤ 256`.
420
;; builder store_uint(builder b, int x, int len) asm(x b len) "STUX";
421

422
;;; Stores a signed [len]-bit integer `x` into `b` for` 0 ≤ len ≤ 257`.
423
;; builder store_int(builder b, int x, int len) asm(x b len) "STIX";
424

425

426
;;; Stores `slice` [s] into `builder` [b]
427
builder store_slice(builder b, slice s) asm "STSLICER";
428

429
;;; Stores (serializes) an integer [x] in the range `0..2^128 − 1` into `builder` [b].
430
;;; The serialization of [x] consists of a 4-bit unsigned big-endian integer `l`,
431
;;; which is the smallest integer `l ≥ 0`, such that `x < 2^8l`,
432
;;; followed by an `8l`-bit unsigned big-endian representation of [x].
433
;;; If [x] does not belong to the supported range, a range check exception is thrown.
434
;;;
435
;;; Store amounts of TonCoins to the builder as VarUInteger 16
436
builder store_grams(builder b, int x) asm "STGRAMS";
437
builder store_coins(builder b, int x) asm "STGRAMS";
438

439
;;; Stores dictionary `D` represented by `cell` [c] or `null` into `builder` [b].
440
;;; In other words, stores a `1`-bit and a reference to [c] if [c] is not `null` and `0`-bit otherwise.
441
builder store_dict(builder b, cell c) asm(c b) "STDICT";
442

443
;;; Stores (Maybe ^Cell) to builder:
444
;;; if cell is null store 1 zero bit
445
;;; otherwise store 1 true bit and ref to cell
446
builder store_maybe_ref(builder b, cell c) asm(c b) "STOPTREF";
447

448

449
{-
450
  # Address manipulation primitives
451
  The address manipulation primitives listed below serialize and deserialize values according to the following TL-B scheme:
452
  ```TL-B
453
  addr_none$00 = MsgAddressExt;
454
  addr_extern$01 len:(## 8) external_address:(bits len)
455
               = MsgAddressExt;
456
  anycast_info$_ depth:(#<= 30) { depth >= 1 }
457
    rewrite_pfx:(bits depth) = Anycast;
458
  addr_std$10 anycast:(Maybe Anycast)
459
    workchain_id:int8 address:bits256 = MsgAddressInt;
460
  addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
461
    workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
462
  _ _:MsgAddressInt = MsgAddress;
463
  _ _:MsgAddressExt = MsgAddress;
464

465
  int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
466
    src:MsgAddress dest:MsgAddressInt
467
    value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
468
    created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
469
  ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt
470
    created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
471
  ```
472
  A deserialized `MsgAddress` is represented by a tuple `t` as follows:
473

474
  - `addr_none` is represented by `t = (0)`,
475
    i.e., a tuple containing exactly one integer equal to zero.
476
  - `addr_extern` is represented by `t = (1, s)`,
477
    where slice `s` contains the field `external_address`. In other words, `
478
    t` is a pair (a tuple consisting of two entries), containing an integer equal to one and slice `s`.
479
  - `addr_std` is represented by `t = (2, u, x, s)`,
480
    where `u` is either a `null` (if `anycast` is absent) or a slice `s'` containing `rewrite_pfx` (if anycast is present).
481
    Next, integer `x` is the `workchain_id`, and slice `s` contains the address.
482
  - `addr_var` is represented by `t = (3, u, x, s)`,
483
    where `u`, `x`, and `s` have the same meaning as for `addr_std`.
484
-}
485

486
;;; Loads from slice [s] the only prefix that is a valid `MsgAddress`,
487
;;; and returns both this prefix `s'` and the remainder `s''` of [s] as slices.
488
(slice, slice) load_msg_addr(slice s) asm( -> 1 0) "LDMSGADDR";
489

490
;;; Decomposes slice [s] containing a valid `MsgAddress` into a `tuple t` with separate fields of this `MsgAddress`.
491
;;; If [s] is not a valid `MsgAddress`, a cell deserialization exception is thrown.
492
tuple parse_addr(slice s) asm "PARSEMSGADDR";
493

494
;;; Parses slice [s] containing a valid `MsgAddressInt` (usually a `msg_addr_std`),
495
;;; applies rewriting from the anycast (if present) to the same-length prefix of the address,
496
;;; and returns both the workchain and the 256-bit address as integers.
497
;;; If the address is not 256-bit, or if [s] is not a valid serialization of `MsgAddressInt`,
498
;;; throws a cell deserialization exception.
499
(int, int) parse_std_addr(slice s) asm "REWRITESTDADDR";
500

501
;;; A variant of [parse_std_addr] that returns the (rewritten) address as a slice [s],
502
;;; even if it is not exactly 256 bit long (represented by a `msg_addr_var`).
503
(int, slice) parse_var_addr(slice s) asm "REWRITEVARADDR";
504

505
{-
506
  # Dictionary primitives
507
-}
508

509

510
;;; Sets the value associated with [key_len]-bit key signed index in dictionary [dict] to [value] (cell),
511
;;; and returns the resulting dictionary.
512
cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
513
(cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
514

515
;;; Sets the value associated with [key_len]-bit key unsigned index in dictionary [dict] to [value] (cell),
516
;;; and returns the resulting dictionary.
517
cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
518
(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
519

520
cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF";
521
(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETREF" "NULLSWAPIFNOT";
522
(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETREF" "NULLSWAPIFNOT";
523
(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF";
524
(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF";
525
(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL";
526
(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDEL";
527
(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT";
528
(slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGET" "NULLSWAPIFNOT";
529
(cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
530
(cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
531
(cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
532
(cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
533
cell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
534
(cell, ()) ~udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
535
cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
536
(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
537
cell dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
538
(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
539
(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUADD";
540
(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACE";
541
(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIADD";
542
(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACE";
543
cell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
544
(cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
545
cell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
546
(cell, ()) ~idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
547
cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
548
(cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
549
(cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUADDB";
550
(cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEB";
551
(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIADDB";
552
(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEB";
553
(cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
554
(cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
555
(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
556
(cell, (int, slice, int)) ~idict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
557
(cell, slice, slice, int) dict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
558
(cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
559
(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
560
(cell, (int, slice, int)) ~udict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
561
(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
562
(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
563
(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
564
(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
565
(int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2";
566
(int, slice, int) udict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAX" "NULLSWAPIFNOT2";
567
(int, cell, int) udict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMINREF" "NULLSWAPIFNOT2";
568
(int, cell, int) udict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAXREF" "NULLSWAPIFNOT2";
569
(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2";
570
(int, slice, int) idict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAX" "NULLSWAPIFNOT2";
571
(int, cell, int) idict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMINREF" "NULLSWAPIFNOT2";
572
(int, cell, int) idict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAXREF" "NULLSWAPIFNOT2";
573
(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2";
574
(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2";
575
(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT2";
576
(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2";
577
(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT2";
578
(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2";
579
(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT2";
580
(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2";
581

582
;;; Creates an empty dictionary, which is actually a null value. Equivalent to PUSHNULL
583
cell new_dict() asm "NEWDICT";
584
;;; Checks whether a dictionary is empty. Equivalent to cell_null?.
585
int dict_empty?(cell c) asm "DICTEMPTY";
586

587

588
{- Prefix dictionary primitives -}
589
(slice, slice, slice, int) pfxdict_get?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTGETQ" "NULLSWAPIFNOT2";
590
(cell, int) pfxdict_set?(cell dict, int key_len, slice key, slice value) asm(value key dict key_len) "PFXDICTSET";
591
(cell, int) pfxdict_delete?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTDEL";
592

593
;;; Returns the value of the global configuration parameter with integer index `i` as a `cell` or `null` value.
594
cell config_param(int x) asm "CONFIGOPTPARAM";
595
;;; Checks whether c is a null. Note, that FunC also has polymorphic null? built-in.
596
int cell_null?(cell c) asm "ISNULL";
597

598
;;; Creates an output action which would reserve exactly amount nanotoncoins (if mode = 0), at most amount nanotoncoins (if mode = 2), or all but amount nanotoncoins (if mode = 1 or mode = 3), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying amount nanotoncoins (or b − amount nanotoncoins, where b is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit +2 in mode means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit +8 in mode means `amount <- -amount` before performing any further actions. Bit +4 in mode means that amount is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently, amount must be a non-negative integer, and mode must be in the range 0..15.
599
() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
600
;;; Similar to raw_reserve, but also accepts a dictionary extra_amount (represented by a cell or null) with extra currencies. In this way currencies other than TonCoin can be reserved.
601
() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm "RAWRESERVEX";
602
;;; Sends a raw message contained in msg, which should contain a correctly serialized object Message X, with the only exception that the source address is allowed to have dummy value addr_none (to be automatically replaced with the current smart contract address), and ihr_fee, fwd_fee, created_lt and created_at fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter mode contains the flags. Currently mode = 0 is used for ordinary messages; mode = 128 is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); mode = 64 is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); mode' = mode + 1 means that the sender wants to pay transfer fees separately; mode' = mode + 2 means that any errors arising while processing this message during the action phase should be ignored. Finally, mode' = mode + 32 means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with +128.
603
() send_raw_message(cell msg, int mode) impure asm "SENDRAWMSG";
604
;;; Creates an output action that would change this smart contract code to that given by cell new_code. Notice that this change will take effect only after the successful termination of the current run of the smart contract
605
() set_code(cell new_code) impure asm "SETCODE";
606

607
;;; Generates a new pseudo-random unsigned 256-bit integer x. The algorithm is as follows: if r is the old value of the random seed, considered as a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its sha512(r) is computed; the first 32 bytes of this hash are stored as the new value r' of the random seed, and the remaining 32 bytes are returned as the next random value x.
608
int random() impure asm "RANDU256";
609
;;; Generates a new pseudo-random integer z in the range 0..range−1 (or range..−1, if range < 0). More precisely, an unsigned random value x is generated as in random; then z := x * range / 2^256 is computed.
610
int rand(int range) impure asm "RAND";
611
;;; Returns the current random seed as an unsigned 256-bit Integer.
612
int get_seed() impure asm "RANDSEED";
613
;;; Sets the random seed to unsigned 256-bit seed.
614
() set_seed(int) impure asm "SETRAND";
615
;;; Mixes unsigned 256-bit integer x into the random seed r by setting the random seed to sha256 of the concatenation of two 32-byte strings: the first with the big-endian representation of the old seed r, and the second with the big-endian representation of x.
616
() randomize(int x) impure asm "ADDRAND";
617
;;; Equivalent to randomize(cur_lt());.
618
() randomize_lt() impure asm "LTIME" "ADDRAND";
619

620
;;; Checks whether the data parts of two slices coinside
621
int equal_slice_bits (slice a, slice b) asm "SDEQ";
622

623
;;; Concatenates two builders
624
builder store_builder(builder to, builder from) asm "STBR";
625

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.