Skip to main content
unknown represents any single-slot TVM value with contents unknown at compile-time.

Primary use

tuple is an alias for array<unknown>:
// declared in stdlib
type tuple = array<unknown>
Because of that, tuple has all the array methods: push, size, and others. Such arrays are opaque, so the push method accepts values of any type:
var t = [];   // array<unknown>
t.push(1);
t.push(null);
t.push(Point { x: 10, y: 20 });
Read more about arrays and tuples.

Manual type casts with as operator

Any type T can be cast to unknown using the as operator. If T is a primitive that fits in a single stack slot, the cast is a no-op. Otherwise, the object is packed into a sub-tuple:
var u = 5 as unknown;
// stack: 5
u as int;
// stack: 5

var u2 = (10, 20) as unknown;
// stack: [ 10 20 ] (a TVM tuple)
u2 as (int, int);
// stack: 10 20 (two integers)
To perform meaningful operations on an unknown value, cast it to a known type with as.

Exception arguments

In TVM, an exception can carry some value in an arbitrary stack slot. The syntax throw (code, arg) allows attaching an argument arg of unknown type:
fun load(id: int) {
    // ...
    throw (NOT_FOUND, id)
}

fun demo() {
    try {
        load(456);
    } catch (ex, arg) {
        // `arg` is `unknown`
        if (ex == NOT_FOUND) {
            arg as int;   // 456
        }
    }
}
Composite argument values are allowed. For example, the structure Point in throw (code, Point { ... }) will be packed to a single slot of unknown type. Casting arg as Point will unpack that unknown back.

Be extremely careful using unknown

Using unknown incorrectly may lead to runtime errors or stack corruption. Always extract a value of the exact type it was originally stored in. For example, this usage is invalid:
fun demoInvalid() {
    var x: int | slice = 123;
    var t = array<unknown> [x];
    t.get(0) as int | slice;   // runtime error
}
There, a runtime error occurs because the x has been smart cast to int when it was placed into the array t:
fun demoInvalid() {
    var x: int | slice = 123;
    // `x` is smart-cast to `int`
    var t = array<unknown> [x];
    // As such, `t` is [123], containing an integer.
    // Because of the unsafe type cast,
    // `t.get(0)` is viewed as a tagged union `int|slice` and not an `int`,
    // triggering a runtime error.
    t.get(0) as int | slice;
}

Stack layout and serialization

A value of type unknown takes a single TVM slot with any valid value at runtime. It cannot be serialized because the exact value type is not known.