From cab7de4960c1d2bc89ed528d13c7404027bbcf12 Mon Sep 17 00:00:00 2001 From: Novus Nota <68142933+novusnota@users.noreply.github.com> Date: Tue, 24 Dec 2024 01:44:20 +0100 Subject: [PATCH] feat(docs): mention the limit of max number of messages that can be sent during action phase --- CHANGELOG.md | 1 + docs/src/content/docs/book/exit-codes.mdx | 6 ++++ docs/src/content/docs/book/send.mdx | 34 +++++++++++++-------- docs/src/content/docs/ref/core-advanced.mdx | 4 +++ docs/src/content/docs/ref/core-common.mdx | 6 +++- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e7b920a2..384b03545 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a link to the article by CertiK to Security best practices page: PR [#1185](https://github.com/tact-lang/tact/pull/1185) - Added a note on `dump()` being computationally expensive: PR [#1189](https://github.com/tact-lang/tact/pull/1189) - Fixed links in Chinese translation: PR [#1206](https://github.com/tact-lang/tact/pull/1206) +- Added a note on 255 being the maximum number of messages that can be sent during action phase: PR [#1237](https://github.com/tact-lang/tact/pull/1237) ### Release contributors diff --git a/docs/src/content/docs/book/exit-codes.mdx b/docs/src/content/docs/book/exit-codes.mdx index 69d8e4fb9..527942735 100644 --- a/docs/src/content/docs/book/exit-codes.mdx +++ b/docs/src/content/docs/book/exit-codes.mdx @@ -502,6 +502,12 @@ When processing the message, TON Blockchain tries to pack it according to the [r If there would not be enough funds to process all the cells in a message, the message is too large or its Merkle depth is too big, an error with exit code $40$ is thrown: `Cannot process a message`. +:::note + + If the [optional flag +2](/book/message-mode#optional-flags) is set, this error won't be thrown and the given message won't be sent. + +::: + ### 41: Library reference is null {#41} If the library reference was required during library change action, but it was null, an error with exit code $41$ is thrown: `Library reference is null`. diff --git a/docs/src/content/docs/book/send.mdx b/docs/src/content/docs/book/send.mdx index 9c2283da7..b6ba343e4 100644 --- a/docs/src/content/docs/book/send.mdx +++ b/docs/src/content/docs/book/send.mdx @@ -57,11 +57,16 @@ send(SendParameters{ }); ``` -The [optional flag](/book/message-mode#optional-flags) `SendIgnoreErrors{:tact}` means that even when an error occurs during message sending next messages would be sent anyway. **No error during the sending phase would revert a transaction.** +The [optional flag](/book/message-mode#optional-flags) `SendIgnoreErrors{:tact}` means that if an error occurs during [message send](#outbound-message-processing), it will be ignored and the given message will be skipped. Message-related [action phase][phases] [exit codes](/book/exit-codes) that might be thrown without the `SendIgnoreErrors{:tact}` set are: + +* $36$: [`Invalid destination address in outbound message`](/book/exit-codes#36) +* $37$: [`Not enough Toncoin`](/book/exit-codes#37) +* $39$: [`Outbound message doesn't fit into a cell`](/book/exit-codes#39) +* $40$: [`Cannot process a message`](/book/exit-codes#40) ## Send typed message -To send a binary typed message you can use the following code: +To send a typed message you can use the following code: ```tact let recipient: Address = address("..."); @@ -98,7 +103,7 @@ send(SendParameters{ Each transaction on TON Blockchain consists of [multiple phases][phases]. Outbound messages are evaluated in [compute phase][compute], but are **not** sent in that phase. Instead, they're queued in order of appearance for the [action phase][phases], where all actions listed in [compute phase][compute], like outbound messages or [reserve requests](/ref/core-advanced#nativereserve), are executed. -As all the values are computed in [compute phase][compute], all the fees computed by the end of it, and exceptions do not revert the transaction during [action phase][phases], outbound message sends can fail without bounce due to unsufficient [action fees](https://docs.ton.org/develop/howto/fees-low-level#action-fee) or [forward fees][fwdfee]. +As all the values are computed in [compute phase][compute], all the fees computed by the end of it, and exceptions do not revert the transaction during [action phase][phases], outbound message sends can fail without bounce due to insufficient [action fees](https://docs.ton.org/develop/howto/fees-low-level#action-fee) or [forward fees][fwdfee]. Consider the following example: @@ -132,17 +137,22 @@ There, the second message won't actually be sent: * When the second message is processed, contract tries to send $\mathrm{R}$ [nanoToncoins](/book/integers#nanotoncoin), but fails to do so because there is already a smaller amount left. -:::note +## Message sending limits + +In total, there could be no more than $255$ actions queued for execution, which means that the maximum allowed number of messages sent per transaction is $255$. + +Attempts to queue more throw an exception with an [exit code 33](/book/exit-codes#33) during [action phase][phases]: `Action list is too long`. + +## Message sending functions - Read more about all message sending functions in the Reference: - * [`send(){:tact}`](/ref/core-common#send) - * [`emit(){:tact}`](/ref/core-common#emit) - * [`self.notify(){:tact}`](/ref/core-base#self-notify) - * [`self.reply(){:tact}`](/ref/core-base#self-reply) - * [`self.forward(){:tact}`](/ref/core-base#self-forward) - * [`nativeSendMessage(){:tact}`](/ref/core-advanced#nativesendmessage) +Read more about all message sending functions in the Reference: -::: +* [`send(){:tact}`](/ref/core-common#send) +* [`emit(){:tact}`](/ref/core-common#emit) +* [`self.notify(){:tact}`](/ref/core-base#self-notify) +* [`self.reply(){:tact}`](/ref/core-base#self-reply) +* [`self.forward(){:tact}`](/ref/core-base#self-forward) +* [`nativeSendMessage(){:tact}`](/ref/core-advanced#nativesendmessage) [p]: /book/types#primitive-types [int]: /book/integers diff --git a/docs/src/content/docs/ref/core-advanced.mdx b/docs/src/content/docs/ref/core-advanced.mdx index 02531ef29..79fdc270c 100644 --- a/docs/src/content/docs/ref/core-advanced.mdx +++ b/docs/src/content/docs/ref/core-advanced.mdx @@ -434,6 +434,8 @@ fun nativeSendMessage(cell: Cell, mode: Int); [Queues the message](/book/send#outbound-message-processing) to be sent by specifying the complete `cell` and the [message `mode`](/book/message-mode). +Attempts to queue more than $255$ messages throw an exception with an [exit code 33](/book/exit-codes#33): `Action list is too long`. + :::note Prefer using a much more common and user-friendly [`send(){:tact}`](/ref/core-common#send) function unless you have a complex logic that can't be expressed otherwise. @@ -466,6 +468,8 @@ It's possible to use raw [`Int{:tact}`][int] values and manually provide them fo Currently, `amount` must be a non-negative integer, and `mode` must be in the range $0..31$, inclusive. + Additionally, attempts to queue more than $255$ reservations in one transaction throw an exception with an [exit code 33](/book/exit-codes#33): `Action list is too long`. + ::: ### Base modes {#nativereserve-base-modes} diff --git a/docs/src/content/docs/ref/core-common.mdx b/docs/src/content/docs/ref/core-common.mdx index 4afcbf27e..5444ece78 100644 --- a/docs/src/content/docs/ref/core-common.mdx +++ b/docs/src/content/docs/ref/core-common.mdx @@ -37,7 +37,7 @@ let iNeedADolla: Int = myBalance(); :::caution - Beware, that [all message sending functions](/book/send) of Tact can change the _actual_ contract's balance, but they _won't_ update the value returned by this function. + Beware, that [all message sending functions](/book/send#message-sending-functions) of Tact can change the _actual_ contract's balance, but they _won't_ update the value returned by this function. ::: @@ -202,6 +202,8 @@ fun send(params: SendParameters); [Queues the message](/book/send#outbound-message-processing) to be sent using a [`SendParameters{:tact}`](/book/send) [Struct](/book/structs-and-messages#structs). +Attempts to queue more than $255$ messages throw an exception with an [exit code 33](/book/exit-codes#33): `Action list is too long`. + Usage example: ```tact @@ -228,6 +230,8 @@ fun emit(body: Cell); [Queues the message](/book/send#outbound-message-processing) `body` to be sent to the outer world with the purpose of logging and analyzing it later off-chain. The message does not have a recipient and is gas-efficient compared to using any other message sending functions of Tact. +Attempts to queue more than $255$ messages throw an exception with an [exit code 33](/book/exit-codes#33): `Action list is too long`. + Usage example: ```tact