Skip to content

Commit 84f0f0f

Browse files
Update functions.md
1 parent eceaef8 commit 84f0f0f

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

docs/v3/documentation/smart-contracts/func/docs/functions.md

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -307,38 +307,46 @@ The `method_id(<some_number>)` specifier allows you to set a function's ID to a
307307
If no ID is specified, the default is calculated as `(crc16(<function_name>) & 0xffff) | 0x10000`.
308308
If a function has the `method_id` specifier, it can be invoked by its name as a get-method in lite client or TON explorer.
309309

310-
:::info
311-
There is a catch if you try to define specific ID manually:
312-
- It should not exceed `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`
313-
- Due to a lazy check in types it can accept up to `0x6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff` and succesfully compile
314-
- In TVM it is still a 257-bit unsigned variable, so it should be defined in range
310+
:::warning Important limitations and recommendations
311+
**19-bit limitation**: Method IDs are limited to 19 bits by the TVM assembler, meaning the valid range is **0 to 524,287** (2^19 - 1).
312+
313+
**Reserved ranges**:
314+
- **0-999**: Reserved for system functions (approximate range)
315+
- **Special functions**: `main`/`recv_internal` (id=0), `recv_external` (id=-1), `run_ticktock` (id=-2)
316+
- **65536+**: Default range for user functions when using automatic generation `(crc16() & 0xffff) | 0x10000`
317+
318+
**Best practice**: It's recommended to **avoid setting method IDs manually** and rely on automatic generation instead. Manual assignment can lead to conflicts and unexpected behavior.
315319
:::
316320

317321
<details>
318-
<summary><b>AnyIntView&lt;Tr&gt;::parse_hex_any</b></summary>
322+
<summary><b>Technical details about method_id parsing</b></summary>
319323

320-
This function (`crypto/common/bigint.hpp`) is responsible for parsing the hexadecimal string.
324+
While the FunC compiler can initially accept larger hex values during parsing, the actual limitation comes from the TVM assembler which restricts method IDs to 19 bits (`@procdictkeylen = 19` in Asm.fif).
321325

322-
It first performs a basic check on the length of the hex string:
326+
The parsing of the hexadecimal string for `method_id` is handled by functions in `crypto/common/bigint.hpp` (specifically `AnyIntView::parse_hex_any` called via `td::string_to_int256` and `BigInt<257>::parse_hex`).
327+
328+
`AnyIntView::parse_hex_any` first performs a basic check on the length of the hex string:
323329
```cpp
324330
if ((j - i - (p > 0)) * 4 > (max_size() - 1) * word_shift + word_bits - 2) {
325331
return 0; // Invalid if too long
326332
}
327333
```
328334

329-
For `BigInt<257>`, `Tr` is `BigIntInfo`, `word_bits` is 64, `word_shift` is 62.
330-
331-
The `max_size()` for `BigInt<257>` is `257 / 62 + 1 = 4 + 1 = 5` "words".
335+
For `BigInt<257>` (which is `td::BigIntG<257, td::BigIntInfo>`):
336+
- `Tr` is `BigIntInfo`.
337+
- `word_bits` (bits in a word) is 64.
338+
- `word_shift` (effective bits used per word in normalization) is 52. (Source: `crypto/common/bigint.hpp`)
339+
- `max_size()` (maximum words for `BigInt<257>`) is `(257 + 52 - 1) / 52 + 1 = 6` words.
332340

333-
Let's plug in the values:
334-
`(5 - 1) * 62 + 64 - 2 = 4 * 62 + 62 = 248 + 62 = 310` bits.
341+
Let's plug these values into the length check formula:
342+
`(max_size() - 1) * word_shift + word_bits - 2`
343+
`(6 - 1) * 52 + 64 - 2 = 5 * 52 + 62 = 260 + 62 = 322` bits.
335344

336345
A 65-character hex string represents \( 65 times 4 = 260 \) bits.
337-
So, `260 < 310 - 2`. Such a number (65 hex digits) can *pass* this initial length check. This check is designed to quickly reject inputs that are grossly too large. The `-2` is a slight margin.
338-
339-
After basic parsing into internal `digits_`, it calls `normalize_bool_any()`.
346+
The calculated bit limit for the quick check is 322 bits. Since `260` is not greater than `322`, such a number (65 hex digits) can *pass* this initial length check. This check is designed to quickly reject inputs that are grossly too large. The `-2` offers a slight margin.
340347

341-
If `normalize_bool_any()` returns `false`, `parse_hex_any` will invalidate the `BigInt` and return `0`, indicating a parsing failure. This leads to `td::string_to_int256` returning a `null` `RefInt256`.
348+
After this initial parsing into internal `digits_`, `parse_hex_any` calls `normalize_bool_any()`. This function converts the internal representation into a canonical signed form.
349+
If `normalize_bool_any()` returns `false`, it indicates an overflow during this canonicalization. This can happen even if the number passed the initial length check, for example, if a carry propagates such that it requires more than `max_size()` words to represent in the specific signed format, or if the most significant word itself overflows. In such a case, `parse_hex_any` invalidates the `BigInt` and returns `0`, leading to `td::string_to_int256` returning a `null RefInt256` and FunC reporting an "invalid integer constant".
342350
</details>
343351

344352
**Example**

0 commit comments

Comments
 (0)