Skip to content
Merged
Changes from all commits
Commits
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
34 changes: 15 additions & 19 deletions tvm/exit-codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ title: "Exit codes"

import { Aside } from '/snippets/aside.jsx';

<Aside>
This page currently gives code examples in [Tact language](/languages/tact). They will be rewritten in [Tolk](/languages/tolk) in the [near future](https://github.com/ton-org/docs/issues/727).
</Aside>

An exit code is a 32-bit signed integer that indicates whether the compute or action phase of the transaction was successful. If not, it holds the code of the exception that occurred.

Each transaction on TON Blockchain consists of multiple phases. An _exit code_ is a 32-bit signed integer that indicates whether the [compute](#compute) or [action](#action) phase of the transaction was successful, and if not, holds the code of the exception that occurred. Each exit code represents its own exception or the resulting state of the transaction.
Expand Down Expand Up @@ -126,7 +122,7 @@ This is an alternative exit code for the successful execution of the [compute ph
If an operation consumes more elements than exist on the stack, an error with exit code 2 is thrown: `Stack underflow`.

```tolk title="Tolk"
fun drop(): void asm "DROP"
fun drop(): void asm "DROP"

fun onInternalMessage() {
try {
Expand All @@ -153,7 +149,7 @@ If there are too many elements copied into a closure continuation, an error with

```tolk title="Tolk"
// Remember kids, don't try to overflow the stack at home!
fun stackOverflow(): void asm
fun stackOverflow(): void asm
"""
x{} SLICE // s
BLESS // c
Expand All @@ -164,7 +160,7 @@ fun stackOverflow(): void asm
"""

fun onInternalMessage() {
try {
try {
stackOverflow();
} catch(exitCode) {
// exitCode is 3
Expand All @@ -184,7 +180,7 @@ fun onInternalMessage() {
If the value in a calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, or there's an attempt to divide or perform modulo by zero, an error with exit code 4 is thrown: `Integer overflow`.

```tolk title="Tolk"
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun pow2(y: int): int asm "POW2"

fun onInternalMessage() {
Expand All @@ -197,7 +193,7 @@ fun onInternalMessage() {
} catch(exitCode) {
// exitCode is 4
assert (exitCode == 4) throw 1111;
}
}

try {
touch(x / zero); // division by zero!
Expand Down Expand Up @@ -227,7 +223,7 @@ A range check error occurs when some integer is out of its expected range. Any a
Examples of specifying an out-of-bounds value:

```tolk title="Tolk"
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun pow2(y: int): int asm "POW2"

fun onInternalMessage() {
Expand All @@ -240,7 +236,7 @@ fun onInternalMessage() {
} catch(exitCode) {
// exitCode is 5
assert (exitCode == 5) throw 1111;
}
}

try {
// Builder.storeUint() function can only use up to 256 bits, thus 512 is too much:
Expand All @@ -250,7 +246,7 @@ fun onInternalMessage() {
assert (exitCode == 5) throw 1111;
}

try {
try {
touch(beginCell().storeUint(100, 2).toCell()); // maximum value is 2^{2} - 1 = 3 < 100
}
catch(exitCode) {
Expand Down Expand Up @@ -291,7 +287,7 @@ If you specify an instruction that is not defined in the current [TVM][tvm] vers

```tolk title="Tolk"
// There's no such code page, and an attempt to set it fails
fun invalidOpcode(): void asm "42 SETCP"
fun invalidOpcode(): void asm "42 SETCP"

fun onInternalMessage() {
try {
Expand All @@ -308,13 +304,13 @@ fun onInternalMessage() {
If an argument to a primitive is of an incorrect value type or there is any other mismatch in types during the [compute phase](#compute), an error with exit code 7 is thrown: `Type check error`.

```tolk title="Tolk"
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
// The actual returned value type doesn't match the declared one
fun typeCheckError(): cell asm "42 PUSHINT";

fun onInternalMessage() {
try {
// it isn't cell
// it isn't cell
touch(typeCheckError().beginParse());
} catch (exitCode) {
// exitCode is 7
Expand All @@ -330,7 +326,7 @@ To construct a `cell`, a `builder` primitive is used. If you try to store more t
This error can be triggered by manual construction of the cells via relevant methods, such as `storeInt()`, or when using structs, their convenience methods.

```tolk title="Tolk"
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions

fun onInternalMessage() {
// Too many bits
Expand Down Expand Up @@ -372,7 +368,7 @@ To parse a `cell`, a `slice` primitive is used. If you try to load more data or
The most common cause of this error is a mismatch between the expected and actual memory layouts of the cells, so it's recommended to use Tolk structs for parsing the cells instead of manual parsing via relevant methods, such as `loadInt()`.

```tolk title="Tolk"
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions

fun onInternalMessage() {
// Too few bits
Expand Down Expand Up @@ -402,7 +398,7 @@ If there is incorrect manipulation of dictionaries, such as improper assumptions
```tolk title="Tolk"
import "@stdlib/tvm-dicts";

fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun touch<T>(y: T): void asm "NOP" // so that the compiler doesn't remove instructions
fun cast<T, U>(y: T): U asm "NOP"
fun cell?.addIntToIDict(mutate self, key: int, number: int): void {
return self.iDictSetBuilder(32, key, beginCell().storeInt(number, 32));
Expand All @@ -415,7 +411,7 @@ fun onInternalMessage() {

// The Int to Int dictionary is being misinterpreted as a map<int32, cell>
val m: map<int32, cell> = cast(dict);

try {
// And the error happens only when we touch it
touch(m.get(0).isFound);
Expand Down