Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new functions in stdlib from stdlib.fc and math.fc #986

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
19a5f30
feat: add missing functions from `stdlib.fc`
Gusarich Oct 25, 2024
a198af0
feat: add `sgn` math function
Gusarich Oct 25, 2024
165a125
chore: update changelog
Gusarich Oct 25, 2024
7941532
feat: apply suggestions from code review
Gusarich Nov 17, 2024
00790e4
chore: fix varuint comment in stdlib
Gusarich Nov 17, 2024
293c7cc
feat: remove `stringHash` due to existence of `.hash` method
Gusarich Nov 17, 2024
fba75c7
feat: update `stdlib.ts`
Gusarich Nov 17, 2024
f384afc
feat: add `MULRSHIFT` functions
Gusarich Nov 17, 2024
0e3d6b4
feat: update `stdlib.ts`
Gusarich Nov 17, 2024
1db9371
feat: add `sqrt` function
Gusarich Nov 18, 2024
a403986
feat: `sliceLast` -> `lastBits`, and make `computeDataSize` an extend…
Gusarich Nov 18, 2024
364dbf8
chore: add all function names to changelog
Gusarich Nov 18, 2024
30038ca
feat: `addressNone`
Gusarich Nov 18, 2024
58c33b5
feat: rename mulrshift functions
Gusarich Nov 21, 2024
cbd36dc
feat: rewrite sqrt on tact
Gusarich Nov 21, 2024
2aca980
chore: update serialization snapshots
Gusarich Nov 21, 2024
3dcaf2a
chore: update cspell ignorelist
Gusarich Nov 21, 2024
83d69e7
chore: update CHANGELOG.md
Gusarich Nov 22, 2024
e801103
fix: `addressNone` and `computeDataSize` types
Gusarich Nov 28, 2024
b0ec774
chore: add comments with specs for new math functions
Gusarich Nov 28, 2024
4d05722
feat: cover new functions with tests
Gusarich Nov 28, 2024
734f3a0
feat: update stdlib.ts
Gusarich Nov 29, 2024
a2da1a2
chore: typos and extra linkage
novusnota Dec 4, 2024
2b72e66
feat(docs): all math functions and all new non-cell related functions…
novusnota Dec 4, 2024
8453507
feat(docs): new cell-related functions plus minor corrections here an…
novusnota Dec 5, 2024
aa58a35
chore: typo
novusnota Dec 5, 2024
4e73eb4
chore: typo
novusnota Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"minmax",
"mintable",
"mktemp",
"muldivc",
"multiformats",
"nanotons",
"Neovim",
Expand Down
1 change: 1 addition & 0 deletions docs/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
"minmax",
"mintable",
"mktemp",
"muldivc",
"multiformats",
"nanotons",
"nanotons",
Expand Down
8 changes: 4 additions & 4 deletions docs/src/content/docs/book/exit-codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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:

Expand Down Expand Up @@ -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.
Expand Down
205 changes: 182 additions & 23 deletions docs/src/content/docs/ref/core-advanced.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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]

:::

Expand Down Expand Up @@ -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`.

Expand Down Expand Up @@ -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].

Expand Down Expand Up @@ -276,31 +276,27 @@ let origFee: Int = getOriginalFwdFee(fee, false);

:::

## getConfigParam
## setGasLimit

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

```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).

:::

Expand All @@ -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:

Expand Down Expand Up @@ -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:

Expand All @@ -351,6 +347,146 @@ commit(); // now, transaction is considered "successful"
throw(42); // and this won't fail it
```

## myCode

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

```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

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

```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

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

```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

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

```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

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

```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
Expand All @@ -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:

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Loading
Loading