diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d00388b5..68fb5bc92 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Docs: `preloadRef` method for the `Slice` type: PR [#1044](https://github.com/tact-lang/tact/pull/1044)
- Docs: added DeDust cookbook: PR [#954](https://github.com/tact-lang/tact/pull/954)
- Docs: described the limit for deeply nested expressions: PR [#1101](https://github.com/tact-lang/tact/pull/1101)
+- New functions in stdlib from `stdlib.fc` and `math.fc`: `Builder.depth`, `Slice.skipLastBits`, `Slice.firstBits`, `Slice.lastBits`, `Slice.depth`, `Cell.computeDataSize`, `Slice.computeDataSize`, `Cell.depth`, `curLt`, `blockLt`, `setGasLimit`, `getSeed`, `setSeed`, `myCode`, `sign`, `divc`, `muldivc`, `mulShiftRight`, `mulShiftRightRound`, `mulShiftRightCeil`, `sqrt`, `addressNone`: PR [#986](https://github.com/tact-lang/tact/pull/986)
### Changed
diff --git a/cspell.json b/cspell.json
index b48885a05..50852ff42 100644
--- a/cspell.json
+++ b/cspell.json
@@ -73,6 +73,7 @@
"minmax",
"mintable",
"mktemp",
+ "muldivc",
"multiformats",
"nanotons",
"Neovim",
diff --git a/docs/cspell.json b/docs/cspell.json
index 623040802..c1000d52b 100644
--- a/docs/cspell.json
+++ b/docs/cspell.json
@@ -160,6 +160,7 @@
"minmax",
"mintable",
"mktemp",
+ "muldivc",
"multiformats",
"nanotons",
"nanotons",
diff --git a/docs/src/content/docs/book/exit-codes.mdx b/docs/src/content/docs/book/exit-codes.mdx
index bfb6486b7..57664463a 100644
--- a/docs/src/content/docs/book/exit-codes.mdx
+++ b/docs/src/content/docs/book/exit-codes.mdx
@@ -183,7 +183,7 @@ contract ItsSoOver {
### 4: Integer overflow {#4}
-If the value in calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, or there's an attempt to [divide](/book/operators#binary-divide) or [modulo](/book/operators#binary-modulo) by zero, an error with exit code $4$ is thrown: `Integer overflow`.
+If the [value in calculation](/book/integers#operations) goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, or there's an attempt to [divide](/book/operators#binary-divide) or [modulo](/book/operators#binary-modulo) by zero, an error with exit code $4$ is thrown: `Integer overflow`.
```tact
let x = -pow(2, 255) - pow(2, 255); // -2^{256}
@@ -213,9 +213,9 @@ try {
// division (/) by a negative number or modulo (%) by zero
```
-### 5: Integer out of range {#5}
+### 5: Integer out of expected range {#5}
-Range check error — some integer is out of its expected range. I.e. any attempt to store an unexpected amount of data or specify an out-of-bounds value throws an error with exit code $5$: `Integer out of range`.
+Range check error — [some integer](/book/integers#operations) is out of its expected range. I.e. any attempt to store an unexpected amount of data or specify an out-of-bounds value throws an error with exit code $5$: `Integer out of expected range`.
Examples of specifying an out-of-bounds value:
@@ -521,7 +521,7 @@ If the configuration is absent, default values are:
* `max_msg_bits` is equal to $2^{21}$ — maximum message size in bits.
* `max_msg_cells` is equal to $2^{13}$ — maximum number of [cells][cell] a message can occupy.
* `max_library_cells` is equal to $1000$ — maximum number of [cells][cell] that can be used as [library reference cells](/book/cells#cells-kinds).
-* `max_vm_data_depth` is equal to $2^{9}$ — maximum [cells][cell] depth in messages and account state.
+* `max_vm_data_depth` is equal to $2^{9}$ — maximum [cells][cell] [depth](/book/cells#cells-representation) in messages and account state.
* `ext_msg_limits.max_size` is equal to $65535$ — maximum external message size in bits.
* `ext_msg_limits.max_depth` is equal to $2^{9}$ — maximum external message [depth](/book/cells#cells-representation).
* `max_acc_state_cells` is equal to $2^{16}$ — maximum number of [cells][cell] that an account state can occupy.
diff --git a/docs/src/content/docs/ref/core-advanced.mdx b/docs/src/content/docs/ref/core-advanced.mdx
index 25dba26cd..4787e5d0a 100644
--- a/docs/src/content/docs/ref/core-advanced.mdx
+++ b/docs/src/content/docs/ref/core-advanced.mdx
@@ -31,7 +31,7 @@ let gas: Int = gasConsumed();
:::note[Useful links:]
- [Gas in TON Docs](https://docs.ton.org/v3/documentation/smart-contracts/transaction-fees/fees#gas)
+ [Gas in TON Docs][gas]
:::
@@ -68,7 +68,7 @@ fun getStorageFee(cells: Int, bits: Int, seconds: Int, isMasterchain: Bool): Int
Calculates and returns the [storage fee][storage-fee] in [nanoToncoins][nanotoncoin] [`Int{:tact}`][int] for storing a contract with a given number of `cells` and `bits` for a number of `seconds`. Uses the prices of the [masterchain][masterchain] if `isMasterchain` is `true{:tact}`, otherwise the prices of the [basechain][basechain]. The current prices are obtained from the [config param 18 of TON Blockchain](https://docs.ton.org/develop/howto/blockchain-configs#param-18).
-Note, that the values of `cells` and `bits` are taken modulo their maximum values plus $1$. That is, specifying values higher than those listed in [account state limits (`max_acc_state_cells` and `max_acc_state_bits`)](/book/exit-codes#50) will have the same result as with specifying the exact limits. In addition, make sure you take into account the [deduplication of cells with the same hash][deduplication].
+Note, that specifying values of `cells` and `bits` higher than their maximum values listed in [account state limits (`max_acc_state_cells` and `max_acc_state_bits`)](/book/exit-codes#50) will have the same result as with specifying the exact limits. In addition, make sure you take into account the [deduplication of cells with the same hash][deduplication].
Attempts to specify negative number of `cells`, `bits` or `seconds` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
@@ -189,7 +189,7 @@ Calculates and returns the [forward fee][forward-fee] in [nanoToncoins][nanotonc
If both the source and the destination addresses are in the [basechain][basechain], then specify `isMasterchain` as `false{:tact}`. Otherwise, specify `true{:tact}`.
-Note, that the values of `cells` and `bits` are taken modulo their maximum values plus $1$. That is, specifying values higher than those listed in [account state limits (`max_msg_cells` and `max_msg_bits`)](/book/exit-codes#50) will have the same result as with specifying the exact limits.
+Note, that specifying values of `cells` and `bits` higher than their maximum values listed in [account state limits (`max_msg_cells` and `max_msg_bits`)](/book/exit-codes#50) will have the same result as with specifying the exact limits.
However, regardless of the values of `cells` and `bits`, this function always adds the minimum price based on the value of [`lump_price`][param-24-25]. See the example for [`getSimpleForwardFee(){:tact}`](#getsimpleforwardfee) to derive it. In addition, make sure you take into account the [deduplication of cells with the same hash][deduplication], since for example the root cell and its data bits don't count towards the forward fee and are covered by the [`lump_price`][param-24-25].
@@ -276,31 +276,27 @@ let origFee: Int = getOriginalFwdFee(fee, false);
:::
-## getConfigParam
+## setGasLimit
+
+
```tact
-fun getConfigParam(id: Int): Cell?;
+fun setGasLimit(limit: Int);
```
-Loads a [configuration parameter](https://docs.ton.org/develop/howto/blockchain-configs) of TON Blockchain by its `id` number.
+Sets the [`gas_limit`][param-20-21] to the [`Int{:tact}`][int] `limit` and resets the [`gas_credit`][param-20-21] to $0$. Note, that specifying the `limit` higher than the maximum allowed value of $2^{63} - 1$ will have the same result as with specifying that exact maximum or calling [`acceptMessage(){:tact}`](#acceptmessage).
-Usage examples:
+Attempts to specify a negative or insufficient value of `limit` will cause an exception with [exit code -14](/book/exit-codes#-14): `Out of gas error`.
-```tact
-// Parameter 0, address of a special smart contract that stores the blockchain's configuration
-let configAddrAsCell: Cell = getConfigParam(0)!!;
+Usage example:
-// Parameter 18, configuration for determining the prices for data storage
-let dataStorageFeeConfig: Cell = getConfigParam(18)!!;
+```tact
+setGasLimit(42000);
```
:::note
- Standard library [`@stdlib/config`](/ref/stdlib-config) provides two related helper functions:\
- [`getConfigAddress(){:tact}`](/ref/stdlib-config#getconfigaddress) for retrieving config [`Address{:tact}`][p]\
- [`getElectorAddress(){:tact}`](/ref/stdlib-config#getconfigaddress) for retrieving elector [`Address{:tact}`][p]
-
- Read more about other parameters: [Config Parameters in TON Docs](https://docs.ton.org/develop/howto/blockchain-configs).
+ For more details, see: [Accept Message Effects in TON Docs](https://docs.ton.org/develop/smart-contracts/guidelines/accept).
:::
@@ -310,7 +306,7 @@ let dataStorageFeeConfig: Cell = getConfigParam(18)!!;
fun acceptMessage();
```
-Agrees to buy some gas to finish the current transaction. This action is required to process external messages, which bring no value (hence no gas) with themselves.
+Agrees to buy some [gas][gas] to finish the current transaction by setting the [`gas_limit`][param-20-21] to its maximum allowed value of $2^{63} - 1$ and resetting the [`gas_credit`][param-20-21] to $0$. This action is required to process external messages, which bring no value (hence no gas) with themselves.
Usage example:
@@ -342,7 +338,7 @@ contract Timeout {
fun commit();
```
-Commits the current state of [registers](https://docs.ton.org/learn/tvm-instructions/tvm-overview#control-registers) `c4` ("persistent data") and `c5` ("actions"), so that the current execution is considered "successful" with the saved values even if an exception in compute phase is thrown later.
+Commits the current state of [registers][registers] `c4` ("persistent data") and `c5` ("actions"), so that the current execution is considered "successful" with the saved values even if an exception in compute phase is thrown later.
Usage example:
@@ -351,6 +347,146 @@ commit(); // now, transaction is considered "successful"
throw(42); // and this won't fail it
```
+## myCode
+
+
+
+```tact
+fun myCode(): Cell;
+```
+
+Returns the smart contract code [`Cell{:tact}`][cell] obtained from the `c7` [register][registers].
+
+Usage example:
+
+```tact
+let code: Cell = myCode();
+```
+
+## getConfigParam
+
+```tact
+fun getConfigParam(id: Int): Cell?;
+```
+
+Loads a [configuration parameter](https://docs.ton.org/develop/howto/blockchain-configs) of TON Blockchain by its `id` number.
+
+Usage examples:
+
+```tact
+// Parameter 0, address of a special smart contract that stores the blockchain's configuration
+let configAddrAsCell: Cell = getConfigParam(0)!!;
+
+// Parameter 18, configuration for determining the prices for data storage
+let dataStorageFeeConfig: Cell = getConfigParam(18)!!;
+```
+
+:::note
+
+ Standard library [`@stdlib/config`](/ref/stdlib-config) provides two related helper functions:\
+ [`getConfigAddress(){:tact}`](/ref/stdlib-config#getconfigaddress) for retrieving config [`Address{:tact}`][p]\
+ [`getElectorAddress(){:tact}`](/ref/stdlib-config#getconfigaddress) for retrieving elector [`Address{:tact}`][p]
+
+ Read more about other parameters: [Config Parameters in TON Docs](https://docs.ton.org/develop/howto/blockchain-configs).
+
+:::
+
+## getSeed
+
+
+
+```tact
+fun getSeed(): Int;
+```
+
+Generates and returns an unsigned $256$-bit [`Int{:tact}`][int] [seed][seed] for the random number generator. The resulting seed is commonly used with the [`setSeed(){:tact}`](#setseed) and [`nativeRandomize(){:tact}`](#nativerandomize) functions.
+
+Usage example:
+
+```tact
+let seed: Int = getSeed();
+setSeed(seed); // from now on the results of pseudorandom number generator
+ // are completely determined by the seed, which can be handy in tests,
+ // but must not be used in production code!
+```
+
+:::note[Useful links:]
+
+ [Random seed in Wikipedia][seed]\
+ [`setSeed(){:tact}`](#setseed)\
+ [`nativeRandomize(){:tact}`](#nativerandomize)
+
+:::
+
+## setSeed
+
+
+
+```tact
+fun setSeed(seed: Int);
+```
+
+Sets the [seed][seed] of the random number generator to the unsigned $256$-bit [`Int{:tact}`][int] `seed` which can be obtained with the [`getSeed(){:tact}`](#getseed) function.
+
+Attempts to specify a negative value of `seed` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Usage example:
+
+```tact
+let seed: Int = getSeed();
+setSeed(seed); // from now on the results of pseudorandom number generator
+ // are completely determined by the seed, which can be handy in tests,
+ // but must not be used in production code!
+```
+
+:::note[Useful links:]
+
+ [Random seed in Wikipedia][seed]\
+ [`getSeed(){:tact}`](#getseed)
+
+:::
+
+## curLt
+
+
+
+```tact
+fun curLt(): Int;
+```
+
+Returns the [`Int{:tact}`][int] value of the [logical time][lt] of the current transaction.
+
+Usage example:
+
+```tact
+let lt: Int = curLt();
+nativeRandomize(lt); // equivalent to calling nativeRandomizeLt()
+```
+
+:::note[Useful links:]
+
+ [Random seed in Wikipedia][seed]\
+ [`nativeRandomize{:tact}`](#nativerandomize)\
+ [`nativeRandomizeLt{:tact}`](#nativerandomizelt)
+
+:::
+
+## blockLt
+
+
+
+```tact
+fun blockLt(): Int;
+```
+
+Returns the [`Int{:tact}`][int] value of the [starting logical time][lt] of the current block.
+
+Usage example:
+
+```tact
+let time: Int = blockLt();
+```
+
## nativePrepareRandom
```tact
@@ -372,22 +508,31 @@ nativePrepareRandom(); // prepare the RNG
fun nativeRandomize(x: Int);
```
-Randomizes the pseudo-random number generator with the specified seed `x`.
+Randomizes the pseudorandom number generator with the specified unsigned $256$-bit [`Int{:tact}`][int] `x` by mixing it with the current [seed][seed]. The new seed is the unsigned $256$-bit [`Int{:tact}`][int] value of the [SHA-256][sha-2] hash of concatenated old seed and `x` in their $32$-byte strings [big-endian](https://en.wikipedia.org/wiki/Endianness) representation.
+
+Attempts to specify a negative value of `x` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
Usage example:
```tact
-nativeRandomize(); // now, random numbers are less predictable
-let idk: Int = randomInt(); // ???, it's random!
+nativeRandomize(42); // now, random numbers are less predictable
+let idk: Int = randomInt(); // ???, it's random,
+ // but the seed was adjusted deterministically!
```
+:::note[Useful links:]
+
+ [Random seed in Wikipedia][seed]
+
+:::
+
## nativeRandomizeLt
```tact
fun nativeRandomizeLt();
```
-Randomizes the random number generator with the current [logical time](https://docs.ton.org/develop/smart-contracts/guidelines/message-delivery-guarantees#what-is-a-logical-time).
+Randomizes the random number generator with the [logical time][lt] of the current transaction. Equivalent to calling `nativeRandomize(curLt()){:tact}`.
Usage example:
@@ -398,6 +543,14 @@ nativeRandomizeLt(); // now, random numbers are unpredictable for users,
let idk: Int = randomInt(); // ???, it's random!
```
+:::note[Useful links:]
+
+ [Random seed in Wikipedia][seed]\
+ [`nativeRandomize{:tact}`](#nativerandomize)\
+ [`curLt(){:tact}`](#curlt)
+
+:::
+
## nativeRandom
```tact
@@ -579,6 +732,7 @@ parsedVarAddr.address.loadUint(123); // 345
[p]: /book/types#primitive-types
[bool]: /book/types#booleans
[int]: /book/integers
+[cell]: /book/cells#cells
[slice]: /book/cells#slices
[s]: /book/structs-and-messages#structs
[masterchain]: /book/masterchain
@@ -588,6 +742,7 @@ parsedVarAddr.address.loadUint(123); // 345
[tvm]: https://docs.ton.org/learn/tvm-instructions/tvm-overview
[basechain]: https://docs.ton.org/v3/concepts/ton-blockchain/smart-contract-addresses#address-components
[deduplication]: https://docs.ton.org/v3/documentation/data-formats/tlb/library-cells
+[registers]: https://docs.ton.org/learn/tvm-instructions/tvm-overview#control-registers
[storage-fee]: https://docs.ton.org/v3/documentation/smart-contracts/transaction-fees/fees-low-level#storage-fee
[storage-fee-calc]: https://docs.ton.org/v3/guidelines/smart-contracts/fee-calculation#storage-fee
@@ -600,3 +755,7 @@ parsedVarAddr.address.loadUint(123); // 345
[forward-fee]: https://docs.ton.org/v3/documentation/smart-contracts/transaction-fees/forward-fees
[forward-fee-calc]: https://docs.ton.org/v3/guidelines/smart-contracts/fee-calculation#forward-fee
[param-24-25]: https://docs.ton.org/v3/documentation/network/configs/blockchain-configs#param-24-and-25
+
+[lt]: https://docs.ton.org/v3/documentation/smart-contracts/message-management/messages-and-transactions#what-is-a-logical-time
+[seed]: https://en.wikipedia.org/wiki/Random_seed
+[sha-2]: https://en.wikipedia.org/wiki/SHA-2#Hash_standard
diff --git a/docs/src/content/docs/ref/core-cells.mdx b/docs/src/content/docs/ref/core-cells.mdx
index 770130032..78bb4b6e7 100644
--- a/docs/src/content/docs/ref/core-cells.mdx
+++ b/docs/src/content/docs/ref/core-cells.mdx
@@ -84,6 +84,64 @@ let c: Cell = emptyCell();
let fizz: Slice = c.beginParse();
```
+## Cell.depth
+
+
+
+```tact
+extends fun depth(self: Cell): Int;
+```
+
+Extension function for the [`Cell{:tact}`][cell].
+
+Computes and returns the [`Int{:tact}`][int] [depth][std-repr] of the [`Cell{:tact}`][cell]. Produces $0$ if the [`Cell{:tact}`][cell] has no references, otherwise $1$ plus the maximum of the depths of the referenced cells.
+
+Usage example:
+
+```tact
+let c: Cell = beginCell().storeInt(42, 7).endCell();
+let depth: Int = c.depth;
+```
+
+## Cell.computeDataSize
+
+
+
+```tact
+extends fun computeDataSize(self: Cell, maxCells: Int): DataSize;
+```
+
+Extension function for the [`Cell{:tact}`][cell].
+
+Computes and returns the number of distinct cells, bits and refs in the [`Cell{:tact}`][tact] by using a [depth-first search (DFS)][dfs] algorithm, recursively traversing each referenced cell. This function is computationally expensive and can consume a lot of [gas][gas].
+
+The results are packed into a `DataSize{:tact}` [Struct][struct] consisting of:
+
+Field | Type | Description
+:------ | :------------------ | :----------
+`cells` | [`Int{:tact}`][int] | The total number of nested cells, including the starting one
+`bits` | [`Int{:tact}`][int] | The total number of bits in all nested cells, including the starting one
+`refs` | [`Int{:tact}`][int] | The total number of refs in all nested cells, including the starting one
+
+If the specified `maxCells` value isn't enough to traverse all cells including the starting one, an exception with [exit code 8](/book/exit-codes#8) is thrown: `Cell overflow`.
+
+Attempts to specify a negative value of `maxCells` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Usage example:
+
+```tact
+let c: Cell = beginCell().storeInt(42, 7).storeRef(emptyCell()).endCell();
+try {
+ let dataSize: DataSize = c.computeDataSize(2);
+ dataSize.cells; // 2
+ dataSize.bits; // 7
+ dataSize.refs; // 1
+} catch (exitCode) {
+ // if maxCells was insufficient to traverse the cell
+ // and all of its references, the exitCode here would be 8
+}
+```
+
## Cell.hash
```tact
@@ -367,6 +425,25 @@ let b: Builder = beginCell();
let fizz: Int = b.bits(); // 0
```
+## Builder.depth
+
+
+
+```tact
+extends fun depth(self: Builder): Int;
+```
+
+Extension function for the [`Builder{:tact}`][builder].
+
+Computes and returns the [`Int{:tact}`][int] [depth][std-repr] of the [`Builder{:tact}`][builder]. Produces $0$ if the [`Builder{:tact}`][builder] has no references stored so far, otherwise $1$ plus the maximum of the depths of the referenced cells.
+
+Usage example:
+
+```tact
+let b: Builder = beginCell().storeInt(42, 7);
+let depth: Int = b.depth;
+```
+
## Builder.asSlice
```tact
@@ -527,6 +604,12 @@ let s: Slice = beginCell().storeInt(42, 7).asSlice();
let fizz: Slice = s.preloadBits(7);
```
+:::note
+
+ In order to reduce gas usage, prefer using this function over calling [`Slice.firstBits(){:tact}`](#slicefirstbits) since the latter is less optimized.
+
+:::
+
## Slice.skipBits
```tact
@@ -549,6 +632,30 @@ s.skipBits(5); // all but first 5 bits
let fizz: Slice = s.loadBits(1); // load only 1 bit
```
+## Slice.skipLastBits
+
+
+
+```tact
+extends fun skipLastBits(self: Slice, len: Int);
+```
+
+Extension function for the [`Slice{:tact}`][slice].
+
+Preloads all but the last $0 ≤$ `len` $≤ 1023$ bits from the [`Slice{:tact}`][slice].
+
+Attempts to specify an out-of-bounds `len` value throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Attempts to preload more data than [`Slice{:tact}`][slice] contains throw an exception with [exit code 9](/book/exit-codes#9): `Cell underflow`.
+
+Usage example:
+
+```tact
+let s: Slice = beginCell().storeInt(42, 7).asSlice();
+let allButLastFive: Slice = s.skipLastBits(5); // all but last 5 bits,
+ // i.e. only first 2
+```
+
## Slice.loadBool
```tact
@@ -727,6 +834,106 @@ let s: Slice = beginCell().storeRef(emptyCell()).asSlice();
let fizz: Int = s.bits();
```
+## Slice.firstBits
+
+
+
+```tact
+extends fun firstBits(self: Slice, len: Int): Slice;
+```
+
+Extension function for the [`Slice{:tact}`][slice].
+
+Preloads the first $0 ≤$ `len` $≤ 1023$ bits from the [`Slice{:tact}`][slice].
+
+Attempts to specify an out-of-bounds `len` value throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Attempts to preload more data than [`Slice{:tact}`][slice] contains throw an exception with [exit code 9](/book/exit-codes#9): `Cell underflow`.
+
+Usage example:
+
+```tact
+let s: Slice = beginCell().storeInt(42, 7).asSlice();
+let firstFive: Slice = s.firstBits(5); // first 5 bits
+```
+
+:::note
+
+ In order to reduce gas usage, prefer calling [`Slice.preloadBits(){:tact}`](#slicepreloadbits) over using this function since the former is more optimized.
+
+:::
+
+## Slice.lastBits
+
+
+
+```tact
+extends fun lastBits(self: Slice, len: Int): Slice;
+```
+
+Extension function for the [`Slice{:tact}`][slice].
+
+Preloads the last $0 ≤$ `len` $≤ 1023$ bits from the [`Slice{:tact}`][slice].
+
+Attempts to specify an out-of-bounds `len` value throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Attempts to preload more data than [`Slice{:tact}`][slice] contains throw an exception with [exit code 9](/book/exit-codes#9): `Cell underflow`.
+
+Usage example:
+
+```tact
+let s: Slice = beginCell().storeInt(42, 7).asSlice();
+let lastFive: Slice = s.lastBits(5); // last 5 bits
+```
+
+## Slice.depth
+
+
+
+```tact
+extends fun depth(self: Slice): Int;
+```
+
+Extension function for the [`Slice{:tact}`][slice].
+
+Computes and returns the [`Int{:tact}`][int] [depth][std-repr] of the [`Slice{:tact}`][slice]. Produces $0$ if the [`Slice{:tact}`][slice] has no references, otherwise $1$ plus the maximum of the depths of the referenced cells.
+
+Usage example:
+
+```tact
+let s: Slice = beginCell().storeInt(42, 7).asSlice();
+let depth: Int = s.depth;
+```
+
+## Slice.computeDataSize
+
+
+
+```tact
+extends fun computeDataSize(self: Slice, maxCells: Int): DataSize;
+```
+
+Extension function for the [`Slice{:tact}`][slice]. Similar to [`Cell.computeDataSize(){:tact}`](#cellcomputedatasize), but doesn't take into account the cell that contains the [`Slice{:tact}`][slice] itself. However, accounts for its bits and refs.
+
+If the specified `maxCells` value isn't enough to traverse all cells **not** including the starting one, an exception with [exit code 8](/book/exit-codes#8) is thrown: `Cell overflow`.
+
+Attempts to specify a negative value of `maxCells` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Usage example:
+
+```tact
+let s: Slice = beginCell().storeInt(42, 7).storeRef(emptyCell()).asSlice();
+try {
+ let dataSize: DataSize = s.computeDataSize(1);
+ dataSize.cells; // 1
+ dataSize.bits; // 7
+ dataSize.refs; // 1
+} catch (exitCode) {
+ // if maxCells was insufficient to traverse the cell
+ // and all of its references, the exitCode here would be 8
+}
+```
+
## Slice.empty
```tact
@@ -1129,3 +1336,5 @@ fun cautiousParse(payload: Slice): TripleAxe? {
[tlb]: https://docs.ton.org/develop/data-formats/tl-b-language
[sha-2]: https://en.wikipedia.org/wiki/SHA-2#Hash_standard
+[dfs]: https://en.wikipedia.org/wiki/Depth-first_search
+[gas]: https://docs.ton.org/v3/documentation/smart-contracts/transaction-fees/fees#gas
diff --git a/docs/src/content/docs/ref/core-common.mdx b/docs/src/content/docs/ref/core-common.mdx
index 64c28fdc3..ab858492c 100644
--- a/docs/src/content/docs/ref/core-common.mdx
+++ b/docs/src/content/docs/ref/core-common.mdx
@@ -3,6 +3,8 @@ title: Common
description: "Commonly used global static functions from the Core library of Tact"
---
+import { Badge } from '@astrojs/starlight/components';
+
List of the most commonly used built-in [global static functions](/book/functions#global-static-functions).
## Contextual
@@ -125,6 +127,10 @@ Creates a new [`Address{:tact}`][p] based on the [`chain` id](https://ton-blockc
This function tries to resolve constant values in [compile-time](/ref/core-comptime) whenever possible.
+Attempts to specify an invalid `chain` ID (not $-1$ or $0$) throw an exception with [exit code 136](/book/exit-codes#136): `Invalid address`.
+
+Attempts to specify an `chain` ID pointing to the masterchain ($-1$) without [masterchain support](/book/masterchain) enabled throw an exception with [exit code 137](/book/exit-codes#137): `Masterchain support is not enabled for this contract`.
+
Usage example:
```tact
@@ -136,12 +142,6 @@ let oldTonFoundationAddr: Address =
// chain id: 0 is a workchain, -1 is a masterchain
```
-:::caution
-
- This method throws an error with [exit code 136](/book/exit-codes#136) if `chain` is invalid or with [exit code 137](/book/exit-codes#137) if `chain` points to the masterchain ($-1$) without [masterchain support](/book/masterchain) enabled.
-
-:::
-
:::note[Useful links:]
[`chain` (Workchain ID) in TON Docs](https://docs.ton.org/learn/overviews/addresses#workchain-id)\
@@ -172,6 +172,10 @@ fun contractAddressExt(chain: Int, code: Cell, data: Cell): Address;
Computes smart contract's [`Address{:tact}`][p] based on the `chain` id, contract's `code` and contract's initial state `data`. Use [`initOf{:tact}`](/book/expressions#initof) expression to obtain initial `code` and initial `data` of a given contract.
+Attempts to specify an invalid `chain` ID (not $-1$ or $0$) throw an exception with [exit code 136](/book/exit-codes#136): `Invalid address`.
+
+Attempts to specify an `chain` ID pointing to the masterchain ($-1$) without [masterchain support](/book/masterchain) enabled throw an exception with [exit code 137](/book/exit-codes#137): `Masterchain support is not enabled for this contract`.
+
Usage example:
```tact
@@ -179,16 +183,17 @@ let initPkg: StateInit = initOf SomeContract();
let hereBeDragons: Address = contractAddressExt(0, initPkg.code, initPkg.data);
```
-:::caution
+### addressNone
- This method throws an error with [exit code 136](/book/exit-codes#136) if `chain` is invalid or with [exit code 137](/book/exit-codes#137) if `chain` points to the masterchain ($-1$) without [masterchain support](/book/masterchain) enabled.
+
-:::
+```tact
+fun addressNone(): Address?;
+```
:::note
- For this function to work, the compiler option `debug` has to be set to `true{:tact}` for the current project in the [configuration file](/book/config).\
- Read more about debugging on the dedicated page: [Debugging](/book/debug).
+ TODO: awaits resolution of [those comments](https://github.com/tact-lang/tact/pull/986#discussion_r1865450023).
:::
diff --git a/docs/src/content/docs/ref/core-math.mdx b/docs/src/content/docs/ref/core-math.mdx
index e4ccb1f81..3bfdb1c26 100644
--- a/docs/src/content/docs/ref/core-math.mdx
+++ b/docs/src/content/docs/ref/core-math.mdx
@@ -3,6 +3,8 @@ title: Math
description: "Various math helper functions from the Core library of Tact"
---
+import { Badge } from '@astrojs/starlight/components';
+
Various math helper functions.
## min
@@ -46,7 +48,7 @@ max(0x45, 3_0_0); // 300
## abs
```tact
-fun abs(x: Int): Int
+fun abs(x: Int): Int;
```
Computes and returns the [absolute value](https://en.wikipedia.org/wiki/Absolute_value) of the [`Int{:tact}`][int] value `x`.
@@ -59,13 +61,169 @@ abs(-42); // 42
abs(-(-(-42))); // 42
```
+## sign
+
+
+
+```tact
+fun sign(x: Int): Int;
+```
+
+Computes and returns the sign of the [`Int{:tact}`][int] value `x`. Produces $1$ if the `x` is positive, $-1$ if the `x` is negative, and $0$ if the `x` is $0$.
+
+Usage examples:
+
+```tact
+sign(42); // 1
+sign(-42); // -1
+sign(-(-42)); // 1
+sign(-(-(-42))); // -1
+sign(0); // 0
+```
+
+## sqrt
+
+
+
+```tact
+fun sqrt(num: Int): Int;
+```
+
+Computes the [square root](https://en.wikipedia.org/wiki/Square_root) of the [`Int{:tact}`][int] value `num`. Returns the result rounded to the nearest integer. If there are two equally close integers, rounding is done toward the even one.
+
+Attempts to specify a negative value of `num` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Usage examples:
+
+```tact
+sqrt(4); // 2
+sqrt(3); // 2
+sqrt(2); // 1
+sqrt(1); // 1
+sqrt(0); // 0
+sqrt(-1); // ERROR! Exit code 5: Integer out of expected range
+```
+
+## divc
+
+
+
+```tact
+fun divc(x: Int, y: Int): Int;
+```
+
+Computes and returns the [rounded up][round-up] result of division of the [`Int{:tact}`][int] `x` by the [`Int{:tact}`][int] `y`.
+
+Attempts to divide by `y` equal to $0$ throw an exception with [exit code 4](/book/exit-codes#4): `Integer overflow`.
+
+Usage examples:
+
+```tact
+divc(4, 2); // 2
+divc(3, 2); // 2
+divc(-4, 2); // -2
+divc(-3, 2); // -1
+```
+
+## muldivc
+
+
+
+```tact
+fun muldivc(x: Int, y: Int, z: Int): Int;
+```
+
+Computes and returns the [rounded up][round-up] result of `(x * y) / z{:tact}`.
+
+If the value in calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, or if there's an attempt to divide by `z` equal to $0$, an exception with [exit code 4](/book/exit-codes#4) is thrown: `Integer overflow`.
+
+Usage examples:
+
+```tact
+muldivc(4, 1, 2); // 2
+muldivc(3, 1, 2); // 2
+muldivc(-4, 1, 2); // -2
+muldivc(-3, 1, 2); // -1
+muldivc(-3, 0, 2); // 0
+muldivc(-3, 0, 0); // ERROR! Exit code 4: Integer overflow
+```
+
+## mulShiftRight
+
+
+
+```tact
+fun mulShiftRight(x: Int, y: Int, z: Int): Int;
+```
+
+Computes and returns the [rounded down][round-down] result of `(x * y) / z{:tact}`. It is a more gas-efficient equivalent of doing the [bitwise shift right](/book/operators#binary-bitwise-shift-right) on the result of multiplication of [`Int{:tact}`][int] `x` times [`Int{:tact}`][int] `y`, where [`Int{:tact}`][int] `z` is the right operand of the shift.
+
+If the value in calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, an exception with [exit code 4](/book/exit-codes#4) is thrown: `Integer overflow`.
+
+Attempts to specify a negative value of `z` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Usage examples:
+
+```tact
+mulShiftRight(5, 5, 2); // 6
+mulShiftRight(5, 5, 1); // 12
+mulShiftRight(5, 5, 0); // 25
+mulShiftRight(5, 5, -1); // ERROR! Exit code 5: Integer out of expected range
+```
+
+## mulShiftRightRound
+
+
+
+```tact
+fun mulShiftRightRound(x: Int, y: Int, z: Int): Int;
+```
+
+Similar to [`mulShiftRight(){:tact}`](#mulshiftright), but instead of [rounding down][round-down], the result value is rounded to the nearest integer. If there are two equally close integers, rounding is done toward the even one.
+
+If the value in calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, an exception with [exit code 4](/book/exit-codes#4) is thrown: `Integer overflow`.
+
+Attempts to specify negative value of `z` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Usage examples:
+
+```tact
+mulShiftRightRound(5, 5, 2); // 6
+mulShiftRightRound(5, 5, 1); // 13
+mulShiftRightRound(5, 5, 0); // 25
+mulShiftRightRound(5, 5, -1); // ERROR! Exit code 5: Integer out of expected range
+```
+
+## mulShiftRightCeil
+
+
+
+```tact
+fun mulShiftRightCeil(x: Int, y: Int, z: Int): Int;
+```
+
+Similar to [`mulShiftRight(){:tact}`](#mulshiftright), but instead of [rounding down][round-down], the result value is [rounded up][round-up].
+
+If the value in calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, an exception with [exit code 4](/book/exit-codes#4) is thrown: `Integer overflow`.
+
+Attempts to specify negative value of `z` throw an exception with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+
+Usage examples:
+
+```tact
+mulShiftRightCeil(5, 5, 2); // 7
+mulShiftRightCeil(5, 5, 1); // 13
+mulShiftRightCeil(5, 5, 0); // 25
+mulShiftRightCeil(5, 5, -1); // ERROR! Exit code 5: Integer out of expected range
+```
+
## log
```tact
fun log(num: Int, base: Int): Int;
```
-Computes and returns the [logarithm](https://en.wikipedia.org/wiki/Logarithm) of a number `num` $> 0$ to the base `base` $≥ 1$. Results are [rounded down](https://en.wikipedia.org/wiki/Rounding#Rounding_down). Passing a non-positive `num` value or a `base` less than $1$ throws an error with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
+Computes and returns the [logarithm](https://en.wikipedia.org/wiki/Logarithm) of a number `num` $> 0$ to the base `base` $≥ 1$. Results are [rounded down][round-down]. Passing a non-positive `num` value or a `base` less than $1$ throws an error with [exit code 5](/book/exit-codes#5): `Integer out of expected range`.
Usage examples:
@@ -142,7 +300,7 @@ contract Example {
:::note
- Note, that if you only need to obtain powers of $2$, use the [`pow2(){:tact}`](#pow2) function, as it's more gas-efficient.
+ If you only need to obtain powers of $2$, use the [`pow2(){:tact}`](#pow2) function, as it's more gas-efficient.
:::
@@ -286,3 +444,6 @@ sha256(someVariableElsewhere); // will try to resolve at compile-time,
[tvm]: https://docs.ton.org/learn/tvm-instructions/tvm-overview
[ed]: https://en.wikipedia.org/wiki/EdDSA#Ed25519
[sha-2]: https://en.wikipedia.org/wiki/SHA-2#Hash_standard
+
+[round-up]: https://en.wikipedia.org/wiki/Rounding#Rounding_up
+[round-down]: https://en.wikipedia.org/wiki/Rounding#Rounding_down
diff --git a/src/imports/stdlib.ts b/src/imports/stdlib.ts
index f38b5ce7c..1a83e4fb1 100644
--- a/src/imports/stdlib.ts
+++ b/src/imports/stdlib.ts
@@ -152,45 +152,52 @@ files['std/cells.tact'] =
'Ly8vCi8vLyBTZWU6IGh0dHBzOi8vZG9jcy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWNlbGxzI2J1aWxkZXJzdG9yZW1heWJlcmVmCi8vLwphc20oY2VsbCBzZWxmKSBl' +
'eHRlbmRzIGZ1biBzdG9yZU1heWJlUmVmKHNlbGY6IEJ1aWxkZXIsIGNlbGw6IENlbGw/KTogQnVpbGRlciB7IFNUT1BUUkVGIH0KCmFzbSBleHRlbmRzIGZ1biBlbmRD' +
'ZWxsKHNlbGY6IEJ1aWxkZXIpOiBDZWxsIHsgRU5EQyB9Cgphc20gZXh0ZW5kcyBmdW4gcmVmcyhzZWxmOiBCdWlsZGVyKTogSW50IHsgQlJFRlMgfQoKYXNtIGV4dGVu' +
- 'ZHMgZnVuIGJpdHMoc2VsZjogQnVpbGRlcik6IEludCB7IEJCSVRTIH0KCi8vCi8vIFNsaWNlCi8vCgphc20gZXh0ZW5kcyBmdW4gYmVnaW5QYXJzZShzZWxmOiBDZWxs' +
- 'KTogU2xpY2UgeyBDVE9TIH0KCmFzbSgtPiAxIDApIGV4dGVuZHMgbXV0YXRlcyBmdW4gbG9hZFJlZihzZWxmOiBTbGljZSk6IENlbGwgeyBMRFJFRiB9CgovLy8gRXh0' +
- 'ZW5zaW9uIGZ1bmN0aW9uIGZvciB0aGUgYFNsaWNlYC4gQXZhaWxhYmxlIHNpbmNlIFRhY3QgMS41LjAuCi8vLwovLy8gUHJlbG9hZHMgdGhlIG5leHQgcmVmZXJlbmNl' +
- 'IGZyb20gdGhlIGBTbGljZWAgYXMgYSBgQ2VsbGAuIERvZXNuJ3QgbW9kaWZ5IHRoZSBvcmlnaW5hbCBgU2xpY2VgLgovLy8KLy8vIEF0dGVtcHRzIHRvIHByZWxvYWQg' +
- 'c3VjaCByZWZlcmVuY2UgYENlbGxgIHdoZW4gYFNsaWNlYCBkb2Vzbid0IGNvbnRhaW4gaXQgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhpdCBjb2RlIDg6IGBDZWxs' +
- 'IG92ZXJmbG93YC4KLy8vCi8vLyBBdHRlbXB0cyB0byBwcmVsb2FkIG1vcmUgZGF0YSB0aGFuIGBTbGljZWAgY29udGFpbnMgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGgg' +
- 'ZXhpdCBjb2RlIDk6IGBDZWxsIHVuZGVyZmxvd2AuCi8vLwovLy8gYGBgdGFjdAovLy8gZnVuIGV4YW1wbGVzKCkgewovLy8gICAgIGxldCBzMTogU2xpY2UgPSBiZWdp' +
- 'bkNlbGwoKS5zdG9yZVJlZihlbXB0eUNlbGwoKSkuYXNTbGljZSgpOwovLy8gICAgIGxldCBmaXp6OiBDZWxsID0gczEucHJlbG9hZFJlZigpOyAvLyBkaWRuJ3QgbW9k' +
- 'aWZ5IHMxCi8vLwovLy8gICAgIGxldCBzMjogU2xpY2UgPSBiZWdpbkNlbGwoKQovLy8gICAgICAgICAuc3RvcmVSZWYoZW1wdHlDZWxsKCkpCi8vLyAgICAgICAgIC5z' +
- 'dG9yZVJlZihzMS5hc0NlbGwoKSkKLy8vICAgICAgICAgLmFzU2xpY2UoKTsKLy8vICAgICBsZXQgcmVmMTogQ2VsbCA9IHMyLnByZWxvYWRSZWYoKTsKLy8vICAgICBs' +
- 'ZXQgcmVmMjogQ2VsbCA9IHMyLnByZWxvYWRSZWYoKTsKLy8vICAgICByZWYxID09IHJlZjI7IC8vIHRydWUKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZToKLy8vICog' +
- 'aHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtY2VsbHMjc2xpY2VwcmVsb2FkcmVmCi8vLyAqIGh0dHBzOi8vZG9jcy50YWN0LWxhbmcub3JnL2Jvb2sv' +
- 'ZXhpdC1jb2RlcwovLy8KYXNtIGV4dGVuZHMgZnVuIHByZWxvYWRSZWYoc2VsZjogU2xpY2UpOiBDZWxsIHsgUExEUkVGIH0KCi8vIHNwZWNpYWwgdHJlYXRtZW50IGlu' +
- 'IEZ1bmMgY29tcGlsZXIsIHNvIG5vdCByZXBsYWNlZCB3aXRoIGFzbSAiTERTTElDRVgiCkBuYW1lKGxvYWRfYml0cykKZXh0ZW5kcyBtdXRhdGVzIG5hdGl2ZSBsb2Fk' +
- 'Qml0cyhzZWxmOiBTbGljZSwgbDogSW50KTogU2xpY2U7CgovLyBzcGVjaWFsIHRyZWF0bWVudCBpbiBGdW5jIGNvbXBpbGVyLCBzbyBub3QgcmVwbGFjZWQgd2l0aCBh' +
- 'c20gIlBMRFNMSUNFWCIKQG5hbWUocHJlbG9hZF9iaXRzKQpleHRlbmRzIG5hdGl2ZSBwcmVsb2FkQml0cyhzZWxmOiBTbGljZSwgbDogSW50KTogU2xpY2U7CgovLyBz' +
- 'cGVjaWFsIHRyZWF0bWVudCBpbiBGdW5jIGNvbXBpbGVyLCBzbyBub3QgcmVwbGFjZWQgd2l0aCBhc20gIkxESVgiCkBuYW1lKGxvYWRfaW50KQpleHRlbmRzIG11dGF0' +
- 'ZXMgbmF0aXZlIGxvYWRJbnQoc2VsZjogU2xpY2UsIGw6IEludCk6IEludDsKCi8vIHNwZWNpYWwgdHJlYXRtZW50IGluIEZ1bmMgY29tcGlsZXIsIHNvIG5vdCByZXBs' +
- 'YWNlZCB3aXRoIGFzbSAiUExESVgiCkBuYW1lKHByZWxvYWRfaW50KQpleHRlbmRzIG5hdGl2ZSBwcmVsb2FkSW50KHNlbGY6IFNsaWNlLCBsOiBJbnQpOiBJbnQ7Cgov' +
- 'LyBzcGVjaWFsIHRyZWF0bWVudCBpbiBGdW5jIGNvbXBpbGVyLCBzbyBub3QgcmVwbGFjZWQgd2l0aCBhc20gIkxEVVgiCkBuYW1lKGxvYWRfdWludCkKZXh0ZW5kcyBt' +
- 'dXRhdGVzIG5hdGl2ZSBsb2FkVWludChzZWxmOiBTbGljZSwgbDogSW50KTogSW50OwoKLy8gc3BlY2lhbCB0cmVhdG1lbnQgaW4gRnVuYyBjb21waWxlciwgc28gbm90' +
- 'IHJlcGxhY2VkIHdpdGggYXNtICJQTERVWCIKQG5hbWUocHJlbG9hZF91aW50KQpleHRlbmRzIG5hdGl2ZSBwcmVsb2FkVWludChzZWxmOiBTbGljZSwgbDogSW50KTog' +
- 'SW50OwoKYXNtKC0+IDEgMCkgZXh0ZW5kcyBtdXRhdGVzIGZ1biBsb2FkQm9vbChzZWxmOiBTbGljZSk6IEJvb2wgeyAxIExESSB9CgovLy8gRXh0ZW5zaW9uIG11dGF0' +
- 'aW9uIGZ1bmN0aW9uIGZvciB0aGUgYFNsaWNlYC4gQWxpYXMgdG8gYFNsaWNlLmxvYWRCb29sKClgLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBg' +
- 'YGB0YWN0Ci8vLyBmdW4gZXhhbXBsZSgpIHsKLy8vICAgICBsZXQgczogU2xpY2UgPSBiZWdpbkNlbGwoKS5zdG9yZUJvb2wodHJ1ZSkuYXNTbGljZSgpOwovLy8gICAg' +
- 'IGxldCBmaXp6OiBCb29sID0gcy5sb2FkQml0KCk7IC8vIHRydWUKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZTogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVm' +
- 'L2NvcmUtY2VsbHMjc2xpY2Vsb2FkYml0Ci8vLwphc20oLT4gMSAwKSBleHRlbmRzIG11dGF0ZXMgZnVuIGxvYWRCaXQoc2VsZjogU2xpY2UpOiBCb29sIHsgMSBMREkg' +
- 'fQoKYXNtKCAtPiAxIDApIGV4dGVuZHMgbXV0YXRlcyBmdW4gbG9hZENvaW5zKHNlbGY6IFNsaWNlKTogSW50IHsgTERWQVJVSU5UMTYgfQoKQG5hbWUoX190YWN0X2xv' +
- 'YWRfYWRkcmVzcykKZXh0ZW5kcyBtdXRhdGVzIG5hdGl2ZSBsb2FkQWRkcmVzcyhzZWxmOiBTbGljZSk6IEFkZHJlc3M7Cgphc20gZXh0ZW5kcyBtdXRhdGVzIGZ1biBz' +
- 'a2lwQml0cyhzZWxmOiBTbGljZSwgbDogSW50KSB7IFNEU0tJUEZJUlNUIH0KCmFzbSBleHRlbmRzIGZ1biBlbmRQYXJzZShzZWxmOiBTbGljZSkgeyBFTkRTIH0KCi8v' +
- 'Ci8vIFNsaWNlIHNpemUKLy8KCmFzbSBleHRlbmRzIGZ1biByZWZzKHNlbGY6IFNsaWNlKTogSW50IHsgU1JFRlMgfQoKYXNtIGV4dGVuZHMgZnVuIGJpdHMoc2VsZjog' +
- 'U2xpY2UpOiBJbnQgeyBTQklUUyB9Cgphc20gZXh0ZW5kcyBmdW4gZW1wdHkoc2VsZjogU2xpY2UpOiBCb29sIHsgU0VNUFRZIH0KCmFzbSBleHRlbmRzIGZ1biBkYXRh' +
- 'RW1wdHkoc2VsZjogU2xpY2UpOiBCb29sIHsgU0RFTVBUWSB9Cgphc20gZXh0ZW5kcyBmdW4gcmVmc0VtcHR5KHNlbGY6IFNsaWNlKTogQm9vbCB7IFNSRU1QVFkgfQoK' +
- 'Ly8KLy8gQ29udmVyc2lvbnMKLy8KCmlubGluZSBleHRlbmRzIGZ1biBhc1NsaWNlKHNlbGY6IEJ1aWxkZXIpOiBTbGljZSB7CiAgICByZXR1cm4gc2VsZi5lbmRDZWxs' +
- 'KCkuYmVnaW5QYXJzZSgpOwp9CgppbmxpbmUgZXh0ZW5kcyBmdW4gYXNTbGljZShzZWxmOiBDZWxsKTogU2xpY2UgewogICAgcmV0dXJuIHNlbGYuYmVnaW5QYXJzZSgp' +
- 'Owp9CgppbmxpbmUgZXh0ZW5kcyBmdW4gYXNDZWxsKHNlbGY6IFNsaWNlKTogQ2VsbCB7CiAgICByZXR1cm4gYmVnaW5DZWxsKCkKICAgICAgICAuc3RvcmVTbGljZShz' +
- 'ZWxmKQogICAgICAgIC5lbmRDZWxsKCk7Cn0KCmlubGluZSBleHRlbmRzIGZ1biBhc0NlbGwoc2VsZjogQnVpbGRlcik6IENlbGwgewogICAgcmV0dXJuIHNlbGYuZW5k' +
- 'Q2VsbCgpOwp9CgppbmxpbmUgZnVuIGVtcHR5Q2VsbCgpOiBDZWxsIHsKICAgIHJldHVybiBiZWdpbkNlbGwoKS5lbmRDZWxsKCk7Cn0KCmlubGluZSBmdW4gZW1wdHlT' +
- 'bGljZSgpOiBTbGljZSB7CiAgICByZXR1cm4gZW1wdHlDZWxsKCkuYXNTbGljZSgpOwp9Cg==';
+ 'ZHMgZnVuIGJpdHMoc2VsZjogQnVpbGRlcik6IEludCB7IEJCSVRTIH0KCmFzbSBleHRlbmRzIGZ1biBkZXB0aChzZWxmOiBCdWlsZGVyKTogSW50IHsgQkRFUFRIIH0K' +
+ 'Ci8vCi8vIFNsaWNlCi8vCgphc20gZXh0ZW5kcyBmdW4gYmVnaW5QYXJzZShzZWxmOiBDZWxsKTogU2xpY2UgeyBDVE9TIH0KCmFzbSgtPiAxIDApIGV4dGVuZHMgbXV0' +
+ 'YXRlcyBmdW4gbG9hZFJlZihzZWxmOiBTbGljZSk6IENlbGwgeyBMRFJFRiB9CgovLy8gRXh0ZW5zaW9uIGZ1bmN0aW9uIGZvciB0aGUgYFNsaWNlYC4gQXZhaWxhYmxl' +
+ 'IHNpbmNlIFRhY3QgMS41LjAuCi8vLwovLy8gUHJlbG9hZHMgdGhlIG5leHQgcmVmZXJlbmNlIGZyb20gdGhlIGBTbGljZWAgYXMgYSBgQ2VsbGAuIERvZXNuJ3QgbW9k' +
+ 'aWZ5IHRoZSBvcmlnaW5hbCBgU2xpY2VgLgovLy8KLy8vIEF0dGVtcHRzIHRvIHByZWxvYWQgc3VjaCByZWZlcmVuY2UgYENlbGxgIHdoZW4gYFNsaWNlYCBkb2Vzbid0' +
+ 'IGNvbnRhaW4gaXQgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhpdCBjb2RlIDg6IGBDZWxsIG92ZXJmbG93YC4KLy8vCi8vLyBBdHRlbXB0cyB0byBwcmVsb2FkIG1v' +
+ 'cmUgZGF0YSB0aGFuIGBTbGljZWAgY29udGFpbnMgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhpdCBjb2RlIDk6IGBDZWxsIHVuZGVyZmxvd2AuCi8vLwovLy8gYGBg' +
+ 'dGFjdAovLy8gZnVuIGV4YW1wbGVzKCkgewovLy8gICAgIGxldCBzMTogU2xpY2UgPSBiZWdpbkNlbGwoKS5zdG9yZVJlZihlbXB0eUNlbGwoKSkuYXNTbGljZSgpOwov' +
+ 'Ly8gICAgIGxldCBmaXp6OiBDZWxsID0gczEucHJlbG9hZFJlZigpOyAvLyBkaWRuJ3QgbW9kaWZ5IHMxCi8vLwovLy8gICAgIGxldCBzMjogU2xpY2UgPSBiZWdpbkNl' +
+ 'bGwoKQovLy8gICAgICAgICAuc3RvcmVSZWYoZW1wdHlDZWxsKCkpCi8vLyAgICAgICAgIC5zdG9yZVJlZihzMS5hc0NlbGwoKSkKLy8vICAgICAgICAgLmFzU2xpY2Uo' +
+ 'KTsKLy8vICAgICBsZXQgcmVmMTogQ2VsbCA9IHMyLnByZWxvYWRSZWYoKTsKLy8vICAgICBsZXQgcmVmMjogQ2VsbCA9IHMyLnByZWxvYWRSZWYoKTsKLy8vICAgICBy' +
+ 'ZWYxID09IHJlZjI7IC8vIHRydWUKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtY2VsbHMj' +
+ 'c2xpY2VwcmVsb2FkcmVmCi8vLyAqIGh0dHBzOi8vZG9jcy50YWN0LWxhbmcub3JnL2Jvb2svZXhpdC1jb2RlcwovLy8KYXNtIGV4dGVuZHMgZnVuIHByZWxvYWRSZWYo' +
+ 'c2VsZjogU2xpY2UpOiBDZWxsIHsgUExEUkVGIH0KCi8vIHNwZWNpYWwgdHJlYXRtZW50IGluIEZ1bmMgY29tcGlsZXIsIHNvIG5vdCByZXBsYWNlZCB3aXRoIGFzbSAi' +
+ 'TERTTElDRVgiCkBuYW1lKGxvYWRfYml0cykKZXh0ZW5kcyBtdXRhdGVzIG5hdGl2ZSBsb2FkQml0cyhzZWxmOiBTbGljZSwgbDogSW50KTogU2xpY2U7CgovLyBzcGVj' +
+ 'aWFsIHRyZWF0bWVudCBpbiBGdW5jIGNvbXBpbGVyLCBzbyBub3QgcmVwbGFjZWQgd2l0aCBhc20gIlBMRFNMSUNFWCIKQG5hbWUocHJlbG9hZF9iaXRzKQpleHRlbmRz' +
+ 'IG5hdGl2ZSBwcmVsb2FkQml0cyhzZWxmOiBTbGljZSwgbDogSW50KTogU2xpY2U7CgovLyBzcGVjaWFsIHRyZWF0bWVudCBpbiBGdW5jIGNvbXBpbGVyLCBzbyBub3Qg' +
+ 'cmVwbGFjZWQgd2l0aCBhc20gIkxESVgiCkBuYW1lKGxvYWRfaW50KQpleHRlbmRzIG11dGF0ZXMgbmF0aXZlIGxvYWRJbnQoc2VsZjogU2xpY2UsIGw6IEludCk6IElu' +
+ 'dDsKCi8vIHNwZWNpYWwgdHJlYXRtZW50IGluIEZ1bmMgY29tcGlsZXIsIHNvIG5vdCByZXBsYWNlZCB3aXRoIGFzbSAiUExESVgiCkBuYW1lKHByZWxvYWRfaW50KQpl' +
+ 'eHRlbmRzIG5hdGl2ZSBwcmVsb2FkSW50KHNlbGY6IFNsaWNlLCBsOiBJbnQpOiBJbnQ7CgovLyBzcGVjaWFsIHRyZWF0bWVudCBpbiBGdW5jIGNvbXBpbGVyLCBzbyBu' +
+ 'b3QgcmVwbGFjZWQgd2l0aCBhc20gIkxEVVgiCkBuYW1lKGxvYWRfdWludCkKZXh0ZW5kcyBtdXRhdGVzIG5hdGl2ZSBsb2FkVWludChzZWxmOiBTbGljZSwgbDogSW50' +
+ 'KTogSW50OwoKLy8gc3BlY2lhbCB0cmVhdG1lbnQgaW4gRnVuYyBjb21waWxlciwgc28gbm90IHJlcGxhY2VkIHdpdGggYXNtICJQTERVWCIKQG5hbWUocHJlbG9hZF91' +
+ 'aW50KQpleHRlbmRzIG5hdGl2ZSBwcmVsb2FkVWludChzZWxmOiBTbGljZSwgbDogSW50KTogSW50OwoKYXNtKC0+IDEgMCkgZXh0ZW5kcyBtdXRhdGVzIGZ1biBsb2Fk' +
+ 'Qm9vbChzZWxmOiBTbGljZSk6IEJvb2wgeyAxIExESSB9CgovLy8gRXh0ZW5zaW9uIG11dGF0aW9uIGZ1bmN0aW9uIGZvciB0aGUgYFNsaWNlYC4gQWxpYXMgdG8gYFNs' +
+ 'aWNlLmxvYWRCb29sKClgLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBgYGB0YWN0Ci8vLyBmdW4gZXhhbXBsZSgpIHsKLy8vICAgICBsZXQgczog' +
+ 'U2xpY2UgPSBiZWdpbkNlbGwoKS5zdG9yZUJvb2wodHJ1ZSkuYXNTbGljZSgpOwovLy8gICAgIGxldCBmaXp6OiBCb29sID0gcy5sb2FkQml0KCk7IC8vIHRydWUKLy8v' +
+ 'IH0KLy8vIGBgYAovLy8KLy8vIFNlZTogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtY2VsbHMjc2xpY2Vsb2FkYml0Ci8vLwphc20oLT4gMSAwKSBl' +
+ 'eHRlbmRzIG11dGF0ZXMgZnVuIGxvYWRCaXQoc2VsZjogU2xpY2UpOiBCb29sIHsgMSBMREkgfQoKYXNtKCAtPiAxIDApIGV4dGVuZHMgbXV0YXRlcyBmdW4gbG9hZENv' +
+ 'aW5zKHNlbGY6IFNsaWNlKTogSW50IHsgTERWQVJVSU5UMTYgfQoKQG5hbWUoX190YWN0X2xvYWRfYWRkcmVzcykKZXh0ZW5kcyBtdXRhdGVzIG5hdGl2ZSBsb2FkQWRk' +
+ 'cmVzcyhzZWxmOiBTbGljZSk6IEFkZHJlc3M7Cgphc20gZXh0ZW5kcyBtdXRhdGVzIGZ1biBza2lwQml0cyhzZWxmOiBTbGljZSwgbDogSW50KSB7IFNEU0tJUEZJUlNU' +
+ 'IH0KCmFzbSBleHRlbmRzIGZ1biBlbmRQYXJzZShzZWxmOiBTbGljZSkgeyBFTkRTIH0KCmFzbSBleHRlbmRzIGZ1biBza2lwTGFzdEJpdHMoc2VsZjogU2xpY2UsIGxl' +
+ 'bjogSW50KTogU2xpY2UgeyBTRFNLSVBMQVNUIH0KCmFzbSBleHRlbmRzIGZ1biBmaXJzdEJpdHMoc2VsZjogU2xpY2UsIGxlbjogSW50KTogU2xpY2UgeyBTRENVVEZJ' +
+ 'UlNUIH0KCmFzbSBleHRlbmRzIGZ1biBsYXN0Qml0cyhzZWxmOiBTbGljZSwgbGVuOiBJbnQpOiBTbGljZSB7IFNEQ1VUTEFTVCB9Cgphc20gZXh0ZW5kcyBmdW4gZGVw' +
+ 'dGgoc2VsZjogU2xpY2UpOiBJbnQgeyBTREVQVEggfQoKLy8KLy8gU2xpY2Ugc2l6ZQovLwoKYXNtIGV4dGVuZHMgZnVuIHJlZnMoc2VsZjogU2xpY2UpOiBJbnQgeyBT' +
+ 'UkVGUyB9Cgphc20gZXh0ZW5kcyBmdW4gYml0cyhzZWxmOiBTbGljZSk6IEludCB7IFNCSVRTIH0KCmFzbSBleHRlbmRzIGZ1biBlbXB0eShzZWxmOiBTbGljZSk6IEJv' +
+ 'b2wgeyBTRU1QVFkgfQoKYXNtIGV4dGVuZHMgZnVuIGRhdGFFbXB0eShzZWxmOiBTbGljZSk6IEJvb2wgeyBTREVNUFRZIH0KCmFzbSBleHRlbmRzIGZ1biByZWZzRW1w' +
+ 'dHkoc2VsZjogU2xpY2UpOiBCb29sIHsgU1JFTVBUWSB9CgovLwovLyBDb252ZXJzaW9ucwovLwoKaW5saW5lIGV4dGVuZHMgZnVuIGFzU2xpY2Uoc2VsZjogQnVpbGRl' +
+ 'cik6IFNsaWNlIHsKICAgIHJldHVybiBzZWxmLmVuZENlbGwoKS5iZWdpblBhcnNlKCk7Cn0KCmlubGluZSBleHRlbmRzIGZ1biBhc1NsaWNlKHNlbGY6IENlbGwpOiBT' +
+ 'bGljZSB7CiAgICByZXR1cm4gc2VsZi5iZWdpblBhcnNlKCk7Cn0KCmlubGluZSBleHRlbmRzIGZ1biBhc0NlbGwoc2VsZjogU2xpY2UpOiBDZWxsIHsKICAgIHJldHVy' +
+ 'biBiZWdpbkNlbGwoKQogICAgICAgIC5zdG9yZVNsaWNlKHNlbGYpCiAgICAgICAgLmVuZENlbGwoKTsKfQoKaW5saW5lIGV4dGVuZHMgZnVuIGFzQ2VsbChzZWxmOiBC' +
+ 'dWlsZGVyKTogQ2VsbCB7CiAgICByZXR1cm4gc2VsZi5lbmRDZWxsKCk7Cn0KCmlubGluZSBmdW4gZW1wdHlDZWxsKCk6IENlbGwgewogICAgcmV0dXJuIGJlZ2luQ2Vs' +
+ 'bCgpLmVuZENlbGwoKTsKfQoKaW5saW5lIGZ1biBlbXB0eVNsaWNlKCk6IFNsaWNlIHsKICAgIHJldHVybiBlbXB0eUNlbGwoKS5hc1NsaWNlKCk7Cn0KCmFzbSBmdW4g' +
+ 'YWRkcmVzc05vbmUoKTogQWRkcmVzcz8geyBiezAwfSBQVVNIU0xJQ0UgfQoKc3RydWN0IERhdGFTaXplIHsKICAgIGNlbGxzOiBJbnQ7CiAgICBiaXRzOiBJbnQ7CiAg' +
+ 'ICByZWZzOiBJbnQ7Cn0KCmFzbSBleHRlbmRzIGZ1biBjb21wdXRlRGF0YVNpemUoc2VsZjogQ2VsbCwgbWF4Q2VsbHM6IEludCk6IERhdGFTaXplIHsgQ0RBVEFTSVpF' +
+ 'IH0KCmFzbSBleHRlbmRzIGZ1biBjb21wdXRlRGF0YVNpemUoc2VsZjogU2xpY2UsIG1heENlbGxzOiBJbnQpOiBEYXRhU2l6ZSB7IFNEQVRBU0laRSB9Cgphc20gZXh0' +
+ 'ZW5kcyBmdW4gZGVwdGgoc2VsZjogQ2VsbCk6IEludCB7IENERVBUSCB9Cgo=';
files['std/config.tact'] =
'YXNtIGZ1biBnZXRDb25maWdQYXJhbShpZDogSW50KTogQ2VsbD8geyBDT05GSUdPUFRQQVJBTSB9Cg==';
files['std/context.tact'] =
@@ -219,108 +226,109 @@ files['std/contract.tact'] =
'YWxjdWxhdGVzIGFuZCByZXR1cm5zIHRoZSBzdG9yYWdlIGZlZSBpbiBuYW5vVG9uY29pbnMgYEludGAgZm9yIHN0b3JpbmcgYSBjb250cmFjdCB3aXRoIGEgZ2l2ZW4g' +
'bnVtYmVyIG9mIGBjZWxsc2AgYW5kIGBiaXRzYCBmb3IgYSBudW1iZXIgb2YgYHNlY29uZHNgLiBVc2VzIHRoZSBwcmljZXMgb2YgdGhlIG1hc3RlcmNoYWluIGlmIGBp' +
'c01hc3RlcmNoYWluYCBpcyBgdHJ1ZWAsIG90aGVyd2lzZSB0aGUgcHJpY2VzIG9mIHRoZSBiYXNlY2hhaW4uIFRoZSBjdXJyZW50IHByaWNlcyBhcmUgb2J0YWluZWQg' +
- 'ZnJvbSB0aGUgY29uZmlnIHBhcmFtIDE4IG9mIFRPTiBCbG9ja2NoYWluLgovLy8KLy8vIE5vdGUsIHRoYXQgdGhlIHZhbHVlcyBvZiBgY2VsbHNgIGFuZCBgYml0c2Ag' +
- 'YXJlIHRha2VuIG1vZHVsbyB0aGVpciBtYXhpbXVtIHZhbHVlcyBwbHVzIDEuIFRoYXQgaXMsIHNwZWNpZnlpbmcgdmFsdWVzIGhpZ2hlciB0aGFuIHRob3NlIGxpc3Rl' +
- 'ZCBpbiBhY2NvdW50IHN0YXRlIGxpbWl0cyAoYG1heF9hY2Nfc3RhdGVfY2VsbHNgIGFuZCBgbWF4X2FjY19zdGF0ZV9iaXRzYCkgd2lsbCBoYXZlIHRoZSBzYW1lIHJl' +
- 'c3VsdCBhcyB3aXRoIHNwZWNpZnlpbmcgdGhlIGV4YWN0IGxpbWl0cy4gSW4gYWRkaXRpb24sIG1ha2Ugc3VyZSB5b3UgdGFrZSBpbnRvIGFjY291bnQgdGhlIGRlZHVw' +
- 'bGljYXRpb24gb2YgY2VsbHMgd2l0aCB0aGUgc2FtZSBoYXNoLgovLy8KLy8vIEF0dGVtcHRzIHRvIHNwZWNpZnkgbmVnYXRpdmUgbnVtYmVyIG9mIGBjZWxsc2AsIGBi' +
- 'aXRzYCBvciBgc2Vjb25kc2AgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhpdCBjb2RlIDU6IGBJbnRlZ2VyIG91dCBvZiBleHBlY3RlZCByYW5nZWAuCi8vLwovLy8g' +
- 'YGBgdGFjdAovLy8gZnVuIGV4YW1wbGUoKSB7Ci8vLyAgICAgbGV0IGZlZTogSW50ID0gZ2V0U3RvcmFnZUZlZSgxXzAwMCwgMV8wMDAsIDFfMDAwLCBmYWxzZSk7Ci8v' +
- 'LyB9Ci8vLyBgYGAKLy8vCi8vLyBTZWU6Ci8vLyAqIGh0dHBzOi8vZG9jcy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldHN0b3JhZ2VmZWUKLy8vICog' +
- 'aHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0c2ltcGxlc3RvcmFnZWZlZQovLy8KYXNtIGZ1biBnZXRTdG9yYWdlRmVlKGNlbGxz' +
- 'OiBJbnQsIGJpdHM6IEludCwgc2Vjb25kczogSW50LCBpc01hc3RlcmNoYWluOiBCb29sKTogSW50IHsgR0VUU1RPUkFHRUZFRSB9CgovLy8gR2xvYmFsIGZ1bmN0aW9u' +
- 'LiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBDYWxjdWxhdGVzIGFuZCByZXR1cm5zIHRoZSBjb21wdXRlIGZlZSBpbiBuYW5vVG9uY29pbnMgYElu' +
- 'dGAgZm9yIGEgdHJhbnNhY3Rpb24gdGhhdCBjb25zdW1lZCBgZ2FzVXNlZGAgYW1vdW50IG9mIGdhcy4gVXNlcyB0aGUgcHJpY2VzIG9mIHRoZSBtYXN0ZXJjaGFpbiBp' +
- 'ZiBgaXNNYXN0ZXJjaGFpbmAgaXMgYHRydWVgLCBvdGhlcndpc2UgdGhlIHByaWNlcyBvZiB0aGUgYmFzZWNoYWluLiBUaGUgY3VycmVudCBwcmljZXMgYXJlIG9idGFp' +
- 'bmVkIGZyb20gdGhlIGNvbmZpZyBwYXJhbSAyMCBmb3IgdGhlIG1hc3RlcmNoYWluIGFuZCBjb25maWcgcGFyYW0gMjEgZm9yIHRoZSBiYXNlY2hhaW4gb2YgVE9OIEJs' +
- 'b2NrY2hhaW4uCi8vLwovLy8gV2hlbiB0aGUgYGdhc1VzZWRgIGlzIGxlc3MgdGhhbiBhIGNlcnRhaW4gdGhyZXNob2xkIGNhbGxlZCBgZmxhdF9nYXNfbGltaXRgLCB0' +
- 'aGVyZSdzIGEgbWluaW11bSBwcmljZSB0byBwYXkgYmFzZWQgb24gdGhlIHZhbHVlIG9mIGBmbGF0X2dhc19wcmljZWAuIFRoZSBsZXNzIGdhcyBpcyB1c2VkIGJlbG93' +
- 'IHRoaXMgdGhyZXNob2xkLCB0aGUgaGlnaGVyIHRoZSBtaW5pbXVtIHByaWNlIHdpbGwgYmUuIFNlZSB0aGUgZXhhbXBsZSBmb3IgYGdldFNpbXBsZUNvbXB1dGVGZWUo' +
- 'KWAgdG8gZGVyaXZlIHRoYXQgdGhyZXNob2xkLgovLy8KLy8vIEF0dGVtcHRzIHRvIHNwZWNpZnkgbmVnYXRpdmUgdmFsdWUgb2YgYGdhc1VzZWRgIHRocm93IGFuIGV4' +
- 'Y2VwdGlvbiB3aXRoIGV4aXQgY29kZSA1OiBgSW50ZWdlciBvdXQgb2YgZXhwZWN0ZWQgcmFuZ2VgLgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewov' +
- 'Ly8gICAgIGxldCBmZWU6IEludCA9IGdldENvbXB1dGVGZWUoMV8wMDAsIGZhbHNlKTsKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZTogaHR0cHM6Ly9kb2NzLnRhY3Qt' +
- 'bGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0Y29tcHV0ZWZlZQovLy8KYXNtIGZ1biBnZXRDb21wdXRlRmVlKGdhc1VzZWQ6IEludCwgaXNNYXN0ZXJjaGFpbjog' +
- 'Qm9vbCk6IEludCB7IEdFVEdBU0ZFRSB9CgovLy8gR2xvYmFsIGZ1bmN0aW9uLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBTaW1pbGFyIHRvIGBn' +
- 'ZXRDb21wdXRlRmVlKClgLCBidXQgd2l0aG91dCB0aGUgYGZsYXRfZ2FzX3ByaWNlYCwgaS5lLiB3aXRob3V0IGEgbWluaW11bSBwcmljZSB0byBwYXkgaWYgdGhlIGBn' +
- 'YXNVc2VkYCBpcyBsZXNzIHRoYW4gYSBjZXJ0YWluIHRocmVzaG9sZCBjYWxsZWQgYGZsYXRfZ2FzX2xpbWl0YC4gQ2FsY3VsYXRlcyBhbmQgcmV0dXJucyBvbmx5IHRo' +
- 'ZSBgZ2FzVXNlZGAgdGltZXMgdGhlIGN1cnJlbnQgZ2FzIHByaWNlLgovLy8KLy8vIEF0dGVtcHRzIHRvIHNwZWNpZnkgbmVnYXRpdmUgbnVtYmVyIG9mIGBjZWxsc2As' +
- 'IGBiaXRzYCBvciBgc2Vjb25kc2AgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhpdCBjb2RlIDU6IGBJbnRlZ2VyIG91dCBvZiBleHBlY3RlZCByYW5nZWAuCi8vLwov' +
- 'Ly8gYGBgdGFjdAovLy8gZnVuIGV4YW1wbGUoKSB7Ci8vLyAgICAgbGV0IGZlZSA9IGdldENvbXB1dGVGZWUoMCwgZmFsc2UpOwovLy8gICAgIGxldCBmZWVOb0ZsYXQg' +
- 'PSBnZXRTaW1wbGVDb21wdXRlRmVlKDAsIGZhbHNlKTsKLy8vICAgICBsZXQgbWF4RmxhdFByaWNlID0gZmVlIC0gZmVlTm9GbGF0OwovLy8gfQovLy8gYGBgCi8vLwov' +
- 'Ly8gU2VlOgovLy8gKiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1hZHZhbmNlZCNnZXRzaW1wbGVzdG9yYWdlZmVlCi8vLyAqIGh0dHBzOi8vZG9j' +
- 'cy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldHN0b3JhZ2VmZWUKLy8vCmFzbSBmdW4gZ2V0U2ltcGxlQ29tcHV0ZUZlZShnYXNVc2VkOiBJbnQsIGlz' +
- 'TWFzdGVyY2hhaW46IEJvb2wpOiBJbnQgeyBHRVRHQVNGRUVTSU1QTEUgfQoKLy8vIEdsb2JhbCBmdW5jdGlvbi4gQXZhaWxhYmxlIHNpbmNlIFRhY3QgMS41LjAuCi8v' +
- 'LwovLy8gQ2FsY3VsYXRlcyBhbmQgcmV0dXJucyB0aGUgZm9yd2FyZCBmZWUgaW4gbmFub1RvbmNvaW5zIGBJbnRgIGZvciBhbiBvdXRnb2luZyBtZXNzYWdlIGNvbnNp' +
- 'c3Rpbmcgb2YgYSBnaXZlbiBudW1iZXIgb2YgYGNlbGxzYCBhbmQgYGJpdHNgLiBVc2VzIHRoZSBwcmljZXMgb2YgdGhlIG1hc3RlcmNoYWluIGlmIGBpc01hc3RlcmNo' +
- 'YWluYCBpcyBgdHJ1ZXs6dGFjdH1gLCBvdGhlcndpc2UgdGhlIHByaWNlcyBvZiB0aGUgYmFzZWNoYWluLiBUaGUgY3VycmVudCBwcmljZXMgYXJlIG9idGFpbmVkIGZy' +
- 'b20gdGhlIGNvbmZpZyBwYXJhbSAyNCBmb3IgdGhlIG1hc3RlcmNoYWluIGFuZCBjb25maWcgcGFyYW0gMjUgZm9yIHRoZSBiYXNlY2hhaW4gb2YgVE9OIEJsb2NrY2hh' +
- 'aW4uCi8vLwovLy8gSWYgYm90aCB0aGUgc291cmNlIGFuZCB0aGUgZGVzdGluYXRpb24gYWRkcmVzc2VzIGFyZSBpbiB0aGUgYmFzZWNoYWluLCB0aGVuIHNwZWNpZnkg' +
- 'YGlzTWFzdGVyY2hhaW5gIGFzIGBmYWxzZWAuIE90aGVyd2lzZSwgc3BlY2lmeSBgdHJ1ZWAuCi8vLwovLy8gTm90ZSwgdGhhdCB0aGUgdmFsdWVzIG9mIGBjZWxsc2Ag' +
- 'YW5kIGBiaXRzYCBhcmUgdGFrZW4gbW9kdWxvIHRoZWlyIG1heGltdW0gdmFsdWVzIHBsdXMgMS4gVGhhdCBpcywgc3BlY2lmeWluZyB2YWx1ZXMgaGlnaGVyIHRoYW4g' +
- 'dGhvc2UgbGlzdGVkIGluIGFjY291bnQgc3RhdGUgbGltaXRzIChgbWF4X21zZ19jZWxsc2AgYW5kIGBtYXhfbXNnX2JpdHNgKSB3aWxsIGhhdmUgdGhlIHNhbWUgcmVz' +
- 'dWx0IGFzIHdpdGggc3BlY2lmeWluZyB0aGUgZXhhY3QgbGltaXRzLgovLy8KLy8vIEhvd2V2ZXIsIHJlZ2FyZGxlc3Mgb2YgdGhlIHZhbHVlcyBvZiBgY2VsbHNgIGFu' +
- 'ZCBgYml0c2AsIHRoaXMgZnVuY3Rpb24gYWx3YXlzIGFkZHMgdGhlIG1pbmltdW0gcHJpY2UgYmFzZWQgb24gdGhlIHZhbHVlIG9mIGBsdW1wX3ByaWNlYC4gU2VlIHRo' +
- 'ZSBleGFtcGxlIGZvciBbYGdldFNpbXBsZUZvcndhcmRGZWUoKXs6dGFjdH1gXSgjZ2V0c2ltcGxlZm9yd2FyZGZlZSkgdG8gZGVyaXZlIGl0LiBJbiBhZGRpdGlvbiwg' +
- 'bWFrZSBzdXJlIHlvdSB0YWtlIGludG8gYWNjb3VudCB0aGUgZGVkdXBsaWNhdGlvbiBvZiBjZWxscyB3aXRoIHRoZSBzYW1lIGhhc2gsIHNpbmNlIGZvciBleGFtcGxl' +
- 'IHRoZSByb290IGNlbGwgYW5kIGl0cyBkYXRhIGJpdHMgZG9uJ3QgY291bnQgdG93YXJkcyB0aGUgZm9yd2FyZCBmZWUgYW5kIGFyZSBjb3ZlcmVkIGJ5IHRoZSBgbHVt' +
- 'cF9wcmljZWAuCi8vLwovLy8gQXR0ZW1wdHMgdG8gc3BlY2lmeSBuZWdhdGl2ZSBudW1iZXIgb2YgYGNlbGxzYCBvciBgYml0c2AgdGhyb3cgYW4gZXhjZXB0aW9uIHdp' +
- 'dGggZXhpdCBjb2RlIDU6IGBJbnRlZ2VyIG91dCBvZiBleHBlY3RlZCByYW5nZWAuCi8vLwovLy8gYGBgdGFjdAovLy8gZnVuIGV4YW1wbGUoKSB7Ci8vLyAgICAgbGV0' +
- 'IGZlZTogSW50ID0gZ2V0Rm9yd2FyZEZlZSgxXzAwMCwgMV8wMDAsIGZhbHNlKTsKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRh' +
- 'Y3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0Zm9yd2FyZGZlZQovLy8gKiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1hZHZhbmNlZCNn' +
- 'ZXRzaW1wbGVmb3J3YXJkZmVlCi8vLyAqIGh0dHBzOi8vZG9jcy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldG9yaWdpbmFsZndkZmVlCi8vLwphc20g' +
- 'ZnVuIGdldEZvcndhcmRGZWUoY2VsbHM6IEludCwgYml0czogSW50LCBpc01hc3RlcmNoYWluOiBCb29sKTogSW50IHsgR0VURk9SV0FSREZFRSB9CgovLy8gR2xvYmFs' +
- 'IGZ1bmN0aW9uLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBTaW1pbGFyIHRvIGBnZXRGb3J3YXJkRmVlKClgLCBidXQgd2l0aG91dCB0aGUgYGx1' +
- 'bXBfcHJpY2VgLCBpLmUuIHdpdGhvdXQgdGhlIG1pbmltdW0gcHJpY2UgdG8gcGF5IHJlZ2FyZGxlc3Mgb2YgdGhlIGFtb3VudCBvZiBgY2VsbHNgIG9yIGBiaXRzYC4g' +
- 'Q2FsY3VsYXRlcyBhbmQgcmV0dXJucyBvbmx5IHRoZSBgY2VsbHNgIHRpbWVzIHRoZSBjdXJyZW50IGNlbGwgcHJpY2UgcGx1cyBgYml0c2AgdGltZXMgdGhlIGN1cnJl' +
- 'bnQgYml0IHByaWNlLgovLy8KLy8vIEF0dGVtcHRzIHRvIHNwZWNpZnkgbmVnYXRpdmUgbnVtYmVyIG9mIGBjZWxsc2Agb3IgYGJpdHNgIHRocm93IGFuIGV4Y2VwdGlv' +
- 'biB3aXRoIGV4aXQgY29kZSA1OiBgSW50ZWdlciBvdXQgb2YgZXhwZWN0ZWQgcmFuZ2VgLgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAg' +
- 'IGxldCBmZWUgPSBnZXRGb3J3YXJkRmVlKDFfMDAwLCAxXzAwMCwgZmFsc2UpOwovLy8gICAgIGxldCBmZWVOb0x1bXAgPSBnZXRTaW1wbGVGb3J3YXJkRmVlKDFfMDAw' +
- 'LCAxXzAwMCwgZmFsc2UpOwovLy8gICAgIGxldCBsdW1wUHJpY2UgPSBmZWUgLSBmZWVOb0x1bXA7Ci8vLyB9Ci8vLyBgYGAKLy8vCi8vLyBTZWU6Ci8vLyAqIGh0dHBz' +
- 'Oi8vZG9jcy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldHNpbXBsZWZvcndhcmRmZWUKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVm' +
- 'L2NvcmUtYWR2YW5jZWQjZ2V0Zm9yd2FyZGZlZQovLy8KYXNtIGZ1biBnZXRTaW1wbGVGb3J3YXJkRmVlKGNlbGxzOiBJbnQsIGJpdHM6IEludCwgaXNNYXN0ZXJjaGFp' +
- 'bjogQm9vbCk6IEludCB7IEdFVEZPUldBUkRGRUVTSU1QTEUgfQoKLy8vIEdsb2JhbCBmdW5jdGlvbi4gQXZhaWxhYmxlIHNpbmNlIFRhY3QgMS41LjAuCi8vLwovLy8g' +
- 'Q2FsY3VsYXRlcyBhbmQgcmV0dXJucyB0aGUgc28tY2FsbGVkIF9vcmlnaW5hbF8gZm9yd2FyZCBmZWUgaW4gbmFub1RvbmNvaW5zIGBJbnRgIGZvciBhbiBvdXRnb2lu' +
- 'ZyBtZXNzYWdlIGJhc2VkIG9uIHRoZSBgZndkRmVlYCBvYnRhaW5lZCBmcm9tIHRoZSBpbmNvbWluZyBtZXNzYWdlLiBJZiBib3RoIHRoZSBzb3VyY2UgYW5kIHRoZSBk' +
- 'ZXN0aW5hdGlvbiBhZGRyZXNzZXMgYXJlIGluIHRoZSBiYXNlY2hhaW4sIHRoZW4gc3BlY2lmeSBgaXNNYXN0ZXJjaGFpbmAgYXMgYGZhbHNlYC4gT3RoZXJ3aXNlLCBz' +
- 'cGVjaWZ5IGB0cnVlYC4KLy8vCi8vLyBUaGlzIGZ1bmN0aW9uIGlzIHVzZWZ1bCB3aGVuIHRoZSBvdXRnb2luZyBtZXNzYWdlIGRlcGVuZHMgaGVhdmlseSBvbiB0aGUg' +
- 'c3RydWN0dXJlIG9mIHRoZSBpbmNvbWluZyBtZXNzYWdlLCBzbyBtdWNoIHNvIHRoYXQgeW91IGNhbm5vdCBmdWxseSBwcmVkaWN0IHRoZSBmZWUgdXNpbmcgYGdldEZv' +
- 'cndhcmRGZWUoKWAgYWxvbmUuIEV2ZW4gaWYgeW91IGNvdWxkLCBjYWxjdWxhdGluZyB0aGUgZXhhY3QgZmVlIHdpdGggbmFub1RvbmNvaW4tbGV2ZWwgcHJlY2lzaW9u' +
- 'IGNhbiBiZSB2ZXJ5IGV4cGVuc2l2ZSwgc28gdGhlIGFwcHJveGltYXRlIHZhbHVlIGdpdmVuIGJ5IHRoaXMgZnVuY3Rpb24gaXMgb2Z0ZW4gZ29vZCBlbm91Z2guCi8v' +
- 'LwovLy8gQXR0ZW1wdHMgdG8gc3BlY2lmeSBhIG5lZ2F0aXZlIHZhbHVlIG9mIGBmd2RGZWVgIHRocm93IGFuIGV4Y2VwdGlvbiB3aXRoIGV4aXQgY29kZSA1OiBgSW50' +
- 'ZWdlciBvdXQgb2YgZXhwZWN0ZWQgcmFuZ2VgLgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCBmd2RGZWU6IEludCA9IGNvbnRl' +
- 'eHQoKS5yZWFkRm9yd2FyZEZlZSgpOwovLy8gICAgIGxldCBvcmlnRmVlOiBJbnQgPSBnZXRPcmlnaW5hbEZ3ZEZlZShmZWUsIGZhbHNlKTsKLy8vIH0KLy8vIGBgYAov' +
- 'Ly8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0b3JpZ2luYWxmd2RmZWUKLy8vICogaHR0cHM6Ly9k' +
- 'b2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0Zm9yd2FyZGZlZQovLy8gKiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1hZHZh' +
- 'bmNlZCNjb250ZXh0cmVhZGZvcndhcmRmZWUKLy8vCmFzbSBmdW4gZ2V0T3JpZ2luYWxGd2RGZWUoZndkRmVlOiBJbnQsIGlzTWFzdGVyY2hhaW46IEJvb2wpOiBJbnQg' +
- 'eyBHRVRPUklHSU5BTEZXREZFRSB9CgovLy8gU3RydWN0IHJlcHJlc2VudGluZyB0aGUgc3RhbmRhcmQgYWRkcmVzcyBvbiBUT04gQmxvY2tjaGFpbiB3aXRoIHNpZ25l' +
- 'ZCA4LWJpdCBgd29ya2NoYWluYCBJRCBhbmQgYW4gdW5zaWduZWQgMjU2LWJpdCBgYWRkcmVzc2AgaW4gdGhlIHNwZWNpZmllZCBgd29ya2NoYWluYC4gQXZhaWxhYmxl' +
- 'IHNpbmNlIFRhY3QgMS41LjAuCi8vLwovLy8gQXQgdGhlIG1vbWVudCwgb25seSBgd29ya2NoYWluYCBJRHMgdXNlZCBvbiBUT04gYXJlIDAgb2YgdGhlIGJhc2VjaGFp' +
- 'biBhbmQgLTEgb2YgdGhlIG1hc3RlcmNoYWluLgovLy8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjcGFy' +
- 'c2VzdGRhZGRyZXNzCi8vLyAqIGh0dHBzOi8vZ2l0aHViLmNvbS90b24tYmxvY2tjaGFpbi90b24vYmxvYi9tYXN0ZXIvY3J5cHRvL2Jsb2NrL2Jsb2NrLnRsYiNMMTA1' +
- 'LUwxMDYKLy8vCnN0cnVjdCBTdGRBZGRyZXNzIHsKICAgIHdvcmtjaGFpbjogSW50IGFzIGludDg7CiAgICBhZGRyZXNzOiBJbnQgYXMgdWludDI1NjsKfQoKLy8vIFN0' +
- 'cnVjdCByZXByZXNlbnRpbmcgdGhlIGFkZHJlc3Mgb2YgdmFyaWFibGUgbGVuZ3RoIHdpdGggc2lnbmVkIDMyLWJpdCBgd29ya2NoYWluYCBJRCBhbmQgYSBgU2xpY2Vg' +
- 'IGNvbnRhaW5pbmcgdW5zaWduZWQgYGFkZHJlc3NgIGluIHRoZSBzcGVjaWZpZWQgYHdvcmtjaGFpbmAuIEF2YWlsYWJsZSBzaW5jZSBUYWN0IDEuNS4wLgovLy8KLy8v' +
- 'IFZhcmlhYmxlLWxlbmd0aCBhZGRyZXNzZXMgYXJlIGludGVuZGVkIGZvciBmdXR1cmUgZXh0ZW5zaW9ucywgYW5kIHdoaWxlIHZhbGlkYXRvcnMgbXVzdCBiZSByZWFk' +
- 'eSB0byBhY2NlcHQgdGhlbSBpbiBpbmJvdW5kIG1lc3NhZ2VzLCB0aGUgc3RhbmRhcmQgKG5vbi12YXJpYWJsZSkgYWRkcmVzc2VzIGFyZSB1c2VkIHdoZW5ldmVyIHBv' +
- 'c3NpYmxlLgovLy8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjcGFyc2V2YXJhZGRyZXNzCi8vLyAqIGh0' +
- 'dHBzOi8vZ2l0aHViLmNvbS90b24tYmxvY2tjaGFpbi90b24vYmxvYi9tYXN0ZXIvY3J5cHRvL2Jsb2NrL2Jsb2NrLnRsYiNMMTA3LUwxMDgKLy8vCnN0cnVjdCBWYXJB' +
- 'ZGRyZXNzIHsKICAgIHdvcmtjaGFpbjogSW50IGFzIGludDMyOwogICAgYWRkcmVzczogU2xpY2U7Cn0KCi8vLyBBc3NlbWJseSBmdW5jdGlvbi4gQXZhaWxhYmxlIHNp' +
- 'bmNlIFRhY3QgMS41LjAuCi8vLwovLy8gQ29udmVydHMgYSBgU2xpY2VgIGNvbnRhaW5pbmcgYW4gYWRkcmVzcyBpbnRvIHRoZSBgU3RkQWRkcmVzc2AgU3RydWN0IGFu' +
- 'ZCByZXR1cm5zIGl0LgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCBhZGRyID0gYWRkcmVzcygiRVFEdEZwRXdjRkFFY1JlNW1M' +
- 'VmgyTjZDMHgtX2hKRU03VzYxX0pMblNGNzRwNHEyIik7Ci8vLyAgICAgbGV0IHBhcnNlZEFkZHIgPSBwYXJzZVN0ZEFkZHJlc3MoYWRkci5hc1NsaWNlKCkpOwovLy8K' +
- 'Ly8vICAgICBwYXJzZWRBZGRyLndvcmtjaGFpbjsgLy8gMAovLy8gICAgIHBhcnNlZEFkZHIuYWRkcmVzczsgICAvLyAxMDcuLi4yODcKLy8vIH0KLy8vIGBgYAovLy8K' +
- 'Ly8vIFNlZTogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjcGFyc2VzdGRhZGRyZXNzCi8vLwphc20gZnVuIHBhcnNlU3RkQWRkcmVz' +
- 'cyhzbGljZTogU2xpY2UpOiBTdGRBZGRyZXNzIHsgUkVXUklURVNUREFERFIgfQoKLy8vIEFzc2VtYmx5IGZ1bmN0aW9uLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUu' +
- 'MC4KLy8vCi8vLyBDb252ZXJ0cyBhIGBTbGljZWAgY29udGFpbmluZyBhbiBhZGRyZXNzIG9mIHZhcmlhYmxlIGxlbmd0aCBpbnRvIHRoZSBgVmFyQWRkcmVzc2AgU3Ry' +
- 'dWN0IGFuZCByZXR1cm5zIGl0LgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCB2YXJBZGRyU2xpY2UgPSBiZWdpbkNlbGwoKQov' +
- 'Ly8gICAgICAgICAuc3RvcmVVaW50KDYsIDMpICAgICAvLyB0byByZWNvZ25pemUgdGhlIGZvbGxvd2luZyBhcyBhIFZhckFkZHJlc3MKLy8vICAgICAgICAgLnN0b3Jl' +
- 'VWludCgxMjMsIDkpICAgLy8gbWFrZSBhZGRyZXNzIG9jY3VweSAxMjMgYml0cwovLy8gICAgICAgICAuc3RvcmVVaW50KDIzNCwgMzIpICAvLyBzcGVjaWZ5IHdvcmtj' +
- 'aGFpbiBJRCBvZiAyMzQKLy8vICAgICAgICAgLnN0b3JlVWludCgzNDUsIDEyMykgLy8gc3BlY2lmeSBhZGRyZXNzIG9mIDM0NQovLy8gICAgICAgICAuYXNTbGljZSgp' +
- 'OwovLy8gICAgIGxldCBwYXJzZWRWYXJBZGRyID0gcGFyc2VWYXJBZGRyZXNzKHZhckFkZHJTbGljZSk7Ci8vLwovLy8gICAgIHBhcnNlZFZhckFkZHIud29ya2NoYWlu' +
- 'OyAgICAgICAgICAgICAvLyAyMzQKLy8vICAgICBwYXJzZWRWYXJBZGRyLmFkZHJlc3M7ICAgICAgICAgICAgICAgLy8gQ1N7Q2VsbHswMDIuLi4yYjN9IGJpdHM6IDQ0' +
- 'Li4xNjc7IHJlZnM6IDAuLjB9Ci8vLyAgICAgcGFyc2VkVmFyQWRkci5hZGRyZXNzLmxvYWRVaW50KDEyMyk7IC8vIDM0NQovLy8gfQovLy8gYGBgCi8vLwovLy8gU2Vl' +
- 'OiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1hZHZhbmNlZCNwYXJzZXZhcmFkZHJlc3MKLy8vCmFzbSBmdW4gcGFyc2VWYXJBZGRyZXNzKHNsaWNl' +
- 'OiBTbGljZSk6IFZhckFkZHJlc3MgeyBSRVdSSVRFVkFSQUREUiB9Cg==';
+ 'ZnJvbSB0aGUgY29uZmlnIHBhcmFtIDE4IG9mIFRPTiBCbG9ja2NoYWluLgovLy8KLy8vIE5vdGUsIHRoYXQgc3BlY2lmeWluZyB2YWx1ZXMgb2YgYGNlbGxzYCBhbmQg' +
+ 'YGJpdHNgIGhpZ2hlciB0aGFuIHRoZWlyIG1heGltdW0gdmFsdWVzIGxpc3RlZCBpbiBhY2NvdW50IHN0YXRlIGxpbWl0cyAoYG1heF9hY2Nfc3RhdGVfY2VsbHNgIGFu' +
+ 'ZCBgbWF4X2FjY19zdGF0ZV9iaXRzYCkgd2lsbCBoYXZlIHRoZSBzYW1lIHJlc3VsdCBhcyB3aXRoIHNwZWNpZnlpbmcgdGhlIGV4YWN0IGxpbWl0cy4gSW4gYWRkaXRp' +
+ 'b24sIG1ha2Ugc3VyZSB5b3UgdGFrZSBpbnRvIGFjY291bnQgdGhlIGRlZHVwbGljYXRpb24gb2YgY2VsbHMgd2l0aCB0aGUgc2FtZSBoYXNoLgovLy8KLy8vIEF0dGVt' +
+ 'cHRzIHRvIHNwZWNpZnkgbmVnYXRpdmUgbnVtYmVyIG9mIGBjZWxsc2AsIGBiaXRzYCBvciBgc2Vjb25kc2AgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhpdCBjb2Rl' +
+ 'IDU6IGBJbnRlZ2VyIG91dCBvZiBleHBlY3RlZCByYW5nZWAuCi8vLwovLy8gYGBgdGFjdAovLy8gZnVuIGV4YW1wbGUoKSB7Ci8vLyAgICAgbGV0IGZlZTogSW50ID0g' +
+ 'Z2V0U3RvcmFnZUZlZSgxXzAwMCwgMV8wMDAsIDFfMDAwLCBmYWxzZSk7Ci8vLyB9Ci8vLyBgYGAKLy8vCi8vLyBTZWU6Ci8vLyAqIGh0dHBzOi8vZG9jcy50YWN0LWxh' +
+ 'bmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldHN0b3JhZ2VmZWUKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0c2lt' +
+ 'cGxlc3RvcmFnZWZlZQovLy8KYXNtIGZ1biBnZXRTdG9yYWdlRmVlKGNlbGxzOiBJbnQsIGJpdHM6IEludCwgc2Vjb25kczogSW50LCBpc01hc3RlcmNoYWluOiBCb29s' +
+ 'KTogSW50IHsgR0VUU1RPUkFHRUZFRSB9CgovLy8gR2xvYmFsIGZ1bmN0aW9uLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBDYWxjdWxhdGVzIGFu' +
+ 'ZCByZXR1cm5zIHRoZSBjb21wdXRlIGZlZSBpbiBuYW5vVG9uY29pbnMgYEludGAgZm9yIGEgdHJhbnNhY3Rpb24gdGhhdCBjb25zdW1lZCBgZ2FzVXNlZGAgYW1vdW50' +
+ 'IG9mIGdhcy4gVXNlcyB0aGUgcHJpY2VzIG9mIHRoZSBtYXN0ZXJjaGFpbiBpZiBgaXNNYXN0ZXJjaGFpbmAgaXMgYHRydWVgLCBvdGhlcndpc2UgdGhlIHByaWNlcyBv' +
+ 'ZiB0aGUgYmFzZWNoYWluLiBUaGUgY3VycmVudCBwcmljZXMgYXJlIG9idGFpbmVkIGZyb20gdGhlIGNvbmZpZyBwYXJhbSAyMCBmb3IgdGhlIG1hc3RlcmNoYWluIGFu' +
+ 'ZCBjb25maWcgcGFyYW0gMjEgZm9yIHRoZSBiYXNlY2hhaW4gb2YgVE9OIEJsb2NrY2hhaW4uCi8vLwovLy8gV2hlbiB0aGUgYGdhc1VzZWRgIGlzIGxlc3MgdGhhbiBh' +
+ 'IGNlcnRhaW4gdGhyZXNob2xkIGNhbGxlZCBgZmxhdF9nYXNfbGltaXRgLCB0aGVyZSdzIGEgbWluaW11bSBwcmljZSB0byBwYXkgYmFzZWQgb24gdGhlIHZhbHVlIG9m' +
+ 'IGBmbGF0X2dhc19wcmljZWAuIFRoZSBsZXNzIGdhcyBpcyB1c2VkIGJlbG93IHRoaXMgdGhyZXNob2xkLCB0aGUgaGlnaGVyIHRoZSBtaW5pbXVtIHByaWNlIHdpbGwg' +
+ 'YmUuIFNlZSB0aGUgZXhhbXBsZSBmb3IgYGdldFNpbXBsZUNvbXB1dGVGZWUoKWAgdG8gZGVyaXZlIHRoYXQgdGhyZXNob2xkLgovLy8KLy8vIEF0dGVtcHRzIHRvIHNw' +
+ 'ZWNpZnkgbmVnYXRpdmUgdmFsdWUgb2YgYGdhc1VzZWRgIHRocm93IGFuIGV4Y2VwdGlvbiB3aXRoIGV4aXQgY29kZSA1OiBgSW50ZWdlciBvdXQgb2YgZXhwZWN0ZWQg' +
+ 'cmFuZ2VgLgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCBmZWU6IEludCA9IGdldENvbXB1dGVGZWUoMV8wMDAsIGZhbHNlKTsK' +
+ 'Ly8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZTogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0Y29tcHV0ZWZlZQovLy8KYXNtIGZ1' +
+ 'biBnZXRDb21wdXRlRmVlKGdhc1VzZWQ6IEludCwgaXNNYXN0ZXJjaGFpbjogQm9vbCk6IEludCB7IEdFVEdBU0ZFRSB9CgovLy8gR2xvYmFsIGZ1bmN0aW9uLiBBdmFp' +
+ 'bGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBTaW1pbGFyIHRvIGBnZXRDb21wdXRlRmVlKClgLCBidXQgd2l0aG91dCB0aGUgYGZsYXRfZ2FzX3ByaWNlYCwg' +
+ 'aS5lLiB3aXRob3V0IGEgbWluaW11bSBwcmljZSB0byBwYXkgaWYgdGhlIGBnYXNVc2VkYCBpcyBsZXNzIHRoYW4gYSBjZXJ0YWluIHRocmVzaG9sZCBjYWxsZWQgYGZs' +
+ 'YXRfZ2FzX2xpbWl0YC4gQ2FsY3VsYXRlcyBhbmQgcmV0dXJucyBvbmx5IHRoZSBgZ2FzVXNlZGAgdGltZXMgdGhlIGN1cnJlbnQgZ2FzIHByaWNlLgovLy8KLy8vIEF0' +
+ 'dGVtcHRzIHRvIHNwZWNpZnkgbmVnYXRpdmUgbnVtYmVyIG9mIGBjZWxsc2AsIGBiaXRzYCBvciBgc2Vjb25kc2AgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhpdCBj' +
+ 'b2RlIDU6IGBJbnRlZ2VyIG91dCBvZiBleHBlY3RlZCByYW5nZWAuCi8vLwovLy8gYGBgdGFjdAovLy8gZnVuIGV4YW1wbGUoKSB7Ci8vLyAgICAgbGV0IGZlZSA9IGdl' +
+ 'dENvbXB1dGVGZWUoMCwgZmFsc2UpOwovLy8gICAgIGxldCBmZWVOb0ZsYXQgPSBnZXRTaW1wbGVDb21wdXRlRmVlKDAsIGZhbHNlKTsKLy8vICAgICBsZXQgbWF4Rmxh' +
+ 'dFByaWNlID0gZmVlIC0gZmVlTm9GbGF0OwovLy8gfQovLy8gYGBgCi8vLwovLy8gU2VlOgovLy8gKiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1h' +
+ 'ZHZhbmNlZCNnZXRzaW1wbGVzdG9yYWdlZmVlCi8vLyAqIGh0dHBzOi8vZG9jcy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldHN0b3JhZ2VmZWUKLy8v' +
+ 'CmFzbSBmdW4gZ2V0U2ltcGxlQ29tcHV0ZUZlZShnYXNVc2VkOiBJbnQsIGlzTWFzdGVyY2hhaW46IEJvb2wpOiBJbnQgeyBHRVRHQVNGRUVTSU1QTEUgfQoKLy8vIEds' +
+ 'b2JhbCBmdW5jdGlvbi4gQXZhaWxhYmxlIHNpbmNlIFRhY3QgMS41LjAuCi8vLwovLy8gQ2FsY3VsYXRlcyBhbmQgcmV0dXJucyB0aGUgZm9yd2FyZCBmZWUgaW4gbmFu' +
+ 'b1RvbmNvaW5zIGBJbnRgIGZvciBhbiBvdXRnb2luZyBtZXNzYWdlIGNvbnNpc3Rpbmcgb2YgYSBnaXZlbiBudW1iZXIgb2YgYGNlbGxzYCBhbmQgYGJpdHNgLiBVc2Vz' +
+ 'IHRoZSBwcmljZXMgb2YgdGhlIG1hc3RlcmNoYWluIGlmIGBpc01hc3RlcmNoYWluYCBpcyBgdHJ1ZXs6dGFjdH1gLCBvdGhlcndpc2UgdGhlIHByaWNlcyBvZiB0aGUg' +
+ 'YmFzZWNoYWluLiBUaGUgY3VycmVudCBwcmljZXMgYXJlIG9idGFpbmVkIGZyb20gdGhlIGNvbmZpZyBwYXJhbSAyNCBmb3IgdGhlIG1hc3RlcmNoYWluIGFuZCBjb25m' +
+ 'aWcgcGFyYW0gMjUgZm9yIHRoZSBiYXNlY2hhaW4gb2YgVE9OIEJsb2NrY2hhaW4uCi8vLwovLy8gSWYgYm90aCB0aGUgc291cmNlIGFuZCB0aGUgZGVzdGluYXRpb24g' +
+ 'YWRkcmVzc2VzIGFyZSBpbiB0aGUgYmFzZWNoYWluLCB0aGVuIHNwZWNpZnkgYGlzTWFzdGVyY2hhaW5gIGFzIGBmYWxzZWAuIE90aGVyd2lzZSwgc3BlY2lmeSBgdHJ1' +
+ 'ZWAuCi8vLwovLy8gTm90ZSwgdGhhdCBzcGVjaWZ5aW5nIHZhbHVlcyBvZiBgY2VsbHNgIGFuZCBgYml0c2AgaGlnaGVyIHRoYW4gdGhlaXIgbWF4aW11bSB2YWx1ZXMg' +
+ 'bGlzdGVkIGluIGFjY291bnQgc3RhdGUgbGltaXRzIChgbWF4X21zZ19jZWxsc2AgYW5kIGBtYXhfbXNnX2JpdHNgKSB3aWxsIGhhdmUgdGhlIHNhbWUgcmVzdWx0IGFz' +
+ 'IHdpdGggc3BlY2lmeWluZyB0aGUgZXhhY3QgbGltaXRzLgovLy8KLy8vIEhvd2V2ZXIsIHJlZ2FyZGxlc3Mgb2YgdGhlIHZhbHVlcyBvZiBgY2VsbHNgIGFuZCBgYml0' +
+ 'c2AsIHRoaXMgZnVuY3Rpb24gYWx3YXlzIGFkZHMgdGhlIG1pbmltdW0gcHJpY2UgYmFzZWQgb24gdGhlIHZhbHVlIG9mIGBsdW1wX3ByaWNlYC4gU2VlIHRoZSBleGFt' +
+ 'cGxlIGZvciBbYGdldFNpbXBsZUZvcndhcmRGZWUoKXs6dGFjdH1gXSgjZ2V0c2ltcGxlZm9yd2FyZGZlZSkgdG8gZGVyaXZlIGl0LiBJbiBhZGRpdGlvbiwgbWFrZSBz' +
+ 'dXJlIHlvdSB0YWtlIGludG8gYWNjb3VudCB0aGUgZGVkdXBsaWNhdGlvbiBvZiBjZWxscyB3aXRoIHRoZSBzYW1lIGhhc2gsIHNpbmNlIGZvciBleGFtcGxlIHRoZSBy' +
+ 'b290IGNlbGwgYW5kIGl0cyBkYXRhIGJpdHMgZG9uJ3QgY291bnQgdG93YXJkcyB0aGUgZm9yd2FyZCBmZWUgYW5kIGFyZSBjb3ZlcmVkIGJ5IHRoZSBgbHVtcF9wcmlj' +
+ 'ZWAuCi8vLwovLy8gQXR0ZW1wdHMgdG8gc3BlY2lmeSBuZWdhdGl2ZSBudW1iZXIgb2YgYGNlbGxzYCBvciBgYml0c2AgdGhyb3cgYW4gZXhjZXB0aW9uIHdpdGggZXhp' +
+ 'dCBjb2RlIDU6IGBJbnRlZ2VyIG91dCBvZiBleHBlY3RlZCByYW5nZWAuCi8vLwovLy8gYGBgdGFjdAovLy8gZnVuIGV4YW1wbGUoKSB7Ci8vLyAgICAgbGV0IGZlZTog' +
+ 'SW50ID0gZ2V0Rm9yd2FyZEZlZSgxXzAwMCwgMV8wMDAsIGZhbHNlKTsKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFu' +
+ 'Zy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0Zm9yd2FyZGZlZQovLy8gKiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1hZHZhbmNlZCNnZXRzaW1w' +
+ 'bGVmb3J3YXJkZmVlCi8vLyAqIGh0dHBzOi8vZG9jcy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldG9yaWdpbmFsZndkZmVlCi8vLwphc20gZnVuIGdl' +
+ 'dEZvcndhcmRGZWUoY2VsbHM6IEludCwgYml0czogSW50LCBpc01hc3RlcmNoYWluOiBCb29sKTogSW50IHsgR0VURk9SV0FSREZFRSB9CgovLy8gR2xvYmFsIGZ1bmN0' +
+ 'aW9uLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8vCi8vLyBTaW1pbGFyIHRvIGBnZXRGb3J3YXJkRmVlKClgLCBidXQgd2l0aG91dCB0aGUgYGx1bXBfcHJp' +
+ 'Y2VgLCBpLmUuIHdpdGhvdXQgdGhlIG1pbmltdW0gcHJpY2UgdG8gcGF5IHJlZ2FyZGxlc3Mgb2YgdGhlIGFtb3VudCBvZiBgY2VsbHNgIG9yIGBiaXRzYC4gQ2FsY3Vs' +
+ 'YXRlcyBhbmQgcmV0dXJucyBvbmx5IHRoZSBgY2VsbHNgIHRpbWVzIHRoZSBjdXJyZW50IGNlbGwgcHJpY2UgcGx1cyBgYml0c2AgdGltZXMgdGhlIGN1cnJlbnQgYml0' +
+ 'IHByaWNlLgovLy8KLy8vIEF0dGVtcHRzIHRvIHNwZWNpZnkgbmVnYXRpdmUgbnVtYmVyIG9mIGBjZWxsc2Agb3IgYGJpdHNgIHRocm93IGFuIGV4Y2VwdGlvbiB3aXRo' +
+ 'IGV4aXQgY29kZSA1OiBgSW50ZWdlciBvdXQgb2YgZXhwZWN0ZWQgcmFuZ2VgLgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCBm' +
+ 'ZWUgPSBnZXRGb3J3YXJkRmVlKDFfMDAwLCAxXzAwMCwgZmFsc2UpOwovLy8gICAgIGxldCBmZWVOb0x1bXAgPSBnZXRTaW1wbGVGb3J3YXJkRmVlKDFfMDAwLCAxXzAw' +
+ 'MCwgZmFsc2UpOwovLy8gICAgIGxldCBsdW1wUHJpY2UgPSBmZWUgLSBmZWVOb0x1bXA7Ci8vLyB9Ci8vLyBgYGAKLy8vCi8vLyBTZWU6Ci8vLyAqIGh0dHBzOi8vZG9j' +
+ 'cy50YWN0LWxhbmcub3JnL3JlZi9jb3JlLWFkdmFuY2VkI2dldHNpbXBsZWZvcndhcmRmZWUKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUt' +
+ 'YWR2YW5jZWQjZ2V0Zm9yd2FyZGZlZQovLy8KYXNtIGZ1biBnZXRTaW1wbGVGb3J3YXJkRmVlKGNlbGxzOiBJbnQsIGJpdHM6IEludCwgaXNNYXN0ZXJjaGFpbjogQm9v' +
+ 'bCk6IEludCB7IEdFVEZPUldBUkRGRUVTSU1QTEUgfQoKLy8vIEdsb2JhbCBmdW5jdGlvbi4gQXZhaWxhYmxlIHNpbmNlIFRhY3QgMS41LjAuCi8vLwovLy8gQ2FsY3Vs' +
+ 'YXRlcyBhbmQgcmV0dXJucyB0aGUgc28tY2FsbGVkIF9vcmlnaW5hbF8gZm9yd2FyZCBmZWUgaW4gbmFub1RvbmNvaW5zIGBJbnRgIGZvciBhbiBvdXRnb2luZyBtZXNz' +
+ 'YWdlIGJhc2VkIG9uIHRoZSBgZndkRmVlYCBvYnRhaW5lZCBmcm9tIHRoZSBpbmNvbWluZyBtZXNzYWdlLiBJZiBib3RoIHRoZSBzb3VyY2UgYW5kIHRoZSBkZXN0aW5h' +
+ 'dGlvbiBhZGRyZXNzZXMgYXJlIGluIHRoZSBiYXNlY2hhaW4sIHRoZW4gc3BlY2lmeSBgaXNNYXN0ZXJjaGFpbmAgYXMgYGZhbHNlYC4gT3RoZXJ3aXNlLCBzcGVjaWZ5' +
+ 'IGB0cnVlYC4KLy8vCi8vLyBUaGlzIGZ1bmN0aW9uIGlzIHVzZWZ1bCB3aGVuIHRoZSBvdXRnb2luZyBtZXNzYWdlIGRlcGVuZHMgaGVhdmlseSBvbiB0aGUgc3RydWN0' +
+ 'dXJlIG9mIHRoZSBpbmNvbWluZyBtZXNzYWdlLCBzbyBtdWNoIHNvIHRoYXQgeW91IGNhbm5vdCBmdWxseSBwcmVkaWN0IHRoZSBmZWUgdXNpbmcgYGdldEZvcndhcmRG' +
+ 'ZWUoKWAgYWxvbmUuIEV2ZW4gaWYgeW91IGNvdWxkLCBjYWxjdWxhdGluZyB0aGUgZXhhY3QgZmVlIHdpdGggbmFub1RvbmNvaW4tbGV2ZWwgcHJlY2lzaW9uIGNhbiBi' +
+ 'ZSB2ZXJ5IGV4cGVuc2l2ZSwgc28gdGhlIGFwcHJveGltYXRlIHZhbHVlIGdpdmVuIGJ5IHRoaXMgZnVuY3Rpb24gaXMgb2Z0ZW4gZ29vZCBlbm91Z2guCi8vLwovLy8g' +
+ 'QXR0ZW1wdHMgdG8gc3BlY2lmeSBhIG5lZ2F0aXZlIHZhbHVlIG9mIGBmd2RGZWVgIHRocm93IGFuIGV4Y2VwdGlvbiB3aXRoIGV4aXQgY29kZSA1OiBgSW50ZWdlciBv' +
+ 'dXQgb2YgZXhwZWN0ZWQgcmFuZ2VgLgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCBmd2RGZWU6IEludCA9IGNvbnRleHQoKS5y' +
+ 'ZWFkRm9yd2FyZEZlZSgpOwovLy8gICAgIGxldCBvcmlnRmVlOiBJbnQgPSBnZXRPcmlnaW5hbEZ3ZEZlZShmZWUsIGZhbHNlKTsKLy8vIH0KLy8vIGBgYAovLy8KLy8v' +
+ 'IFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0b3JpZ2luYWxmd2RmZWUKLy8vICogaHR0cHM6Ly9kb2NzLnRh' +
+ 'Y3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjZ2V0Zm9yd2FyZGZlZQovLy8gKiBodHRwczovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1hZHZhbmNlZCNj' +
+ 'b250ZXh0cmVhZGZvcndhcmRmZWUKLy8vCmFzbSBmdW4gZ2V0T3JpZ2luYWxGd2RGZWUoZndkRmVlOiBJbnQsIGlzTWFzdGVyY2hhaW46IEJvb2wpOiBJbnQgeyBHRVRP' +
+ 'UklHSU5BTEZXREZFRSB9CgovLy8gU3RydWN0IHJlcHJlc2VudGluZyB0aGUgc3RhbmRhcmQgYWRkcmVzcyBvbiBUT04gQmxvY2tjaGFpbiB3aXRoIHNpZ25lZCA4LWJp' +
+ 'dCBgd29ya2NoYWluYCBJRCBhbmQgYW4gdW5zaWduZWQgMjU2LWJpdCBgYWRkcmVzc2AgaW4gdGhlIHNwZWNpZmllZCBgd29ya2NoYWluYC4gQXZhaWxhYmxlIHNpbmNl' +
+ 'IFRhY3QgMS41LjAuCi8vLwovLy8gQXQgdGhlIG1vbWVudCwgb25seSBgd29ya2NoYWluYCBJRHMgdXNlZCBvbiBUT04gYXJlIDAgb2YgdGhlIGJhc2VjaGFpbiBhbmQg' +
+ 'LTEgb2YgdGhlIG1hc3RlcmNoYWluLgovLy8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjcGFyc2VzdGRh' +
+ 'ZGRyZXNzCi8vLyAqIGh0dHBzOi8vZ2l0aHViLmNvbS90b24tYmxvY2tjaGFpbi90b24vYmxvYi9tYXN0ZXIvY3J5cHRvL2Jsb2NrL2Jsb2NrLnRsYiNMMTA1LUwxMDYK' +
+ 'Ly8vCnN0cnVjdCBTdGRBZGRyZXNzIHsKICAgIHdvcmtjaGFpbjogSW50IGFzIGludDg7CiAgICBhZGRyZXNzOiBJbnQgYXMgdWludDI1NjsKfQoKLy8vIFN0cnVjdCBy' +
+ 'ZXByZXNlbnRpbmcgdGhlIGFkZHJlc3Mgb2YgdmFyaWFibGUgbGVuZ3RoIHdpdGggc2lnbmVkIDMyLWJpdCBgd29ya2NoYWluYCBJRCBhbmQgYSBgU2xpY2VgIGNvbnRh' +
+ 'aW5pbmcgdW5zaWduZWQgYGFkZHJlc3NgIGluIHRoZSBzcGVjaWZpZWQgYHdvcmtjaGFpbmAuIEF2YWlsYWJsZSBzaW5jZSBUYWN0IDEuNS4wLgovLy8KLy8vIFZhcmlh' +
+ 'YmxlLWxlbmd0aCBhZGRyZXNzZXMgYXJlIGludGVuZGVkIGZvciBmdXR1cmUgZXh0ZW5zaW9ucywgYW5kIHdoaWxlIHZhbGlkYXRvcnMgbXVzdCBiZSByZWFkeSB0byBh' +
+ 'Y2NlcHQgdGhlbSBpbiBpbmJvdW5kIG1lc3NhZ2VzLCB0aGUgc3RhbmRhcmQgKG5vbi12YXJpYWJsZSkgYWRkcmVzc2VzIGFyZSB1c2VkIHdoZW5ldmVyIHBvc3NpYmxl' +
+ 'LgovLy8KLy8vIFNlZToKLy8vICogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjcGFyc2V2YXJhZGRyZXNzCi8vLyAqIGh0dHBzOi8v' +
+ 'Z2l0aHViLmNvbS90b24tYmxvY2tjaGFpbi90b24vYmxvYi9tYXN0ZXIvY3J5cHRvL2Jsb2NrL2Jsb2NrLnRsYiNMMTA3LUwxMDgKLy8vCnN0cnVjdCBWYXJBZGRyZXNz' +
+ 'IHsKICAgIHdvcmtjaGFpbjogSW50IGFzIGludDMyOwogICAgYWRkcmVzczogU2xpY2U7Cn0KCi8vLyBBc3NlbWJseSBmdW5jdGlvbi4gQXZhaWxhYmxlIHNpbmNlIFRh' +
+ 'Y3QgMS41LjAuCi8vLwovLy8gQ29udmVydHMgYSBgU2xpY2VgIGNvbnRhaW5pbmcgYW4gYWRkcmVzcyBpbnRvIHRoZSBgU3RkQWRkcmVzc2AgU3RydWN0IGFuZCByZXR1' +
+ 'cm5zIGl0LgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCBhZGRyID0gYWRkcmVzcygiRVFEdEZwRXdjRkFFY1JlNW1MVmgyTjZD' +
+ 'MHgtX2hKRU03VzYxX0pMblNGNzRwNHEyIik7Ci8vLyAgICAgbGV0IHBhcnNlZEFkZHIgPSBwYXJzZVN0ZEFkZHJlc3MoYWRkci5hc1NsaWNlKCkpOwovLy8KLy8vICAg' +
+ 'ICBwYXJzZWRBZGRyLndvcmtjaGFpbjsgLy8gMAovLy8gICAgIHBhcnNlZEFkZHIuYWRkcmVzczsgICAvLyAxMDcuLi4yODcKLy8vIH0KLy8vIGBgYAovLy8KLy8vIFNl' +
+ 'ZTogaHR0cHM6Ly9kb2NzLnRhY3QtbGFuZy5vcmcvcmVmL2NvcmUtYWR2YW5jZWQjcGFyc2VzdGRhZGRyZXNzCi8vLwphc20gZnVuIHBhcnNlU3RkQWRkcmVzcyhzbGlj' +
+ 'ZTogU2xpY2UpOiBTdGRBZGRyZXNzIHsgUkVXUklURVNUREFERFIgfQoKLy8vIEFzc2VtYmx5IGZ1bmN0aW9uLiBBdmFpbGFibGUgc2luY2UgVGFjdCAxLjUuMC4KLy8v' +
+ 'Ci8vLyBDb252ZXJ0cyBhIGBTbGljZWAgY29udGFpbmluZyBhbiBhZGRyZXNzIG9mIHZhcmlhYmxlIGxlbmd0aCBpbnRvIHRoZSBgVmFyQWRkcmVzc2AgU3RydWN0IGFu' +
+ 'ZCByZXR1cm5zIGl0LgovLy8KLy8vIGBgYHRhY3QKLy8vIGZ1biBleGFtcGxlKCkgewovLy8gICAgIGxldCB2YXJBZGRyU2xpY2UgPSBiZWdpbkNlbGwoKQovLy8gICAg' +
+ 'ICAgICAuc3RvcmVVaW50KDYsIDMpICAgICAvLyB0byByZWNvZ25pemUgdGhlIGZvbGxvd2luZyBhcyBhIFZhckFkZHJlc3MKLy8vICAgICAgICAgLnN0b3JlVWludCgx' +
+ 'MjMsIDkpICAgLy8gbWFrZSBhZGRyZXNzIG9jY3VweSAxMjMgYml0cwovLy8gICAgICAgICAuc3RvcmVVaW50KDIzNCwgMzIpICAvLyBzcGVjaWZ5IHdvcmtjaGFpbiBJ' +
+ 'RCBvZiAyMzQKLy8vICAgICAgICAgLnN0b3JlVWludCgzNDUsIDEyMykgLy8gc3BlY2lmeSBhZGRyZXNzIG9mIDM0NQovLy8gICAgICAgICAuYXNTbGljZSgpOwovLy8g' +
+ 'ICAgIGxldCBwYXJzZWRWYXJBZGRyID0gcGFyc2VWYXJBZGRyZXNzKHZhckFkZHJTbGljZSk7Ci8vLwovLy8gICAgIHBhcnNlZFZhckFkZHIud29ya2NoYWluOyAgICAg' +
+ 'ICAgICAgICAvLyAyMzQKLy8vICAgICBwYXJzZWRWYXJBZGRyLmFkZHJlc3M7ICAgICAgICAgICAgICAgLy8gQ1N7Q2VsbHswMDIuLi4yYjN9IGJpdHM6IDQ0Li4xNjc7' +
+ 'IHJlZnM6IDAuLjB9Ci8vLyAgICAgcGFyc2VkVmFyQWRkci5hZGRyZXNzLmxvYWRVaW50KDEyMyk7IC8vIDM0NQovLy8gfQovLy8gYGBgCi8vLwovLy8gU2VlOiBodHRw' +
+ 'czovL2RvY3MudGFjdC1sYW5nLm9yZy9yZWYvY29yZS1hZHZhbmNlZCNwYXJzZXZhcmFkZHJlc3MKLy8vCmFzbSBmdW4gcGFyc2VWYXJBZGRyZXNzKHNsaWNlOiBTbGlj' +
+ 'ZSk6IFZhckFkZHJlc3MgeyBSRVdSSVRFVkFSQUREUiB9Cgphc20gZnVuIGN1ckx0KCk6IEludCB7IExUSU1FIH0KCmFzbSBmdW4gYmxvY2tMdCgpOiBJbnQgeyBCTE9D' +
+ 'S0xUIH0KCmFzbSBmdW4gc2V0R2FzTGltaXQobGltaXQ6IEludCkgeyBTRVRHQVNMSU1JVCB9Cgphc20gZnVuIGdldFNlZWQoKTogSW50IHsgUkFORFNFRUQgfQoKYXNt' +
+ 'IGZ1biBzZXRTZWVkKHNlZWQ6IEludCkgeyBTRVRSQU5EIH0KCmFzbSBmdW4gbXlDb2RlKCk6IENlbGwgeyBNWUNPREUgfQo=';
files['std/crypto.tact'] =
'YXNtIGV4dGVuZHMgZnVuIGhhc2goc2VsZjogQ2VsbCk6IEludCB7IEhBU0hDVSB9Cgphc20gZXh0ZW5kcyBmdW4gaGFzaChzZWxmOiBTbGljZSk6IEludCB7IEhBU0hT' +
'VSB9Cgphc20gZnVuIGNoZWNrU2lnbmF0dXJlKGhhc2g6IEludCwgc2lnbmF0dXJlOiBTbGljZSwgcHVibGljX2tleTogSW50KTogQm9vbCB7IENIS1NJR05VIH0KCmFz' +
@@ -348,9 +356,18 @@ files['std/math.tact'] =
'YW5kb21JbnQoKTogSW50IHsKICAgIG5hdGl2ZVByZXBhcmVSYW5kb20oKTsKICAgIHJldHVybiBuYXRpdmVSYW5kb20oKTsKfQoKaW5saW5lIGZ1biByYW5kb20obWlu' +
'OiBJbnQsIG1heDogSW50KTogSW50IHsKICAgIG5hdGl2ZVByZXBhcmVSYW5kb20oKTsKICAgIHJldHVybiBtaW4gKyBuYXRpdmVSYW5kb21JbnRlcnZhbChtYXggLSBt' +
'aW4pOwp9CgovLyBNYXRoCgphc20gZnVuIG1pbih4OiBJbnQsIHk6IEludCk6IEludCB7IE1JTiB9Cgphc20gZnVuIG1heCh4OiBJbnQsIHk6IEludCk6IEludCB7IE1B' +
- 'WCB9Cgphc20gZnVuIGFicyh4OiBJbnQpOiBJbnQgeyBBQlMgfQoKYXNtIGZ1biBub3coKTogSW50IHsgTk9XIH0KCmFzbSBmdW4gbG9nMihudW06IEludCk6IEludCB7' +
- 'CiAgICBEVVAgNSBUSFJPV0lGTk9UIFVCSVRTSVpFIERFQwp9CgpAbmFtZShfX3RhY3RfbG9nKQpuYXRpdmUgbG9nKG51bTogSW50LCBiYXNlOiBJbnQpOiBJbnQ7CgpA' +
- 'bmFtZShfX3RhY3RfcG93KQpuYXRpdmUgcG93KGJhc2U6IEludCwgZXhwOiBJbnQpOiBJbnQ7Cgphc20gZnVuIHBvdzIoZXhwOiBJbnQpOiBJbnQgeyBQT1cyIH0=';
+ 'WCB9Cgphc20gZnVuIGFicyh4OiBJbnQpOiBJbnQgeyBBQlMgfQoKYXNtIGZ1biBub3coKTogSW50IHsgTk9XIH0KCi8vIGZsb29yKGxvZzIobnVtKSkKYXNtIGZ1biBs' +
+ 'b2cyKG51bTogSW50KTogSW50IHsKICAgIERVUCA1IFRIUk9XSUZOT1QgVUJJVFNJWkUgREVDCn0KCi8vIGZsb29yKGxvZyhudW0sIGJhc2UpKQpAbmFtZShfX3RhY3Rf' +
+ 'bG9nKQpuYXRpdmUgbG9nKG51bTogSW50LCBiYXNlOiBJbnQpOiBJbnQ7CgpAbmFtZShfX3RhY3RfcG93KQpuYXRpdmUgcG93KGJhc2U6IEludCwgZXhwOiBJbnQpOiBJ' +
+ 'bnQ7Cgphc20gZnVuIHBvdzIoZXhwOiBJbnQpOiBJbnQgeyBQT1cyIH0KCmFzbSBmdW4gc2lnbih4OiBJbnQpOiBJbnQgeyBTR04gfQoKLy8gY2VpbCh4L3kpCmFzbSBm' +
+ 'dW4gZGl2Yyh4OiBJbnQsIHk6IEludCk6IEludCB7IERJVkMgfQoKLy8gY2VpbCh4KnkveikKYXNtIGZ1biBtdWxkaXZjKHg6IEludCwgeTogSW50LCB6OiBJbnQpOiBJ' +
+ 'bnQgeyBNVUxESVZDIH0KCi8vIGZsb29yKHgqeS8yXnopCmFzbSBmdW4gbXVsU2hpZnRSaWdodCh4OiBJbnQsIHk6IEludCwgejogSW50KTogSW50IHsgTVVMUlNISUZU' +
+ 'IH0KCi8vIHJvdW5kKHgqeS8yXnopCmFzbSBmdW4gbXVsU2hpZnRSaWdodFJvdW5kKHg6IEludCwgeTogSW50LCB6OiBJbnQpOiBJbnQgeyBNVUxSU0hJRlRSIH0KCi8v' +
+ 'IGNlaWwoeCp5LzJeeikKYXNtIGZ1biBtdWxTaGlmdFJpZ2h0Q2VpbCh4OiBJbnQsIHk6IEludCwgejogSW50KTogSW50IHsgTVVMUlNISUZUQyB9CgovLyByb3VuZChz' +
+ 'cXJ0KG51bSkpCmZ1biBzcXJ0KG51bTogSW50KTogSW50IHsKICAgIGlmIChudW0gPT0gMCkgewogICAgICAgIHJldHVybiAwOwogICAgfQoKICAgIGxldCBzOiBJbnQg' +
+ 'PSBsb2cyKG51bSk7CiAgICBsZXQgeDogSW50ID0gKHMgPT0gMSA/IChudW0gLSAxKSAvIDIgKyAxIDogMSA8PCAoKHMgKyAxKSAvIDIpKTsKCiAgICBsZXQgcTogSW50' +
+ 'ID0gMDsKCiAgICBkbyB7CiAgICAgICAgcSA9IChkaXZjKG51bSwgeCkgLSB4KSAvIDI7CiAgICAgICAgeCArPSBxOwogICAgfSB1bnRpbCAocSA9PSAwKTsKCiAgICBy' +
+ 'ZXR1cm4geDsKfQo=';
files['std/primitives.tact'] =
'cHJpbWl0aXZlIEludDsKcHJpbWl0aXZlIEJvb2w7CnByaW1pdGl2ZSBCdWlsZGVyOwpwcmltaXRpdmUgU2xpY2U7CnByaW1pdGl2ZSBDZWxsOwpwcmltaXRpdmUgQWRk' +
'cmVzczsKcHJpbWl0aXZlIFN0cmluZzsKcHJpbWl0aXZlIFN0cmluZ0J1aWxkZXI7';
@@ -837,7 +854,19 @@ files['stdlib.fc'] =
'ZXJfbnVsbD8oYnVpbGRlciBiKSBhc20gIklTTlVMTCI7Cjs7OyBDb25jYXRlbmF0ZXMgdHdvIGJ1aWxkZXJzCmJ1aWxkZXIgc3RvcmVfYnVpbGRlcihidWlsZGVyIHRv' +
'LCBidWlsZGVyIGZyb20pIGFzbSAiU1RCUiI7Cgo7OyBDVVNUT006Cgo7OyBUVk0gVVBHUkFERSAyMDIzLTA3IGh0dHBzOi8vZG9jcy50b24ub3JnL2xlYXJuL3R2bS1p' +
'bnN0cnVjdGlvbnMvdHZtLXVwZ3JhZGUtMjAyMy0wNwo7OyBJbiBtYWlubmV0IHNpbmNlIDIwIERlYyAyMDIzIGh0dHBzOi8vdC5tZS90b25ibG9ja2NoYWluLzIyNgoK' +
- 'Ozs7IFJldHJpZXZlcyBjb2RlIG9mIHNtYXJ0LWNvbnRyYWN0IGZyb20gYzcKY2VsbCBteV9jb2RlKCkgYXNtICJNWUNPREUiOwo=';
+ 'Ozs7IFJldHJpZXZlcyBjb2RlIG9mIHNtYXJ0LWNvbnRyYWN0IGZyb20gYzcKY2VsbCBteV9jb2RlKCkgYXNtICJNWUNPREUiOwoKOzs7IENyZWF0ZXMgYW4gb3V0cHV0' +
+ 'IGFjdGlvbiBhbmQgcmV0dXJucyBhIGZlZSBmb3IgY3JlYXRpbmcgYSBtZXNzYWdlLiBNb2RlIGhhcyB0aGUgc2FtZSBlZmZlY3QgYXMgaW4gdGhlIGNhc2Ugb2YgU0VO' +
+ 'RFJBV01TRwppbnQgc2VuZF9tZXNzYWdlKGNlbGwgbXNnLCBpbnQgbW9kZSkgaW1wdXJlIGFzbSAiU0VORE1TRyI7CgppbnQgZ2FzX2NvbnN1bWVkKCkgYXNtICJHQVND' +
+ 'T05TVU1FRCI7Cgo7OyBUVk0gVjYgaHR0cHM6Ly9naXRodWIuY29tL3Rvbi1ibG9ja2NoYWluL3Rvbi9ibG9iL3Rlc3RuZXQvZG9jL0dsb2JhbFZlcnNpb25zLm1kI3Zl' +
+ 'cnNpb24tNgoKaW50IGdldF9jb21wdXRlX2ZlZShpbnQgd29ya2NoYWluLCBpbnQgZ2FzX3VzZWQpIGFzbShnYXNfdXNlZCB3b3JrY2hhaW4pICJHRVRHQVNGRUUiOwpp' +
+ 'bnQgZ2V0X3N0b3JhZ2VfZmVlKGludCB3b3JrY2hhaW4sIGludCBzZWNvbmRzLCBpbnQgYml0cywgaW50IGNlbGxzKSBhc20oY2VsbHMgYml0cyBzZWNvbmRzIHdvcmtj' +
+ 'aGFpbikgIkdFVFNUT1JBR0VGRUUiOwppbnQgZ2V0X2ZvcndhcmRfZmVlKGludCB3b3JrY2hhaW4sIGludCBiaXRzLCBpbnQgY2VsbHMpIGFzbShjZWxscyBiaXRzIHdv' +
+ 'cmtjaGFpbikgIkdFVEZPUldBUkRGRUUiOwppbnQgZ2V0X3ByZWNvbXBpbGVkX2dhc19jb25zdW1wdGlvbigpIGFzbSAiR0VUUFJFQ09NUElMRURHQVMiOwoKaW50IGdl' +
+ 'dF9zaW1wbGVfY29tcHV0ZV9mZWUoaW50IHdvcmtjaGFpbiwgaW50IGdhc191c2VkKSBhc20oZ2FzX3VzZWQgd29ya2NoYWluKSAiR0VUR0FTRkVFU0lNUExFIjsKaW50' +
+ 'IGdldF9zaW1wbGVfZm9yd2FyZF9mZWUoaW50IHdvcmtjaGFpbiwgaW50IGJpdHMsIGludCBjZWxscykgYXNtKGNlbGxzIGJpdHMgd29ya2NoYWluKSAiR0VURk9SV0FS' +
+ 'REZFRVNJTVBMRSI7CmludCBnZXRfb3JpZ2luYWxfZndkX2ZlZShpbnQgd29ya2NoYWluLCBpbnQgZndkX2ZlZSkgYXNtKGZ3ZF9mZWUgd29ya2NoYWluKSAiR0VUT1JJ' +
+ 'R0lOQUxGV0RGRUUiOwppbnQgbXlfc3RvcmFnZV9kdWUoKSBhc20gIkRVRVBBWU1FTlQiOwoKdHVwbGUgZ2V0X2ZlZV9jb25maWdzKCkgYXNtICJVTlBBQ0tFRENPTkZJ' +
+ 'R1RVUExFIjsK';
files['stdlib.tact'] =
'aW1wb3J0ICIuL3N0ZC9wcmltaXRpdmVzIjsKaW1wb3J0ICIuL3N0ZC9jZWxscyI7CmltcG9ydCAiLi9zdGQvY3J5cHRvIjsKaW1wb3J0ICIuL3N0ZC90ZXh0IjsKaW1w' +
'b3J0ICIuL3N0ZC9tYXRoIjsKaW1wb3J0ICIuL3N0ZC9jb250cmFjdCI7CmltcG9ydCAiLi9zdGQvZGVidWciOwppbXBvcnQgIi4vc3RkL2NvbnRleHQiOwppbXBvcnQg' +
diff --git a/src/test/e2e-emulated/__snapshots__/local-type-inference.spec.ts.snap b/src/test/e2e-emulated/__snapshots__/local-type-inference.spec.ts.snap
index 5573c4ad8..c03922a12 100644
--- a/src/test/e2e-emulated/__snapshots__/local-type-inference.spec.ts.snap
+++ b/src/test/e2e-emulated/__snapshots__/local-type-inference.spec.ts.snap
@@ -321,6 +321,39 @@ exports[`local-type-inference should automatically set types for let statements
},
],
"types": [
+ {
+ "fields": [
+ {
+ "name": "cells",
+ "type": {
+ "format": 257,
+ "kind": "simple",
+ "optional": false,
+ "type": "int",
+ },
+ },
+ {
+ "name": "bits",
+ "type": {
+ "format": 257,
+ "kind": "simple",
+ "optional": false,
+ "type": "int",
+ },
+ },
+ {
+ "name": "refs",
+ "type": {
+ "format": 257,
+ "kind": "simple",
+ "optional": false,
+ "type": "int",
+ },
+ },
+ ],
+ "header": null,
+ "name": "DataSize",
+ },
{
"fields": [
{
diff --git a/src/test/e2e-emulated/contracts/math.tact b/src/test/e2e-emulated/contracts/math.tact
index 28215f20a..01d434afd 100644
--- a/src/test/e2e-emulated/contracts/math.tact
+++ b/src/test/e2e-emulated/contracts/math.tact
@@ -426,4 +426,32 @@ contract MathTester with Deployable {
a >>= b;
return a;
}
+
+ get fun sign(x: Int): Int {
+ return sign(x);
+ }
+
+ get fun divc(x: Int, y: Int): Int {
+ return divc(x, y);
+ }
+
+ get fun muldivc(x: Int, y: Int, z: Int): Int {
+ return muldivc(x, y, z);
+ }
+
+ get fun mulShiftRight(x: Int, y: Int, z: Int): Int {
+ return mulShiftRight(x, y, z);
+ }
+
+ get fun mulShiftRightRound(x: Int, y: Int, z: Int): Int {
+ return mulShiftRightRound(x, y, z);
+ }
+
+ get fun mulShiftRightCeil(x: Int, y: Int, z: Int): Int {
+ return mulShiftRightCeil(x, y, z);
+ }
+
+ get fun sqrt(x: Int): Int {
+ return sqrt(x);
+ }
}
diff --git a/src/test/e2e-emulated/contracts/stdlib.tact b/src/test/e2e-emulated/contracts/stdlib.tact
index c93ac431f..765f57f7f 100644
--- a/src/test/e2e-emulated/contracts/stdlib.tact
+++ b/src/test/e2e-emulated/contracts/stdlib.tact
@@ -58,4 +58,70 @@ contract StdlibTest {
get fun parseVarAddress(slice: Slice): VarAddress {
return parseVarAddress(slice);
}
-}
\ No newline at end of file
+
+ get fun builderDepth(bl: Builder): Int {
+ return bl.depth();
+ }
+
+ get fun skipLastBits(sc: Slice, n: Int): Slice {
+ return sc.skipLastBits(n);
+ }
+
+ get fun firstBits(sc: Slice, n: Int): Slice {
+ return sc.firstBits(n);
+ }
+
+ get fun lastBits(sc: Slice, n: Int): Slice {
+ return sc.lastBits(n);
+ }
+
+ get fun sliceDepth(sc: Slice): Int {
+ return sc.depth();
+ }
+
+ get fun addressNone(): Address? {
+ return addressNone();
+ }
+
+ get fun computeDataSizeCell(c: Cell, maxCells: Int): DataSize {
+ return c.computeDataSize(maxCells);
+ }
+
+ get fun computeDataSizeSlice(sc: Slice, maxCells: Int): DataSize {
+ return sc.computeDataSize(maxCells);
+ }
+
+ get fun cellDepth(c: Cell): Int {
+ return c.depth();
+ }
+
+ get fun curLt(): Int {
+ return curLt();
+ }
+
+ get fun blockLt(): Int {
+ return blockLt();
+ }
+
+ get fun setGasLimit(gl: Int): Int {
+ setGasLimit(gl);
+ let x = 0;
+ repeat (100) {
+ x += 1;
+ }
+ return gasConsumed();
+ }
+
+ get fun getSeed(): Int {
+ return getSeed();
+ }
+
+ get fun setSeed(seed: Int): Int {
+ setSeed(seed);
+ return getSeed();
+ }
+
+ get fun myCode(): Cell {
+ return myCode();
+ }
+}
diff --git a/src/test/e2e-emulated/math.spec.ts b/src/test/e2e-emulated/math.spec.ts
index 397cf7d2b..c6c5a19cd 100644
--- a/src/test/e2e-emulated/math.spec.ts
+++ b/src/test/e2e-emulated/math.spec.ts
@@ -507,5 +507,63 @@ describe("math", () => {
expect(await contract.getAugmentedShiftRight(2n, 1n)).toBe(1n);
expect(await contract.getAugmentedShiftRight(4n, 2n)).toBe(1n);
expect(await contract.getAugmentedShiftRight(16n, 3n)).toBe(2n);
+
+ // sign
+ expect(await contract.getSign(123n)).toBe(1n);
+ expect(await contract.getSign(-123n)).toBe(-1n);
+ expect(await contract.getSign(0n)).toBe(0n);
+
+ // divc: ceil(x/y)
+ expect(await contract.getDivc(123n, 123n)).toBe(1n);
+ expect(await contract.getDivc(123n, 124n)).toBe(1n);
+ expect(await contract.getDivc(0n, 123n)).toBe(0n);
+ expect(await contract.getDivc(123n, 122n)).toBe(2n);
+
+ // muldivc: ceil(x*y/z)
+ expect(await contract.getMuldivc(123n, 123n, 123n)).toBe(123n);
+ expect(await contract.getMuldivc(100n, 100n, 10001n)).toBe(1n);
+ expect(await contract.getMuldivc(100n, 100n, 10000n)).toBe(1n);
+ expect(await contract.getMuldivc(100n, 100n, 9999n)).toBe(2n);
+ expect(await contract.getMuldivc(100n, 0n, 1n)).toBe(0n);
+
+ // mulShiftRight: floor(x*y/2^z)
+ expect(await contract.getMulShiftRight(2n, 4n, 3n)).toBe(1n);
+ expect(await contract.getMulShiftRight(2n, 4n, 2n)).toBe(2n);
+ expect(await contract.getMulShiftRight(2n, 4n, 1n)).toBe(4n);
+ expect(await contract.getMulShiftRight(2n, 4n, 0n)).toBe(8n);
+ expect(await contract.getMulShiftRight(1n, 6n, 0n)).toBe(6n);
+ expect(await contract.getMulShiftRight(1n, 6n, 3n)).toBe(0n);
+
+ // mulShiftRightRound: round(x*y/2^z)
+ expect(await contract.getMulShiftRightRound(2n, 4n, 3n)).toBe(1n);
+ expect(await contract.getMulShiftRightRound(2n, 4n, 2n)).toBe(2n);
+ expect(await contract.getMulShiftRightRound(2n, 4n, 1n)).toBe(4n);
+ expect(await contract.getMulShiftRightRound(2n, 4n, 0n)).toBe(8n);
+ expect(await contract.getMulShiftRightRound(1n, 6n, 0n)).toBe(6n);
+ expect(await contract.getMulShiftRightRound(1n, 4n, 3n)).toBe(1n);
+ expect(await contract.getMulShiftRightRound(1n, 3n, 3n)).toBe(0n);
+
+ // mulShiftRightCeil: ceil(x*y/2^z)
+ expect(await contract.getMulShiftRightCeil(2n, 4n, 3n)).toBe(1n);
+ expect(await contract.getMulShiftRightCeil(2n, 4n, 2n)).toBe(2n);
+ expect(await contract.getMulShiftRightCeil(2n, 4n, 1n)).toBe(4n);
+ expect(await contract.getMulShiftRightCeil(2n, 4n, 0n)).toBe(8n);
+ expect(await contract.getMulShiftRightCeil(1n, 6n, 0n)).toBe(6n);
+ expect(await contract.getMulShiftRightCeil(1n, 7n, 3n)).toBe(1n);
+ expect(await contract.getMulShiftRightCeil(1n, 4n, 3n)).toBe(1n);
+ expect(await contract.getMulShiftRightCeil(1n, 3n, 3n)).toBe(1n);
+
+ // sqrt: round(sqrt(num))
+ for (let num = 0n; num <= 100n; num++) {
+ // console.log(`sqrt(${num}) = ${await contract.getSqrt(num)}`);
+ expect(await contract.getSqrt(num)).toBe(
+ BigInt(Math.round(Math.sqrt(Number(num)))),
+ );
+ }
+ for (let num = -3n; num < 0n; num++) {
+ await expect(contract.getSqrt(num)).rejects.toThrow(
+ "Unable to execute get method. Got exit_code: 5",
+ );
+ }
});
});
diff --git a/src/test/e2e-emulated/stdlib.spec.ts b/src/test/e2e-emulated/stdlib.spec.ts
index 440d82c13..679bea9a6 100644
--- a/src/test/e2e-emulated/stdlib.spec.ts
+++ b/src/test/e2e-emulated/stdlib.spec.ts
@@ -1,4 +1,4 @@
-import { Address, beginCell, toNano } from "@ton/core";
+import { Address, beginCell, Cell, toNano } from "@ton/core";
import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox";
import { StdlibTest } from "./contracts/output/stdlib_StdlibTest";
import "@ton/test-utils";
@@ -56,7 +56,7 @@ describe("stdlib", () => {
.toString(),
).toBe(beginCell().storeBit(true).endCell().toString());
- expect(await contract.getTvm_2023_07Upgrade()).toEqual(1355n);
+ expect(await contract.getTvm_2023_07Upgrade()).toEqual(1455n);
expect(await contract.getTvm_2024_04Upgrade()).toEqual(82009144n);
expect(
@@ -106,5 +106,63 @@ describe("stdlib", () => {
expect(addrVar.address.asCell()).toEqualCell(
beginCell().storeUint(345, 123).endCell(),
);
+
+ expect(await contract.getBuilderDepth(beginCell())).toBe(0n);
+ expect(
+ await contract.getBuilderDepth(beginCell().storeRef(Cell.EMPTY)),
+ ).toBe(1n);
+
+ expect(await contract.getSkipLastBits(slice, 1n)).toEqualSlice(
+ beginCell()
+ .storeBit(1)
+ .storeRef(beginCell().storeBit(1).endCell())
+ .endCell()
+ .asSlice(),
+ );
+
+ expect(await contract.getFirstBits(slice, 1n)).toEqualSlice(
+ beginCell().storeBit(1).endCell().asSlice(),
+ );
+
+ expect(await contract.getLastBits(slice, 1n)).toEqualSlice(
+ beginCell().storeBit(1).endCell().asSlice(),
+ );
+
+ expect(await contract.getSliceDepth(slice)).toBe(1n);
+
+ expect(await contract.getAddressNone()).toEqual(null);
+
+ expect(
+ await contract.getComputeDataSizeCell(slice.asCell(), 1000n),
+ ).toMatchObject({
+ $$type: "DataSize",
+ cells: 2n,
+ bits: 3n,
+ refs: 1n,
+ });
+
+ expect(
+ await contract.getComputeDataSizeSlice(slice, 1000n),
+ ).toMatchObject({
+ $$type: "DataSize",
+ cells: 1n, // -1 for slice
+ bits: 3n,
+ refs: 1n,
+ });
+
+ expect(await contract.getCellDepth(slice.asCell())).toBe(1n);
+
+ expect(await contract.getCurLt()).toBe(0n);
+
+ expect(await contract.getBlockLt()).toBe(0n);
+
+ expect(await contract.getSetGasLimit(5000n)).toBe(3997n); // 5000 just to make sure it's enough, 3997 is how much it actually costs
+ await expect(contract.getSetGasLimit(3996n)).rejects.toThrow("-14"); // 3996 gas is not enough for sure
+
+ expect(await contract.getGetSeed()).toBe(0n);
+
+ expect(await contract.getSetSeed(123n)).toBe(123n);
+
+ expect(await contract.getMyCode()).toEqualCell(contract.init!.code);
});
});
diff --git a/src/test/exit-codes/compute-phase-errors.spec.ts b/src/test/exit-codes/compute-phase-errors.spec.ts
index 15f0c0199..cfdca0644 100644
--- a/src/test/exit-codes/compute-phase-errors.spec.ts
+++ b/src/test/exit-codes/compute-phase-errors.spec.ts
@@ -59,7 +59,7 @@ describe("compute phase errors", () => {
await testComputePhaseExitCode(4, contract, treasure);
});
- // 5: Integer out of range
+ // 5: Integer out of expected range
it("should test exit code 5", async () => {
await testComputePhaseExitCode(5, contract, treasure);
});
diff --git a/stdlib/std/cells.tact b/stdlib/std/cells.tact
index 99c5b7443..5306f2d6e 100644
--- a/stdlib/std/cells.tact
+++ b/stdlib/std/cells.tact
@@ -82,6 +82,8 @@ asm extends fun refs(self: Builder): Int { BREFS }
asm extends fun bits(self: Builder): Int { BBITS }
+asm extends fun depth(self: Builder): Int { BDEPTH }
+
//
// Slice
//
@@ -167,6 +169,14 @@ asm extends mutates fun skipBits(self: Slice, l: Int) { SDSKIPFIRST }
asm extends fun endParse(self: Slice) { ENDS }
+asm extends fun skipLastBits(self: Slice, len: Int): Slice { SDSKIPLAST }
+
+asm extends fun firstBits(self: Slice, len: Int): Slice { SDCUTFIRST }
+
+asm extends fun lastBits(self: Slice, len: Int): Slice { SDCUTLAST }
+
+asm extends fun depth(self: Slice): Int { SDEPTH }
+
//
// Slice size
//
@@ -210,3 +220,18 @@ inline fun emptyCell(): Cell {
inline fun emptySlice(): Slice {
return emptyCell().asSlice();
}
+
+asm fun addressNone(): Address? { b{00} PUSHSLICE }
+
+struct DataSize {
+ cells: Int;
+ bits: Int;
+ refs: Int;
+}
+
+asm extends fun computeDataSize(self: Cell, maxCells: Int): DataSize { CDATASIZE }
+
+asm extends fun computeDataSize(self: Slice, maxCells: Int): DataSize { SDATASIZE }
+
+asm extends fun depth(self: Cell): Int { CDEPTH }
+
diff --git a/stdlib/std/contract.tact b/stdlib/std/contract.tact
index 1420e3be2..74fa06553 100644
--- a/stdlib/std/contract.tact
+++ b/stdlib/std/contract.tact
@@ -52,7 +52,7 @@ asm fun myStorageDue(): Int { DUEPAYMENT }
///
/// Calculates and returns the storage fee in nanoToncoins `Int` for storing a contract with a given number of `cells` and `bits` for a number of `seconds`. Uses the prices of the masterchain if `isMasterchain` is `true`, otherwise the prices of the basechain. The current prices are obtained from the config param 18 of TON Blockchain.
///
-/// Note, that the values of `cells` and `bits` are taken modulo their maximum values plus 1. That is, specifying values higher than those listed in account state limits (`max_acc_state_cells` and `max_acc_state_bits`) will have the same result as with specifying the exact limits. In addition, make sure you take into account the deduplication of cells with the same hash.
+/// Note, that specifying values of `cells` and `bits` higher than their maximum values listed in account state limits (`max_acc_state_cells` and `max_acc_state_bits`) will have the same result as with specifying the exact limits. In addition, make sure you take into account the deduplication of cells with the same hash.
///
/// Attempts to specify negative number of `cells`, `bits` or `seconds` throw an exception with exit code 5: `Integer out of expected range`.
///
@@ -112,7 +112,7 @@ asm fun getSimpleComputeFee(gasUsed: Int, isMasterchain: Bool): Int { GETGASFEES
///
/// If both the source and the destination addresses are in the basechain, then specify `isMasterchain` as `false`. Otherwise, specify `true`.
///
-/// Note, that the values of `cells` and `bits` are taken modulo their maximum values plus 1. That is, specifying values higher than those listed in account state limits (`max_msg_cells` and `max_msg_bits`) will have the same result as with specifying the exact limits.
+/// Note, that specifying values of `cells` and `bits` higher than their maximum values listed in account state limits (`max_msg_cells` and `max_msg_bits`) will have the same result as with specifying the exact limits.
///
/// However, regardless of the values of `cells` and `bits`, this function always adds the minimum price based on the value of `lump_price`. See the example for [`getSimpleForwardFee(){:tact}`](#getsimpleforwardfee) to derive it. In addition, make sure you take into account the deduplication of cells with the same hash, since for example the root cell and its data bits don't count towards the forward fee and are covered by the `lump_price`.
///
@@ -240,3 +240,15 @@ asm fun parseStdAddress(slice: Slice): StdAddress { REWRITESTDADDR }
/// See: https://docs.tact-lang.org/ref/core-advanced#parsevaraddress
///
asm fun parseVarAddress(slice: Slice): VarAddress { REWRITEVARADDR }
+
+asm fun curLt(): Int { LTIME }
+
+asm fun blockLt(): Int { BLOCKLT }
+
+asm fun setGasLimit(limit: Int) { SETGASLIMIT }
+
+asm fun getSeed(): Int { RANDSEED }
+
+asm fun setSeed(seed: Int) { SETRAND }
+
+asm fun myCode(): Cell { MYCODE }
diff --git a/stdlib/std/math.tact b/stdlib/std/math.tact
index 2186bd633..6b46f72c6 100644
--- a/stdlib/std/math.tact
+++ b/stdlib/std/math.tact
@@ -49,14 +49,52 @@ asm fun abs(x: Int): Int { ABS }
asm fun now(): Int { NOW }
+// floor(log2(num))
asm fun log2(num: Int): Int {
DUP 5 THROWIFNOT UBITSIZE DEC
}
+// floor(log(num, base))
@name(__tact_log)
native log(num: Int, base: Int): Int;
@name(__tact_pow)
native pow(base: Int, exp: Int): Int;
-asm fun pow2(exp: Int): Int { POW2 }
\ No newline at end of file
+asm fun pow2(exp: Int): Int { POW2 }
+
+asm fun sign(x: Int): Int { SGN }
+
+// ceil(x/y)
+asm fun divc(x: Int, y: Int): Int { DIVC }
+
+// ceil(x*y/z)
+asm fun muldivc(x: Int, y: Int, z: Int): Int { MULDIVC }
+
+// floor(x*y/2^z)
+asm fun mulShiftRight(x: Int, y: Int, z: Int): Int { MULRSHIFT }
+
+// round(x*y/2^z)
+asm fun mulShiftRightRound(x: Int, y: Int, z: Int): Int { MULRSHIFTR }
+
+// ceil(x*y/2^z)
+asm fun mulShiftRightCeil(x: Int, y: Int, z: Int): Int { MULRSHIFTC }
+
+// round(sqrt(num))
+fun sqrt(num: Int): Int {
+ if (num == 0) {
+ return 0;
+ }
+
+ let s: Int = log2(num);
+ let x: Int = (s == 1 ? (num - 1) / 2 + 1 : 1 << ((s + 1) / 2));
+
+ let q: Int = 0;
+
+ do {
+ q = (divc(num, x) - x) / 2;
+ x += q;
+ } until (q == 0);
+
+ return x;
+}
diff --git a/stdlib/stdlib.fc b/stdlib/stdlib.fc
index 91d461649..7761b68f6 100644
--- a/stdlib/stdlib.fc
+++ b/stdlib/stdlib.fc
@@ -668,3 +668,22 @@ builder store_builder(builder to, builder from) asm "STBR";
;;; Retrieves code of smart-contract from c7
cell my_code() asm "MYCODE";
+
+;;; Creates an output action and returns a fee for creating a message. Mode has the same effect as in the case of SENDRAWMSG
+int send_message(cell msg, int mode) impure asm "SENDMSG";
+
+int gas_consumed() asm "GASCONSUMED";
+
+;; TVM V6 https://github.com/ton-blockchain/ton/blob/testnet/doc/GlobalVersions.md#version-6
+
+int get_compute_fee(int workchain, int gas_used) asm(gas_used workchain) "GETGASFEE";
+int get_storage_fee(int workchain, int seconds, int bits, int cells) asm(cells bits seconds workchain) "GETSTORAGEFEE";
+int get_forward_fee(int workchain, int bits, int cells) asm(cells bits workchain) "GETFORWARDFEE";
+int get_precompiled_gas_consumption() asm "GETPRECOMPILEDGAS";
+
+int get_simple_compute_fee(int workchain, int gas_used) asm(gas_used workchain) "GETGASFEESIMPLE";
+int get_simple_forward_fee(int workchain, int bits, int cells) asm(cells bits workchain) "GETFORWARDFEESIMPLE";
+int get_original_fwd_fee(int workchain, int fwd_fee) asm(fwd_fee workchain) "GETORIGINALFWDFEE";
+int my_storage_due() asm "DUEPAYMENT";
+
+tuple get_fee_configs() asm "UNPACKEDCONFIGTUPLE";