Skip to content

Debug

List of functions commonly used for debugging smart contracts in Tact.

Read more about debugging on the dedicated page: Debugging.

require

fun require(condition: Bool, error: String);

Checks the condition and throws an error with an exit code generated from the error message if the condition is false. Otherwise, does nothing.

This function is similar to throwUnless(), but instead of using the error code directly, it generates it based on the given error message String.

The algorithm for generating the exit code works as follows:

  • First, the SHA-256 hash of the error message String is obtained.
  • Then, its value is read as a 32-bit big-endian number modulo 63000 plus 1000, in that order.
  • Finally, it’s put into the .md compilation report file, which resides with the other compilation artifacts in your project’s outputs/ or build/ directories.

The generated exit code is guaranteed to be outside the common 0–255 range reserved for TVM and Tact contract errors, which makes it possible to distinguish exit codes from require() and any other standard exit codes.

Usage examples:

// now() has to return a value greater than 1000, otherwise an error message will be thrown
require(now() > 1000, "We're in the first 1000 seconds of 1 January 1970!");
try {
// The following will never be true, so this require would always throw
require(now() < -1, "Time is an illusion. Lunchtime doubly so.");
} catch (e) {
// e will be outside of range 0-255
dump(e);
}

dump

Gas-expensive

fun dump(arg);

Prints the argument arg to the contract’s debug console. Evaluated only if the debug option in the configuration file is set to true. Otherwise does nothing.

This function is computationally expensive and consumes a lot of gas because it prints the location from which it was called—i.e., the filename, line, and column numbers—and the original expression that was the arg argument.

Can be applied to the following list of types and values:

Usage examples:

// Int
dump(42); // prints:
// File filename.tact:2:1
// dump(42)
// 42
// Bool
dump(true);
dump(false);
// Address
dump(myAddress());
// Cell, Builder, or Slice
dump(emptyCell()); // Cell
dump(beginCell()); // Builder
dump(emptySlice()); // Slice
// String
dump("Hello, my name is...");
// Maps
let m: map<Int, Int> = emptyMap();
m.set(2 + 2, 4);
dump(m);
// Special values
dump(null);
dump(emit("msg".asComment())); // As emit() function doesn't return a value, dump() would print #DEBUG#: void.

dumpStack

Gas-expensive

fun dumpStack();

Prints the total stack depth and up to 255 of its values from the top to the contract’s debug console. The values are positioned bottom-up—from the deepest value on the left to the topmost value on the right. Evaluated only if the debug option in the configuration file is set to true. Otherwise does nothing.

Usage example:

dumpStack(); // prints:
// File filename.tact:1:1
// dumpStack()
// stack(3 values) : 100000000 C{96...C7} 0

throw

fun throw(code: Int);

Unconditionally throws an exception with an error code.

Execution of the current context stops, statements after throw are not executed, and control is passed to the first try...catch block on the call stack. If there is no try or try...catch block among calling functions, TVM terminates the transaction.

Attempts to specify a code outside the range 0655350-65535 cause an exception with exit code 5: Integer out of expected range.

Usage examples:

fun thisWillTerminateAbruptly() {
throw(1042); // throwing with exit code 1042
}
fun butThisWont() {
try {
throw(1042); // throwing with exit code 1042
}
// ... follow-up logic ...
}

throwIf

Available since Tact 1.6

fun throwIf(code: Int, condition: Bool);

Similar to throw(), but throws an error code only if condition holds, i.e. is equal to true. Doesn’t throw otherwise.

Attempts to specify a code outside the range 0655350-65535 cause an exception with exit code 5: Integer out of expected range.

Usage example:

contract Ownership {
owner: Address;
init() {
self.owner = myAddress();
}
receive() {
// Check whether the sender is the owner of the contract,
// and throw exit code 1024 if not
throwIf(1024, sender() != self.owner);
}
}

throwUnless

Available since Tact 1.6

fun throwUnless(code: Int, condition: Bool);

Similar to throw(), but throws an error code only if condition does not hold, i.e. if condition is not equal to true. Doesn’t throw otherwise.

This function is also similar to require(), but uses the specified code directly instead of generating one based on a given error message String.

Attempts to specify a code outside the range 0655350-65535 cause an exception with exit code 5: Integer out of expected range.

Usage example:

contract Ownership {
owner: Address;
init() {
self.owner = myAddress();
}
receive() {
// Check whether the sender is the owner of the contract,
// and throw exit code 1024 if not
throwUnless(1024, sender() == self.owner);
}
}

nativeThrow

Deprecated since Tact 1.6

Use throw() instead.

fun nativeThrow(code: Int);

An alias to throw().

nativeThrowIf

Deprecated since Tact 1.6

Use throwIf() instead.

fun nativeThrowIf(code: Int, condition: Bool);

An alias to throwIf().

nativeThrowUnless

Deprecated since Tact 1.6

Use throwUnless() instead.

fun nativeThrowUnless(code: Int, condition: Bool);

An alias to throwUnless().