Skip to content

Bounced messages

When a contract sends a message with the flag bounce set to true, and if the message isn’t processed properly, it will bounce back to the sender. This is useful when you want to ensure that the message has been processed properly and, if not, revert the changes.

Caveats

Currently, bounced messages in TON can have at most 256 bits of payload and no references, but the amount of useful data bits when handling messages in bounced receivers is at most 224, since the first 32 bits are occupied by the message opcode. This means that you can’t recover much of the data from the bounced message, for instance you cannot fit an address into a bounced message, since regular internal addresses need 267 bits to be represented.

Tact helps you to check if your message fits the limit, and if it doesn’t, suggests using a special type constructor bounced<M> for the bounced message receiver, which constructs a partial representation of the message that fits within the required limits. Only the first message fields that fit into the 224 bits will be available to use in bounced message receivers. Sometimes you need to rearrange the order of the fields in your message so the relevant ones would fit into the limit.

Bounced message receiver

To receive a bounced message, define a bounced() receiver function in your contract or a trait:

contract MyContract {
bounced(msg: bounced<MyMessage>) {
// ...
}
}

To process bounced messages manually, you can use a fallback definition that handles a raw Slice directly. Note that such a receiver will get all the bounced messages produced by your contract:

contract MyContract {
bounced(rawMsg: Slice) {
// ...
}
}