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
messageString
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’soutputs/
orbuild/
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 thrownrequire(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-expensivefun 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:
Int
Bool
Address
Cell
,Builder
, orSlice
String
map<K, V>
- Optionals and
null
value void
, which is implicitly returned when a function doesn’t have a return value defined
Usage examples:
// Intdump(42); // prints: // File filename.tact:2:1 // dump(42) // 42
// Booldump(true);dump(false);
// Addressdump(myAddress());
// Cell, Builder, or Slicedump(emptyCell()); // Celldump(beginCell()); // Builderdump(emptySlice()); // Slice
// Stringdump("Hello, my name is...");
// Mapslet m: map<Int, Int> = emptyMap();m.set(2 + 2, 4);dump(m);
// Special valuesdump(null);dump(emit("msg".asComment())); // As emit() function doesn't return a value, dump() would print #DEBUG#: void.
dumpStack
Gas-expensivefun 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 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.6fun 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 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.6fun 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 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.6Use throw()
instead.
fun nativeThrow(code: Int);
An alias to throw()
.
nativeThrowIf
Deprecated since Tact 1.6Use throwIf()
instead.
fun nativeThrowIf(code: Int, condition: Bool);
An alias to throwIf()
.
nativeThrowUnless
Deprecated since Tact 1.6Use throwUnless()
instead.
fun nativeThrowUnless(code: Int, condition: Bool);
An alias to throwUnless()
.