> ## Documentation Index
> Fetch the complete documentation index at: https://companyname-a7d5b98e-nft-comparison.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Constructing messages

In FunC, message cells were composed manually:

```func theme={null}
cell m = begin_cell()
    .store_uint(0x10, 6)
    .store_slice(sender_address)
    .store_coins(50000000)
    .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
    .store_uint(0x178d4519, 32)
    .store_uint(query_id, 64)
    ...
    .end_cell();
send_raw_message(m, 0);
```

In Tolk, there is a high-level function:

```tolk theme={null}
val reply = createMessage({
    bounce: BounceMode.NoBounce,
    value: ton("0.05"),
    dest: senderAddress,
    body: RequestedInfo { ... }
});
reply.send(SEND_MODE_REGULAR);
```

## Key features of `createMessage`

1. Supports extra currencies
2. Supports [`StateInit`](/foundations/messages/deploy) with automatic address computation
3. Supports workchains
4. Supports sharding (formerly `splitDepth`)
5. Integrated with auto-serialization of `body`
6. Automatically detects **body ref or not**
7. More efficient than handwritten code

## The concept is based on union types

There is a variety of interacting between contracts. When you explore FunC implementations, you notice that:

* sometimes, you "send to an address (slice)"
* ... but sometimes, you "build the address (builder) manually"
* sometimes, you compose `StateInit` from code+data
* ... but sometimes, you already have `StateInit` as a ready cell
* sometimes, you send a message to basechain
* ... but sometimes, you have the `MY_workchain` constant and use it everywhere
* sometimes, you just attach tons (**msg value**)
* ... but sometimes, you also need extra currencies
* etc.

**How can we describe such a vast variety of options? The solution is union types!**

Let's start exploring this idea by looking at how extra currencies are supported.

## Extra currencies: union

When you don't need them, you just attach **msg value** as tons:

```tolk theme={null}
value: someTonAmount
```

When you need them, you attach tons AND extra currencies dict:

```tolk theme={null}
value: (someTonAmount, extraDict)
```

How does it work? Because the field `value` is a union:

```tolk theme={null}
// how it is declared in stdlib
type ExtraCurrenciesDict = dict;

struct CreateMessageOptions<TBody> {
    ...
    /// message value: attached tons (or tons + extra currencies)
    value: coins | (coins, ExtraCurrenciesDict)
```

That's it! You just attach tons OR tons with extra, and the compiler takes care of composing this into a cell.

## Destination: union

The same idea of union types spreads onto **destination** of a message.

```tolk theme={null}
dest: someAddress,
dest: (workchain, hash)
```

It's either an address, OR (workchain + hash), OR ...:

```tolk theme={null}
struct CreateMessageOptions<TBody> {
    ...
    /// destination is either a provided address, or is auto-calculated by stateInit
    dest: address |             // either just send a message to some address
          builder |             // ... or a manually constructed builder with a valid address
          (int8, uint256) |     // ... or to workchain + hash (also known as accountID)
          AutoDeployAddress;    // ... or "send to stateInit" aka deploy (address auto-calculated)
```

**That's indeed the TypeScript way** — but it works at compile-time!

## `StateInit` and workchains

Let's start from an example. From a jetton minter, you are deploying a jetton wallet. You know wallet's code and initial data:

```tolk theme={null}
val walletInitialState: ContractState = {
    code: ...,   // probably, kept in minter's storage
    data: ...,   // zero balance, etc. (initial wallet's storage)
};
```

Now, from a minter, you want to send a message to a wallet. But since you are not sure whether the wallet already exists onchain, you attach its code+data: if a wallet doesn't exist, it's immediately initialized with that code. So, where should you send a message to? What is **destination**? The answer is: **destination is the wallet's `StateInit`**. You need to send a message to a `walletInitialState` because, in TON, the address of a contract is — by definition — a hash of its initial state:

```tolk theme={null}
// address auto-calculated, code+data auto-attached
dest: {
    stateInit: walletInitialState
}
```

In more complex tasks, you can configure additional fields:

```tolk theme={null}
dest: {
    workchain: ...,     // by default, 0 (basechain)
    stateInit: ...,     // either code+data OR a ready cell
    toShard:   ...,     // by default, null (no sharding)
}
```

That's the essence of `AutoDeployAddress`. Here is how it's declared in stdlib:

```tolk theme={null}
// declared in stdlib
struct AutoDeployAddress {
    workchain: int8 = BASECHAIN;
    stateInit: ContractState | cell;
    toShard: AddressShardingOptions? = null;
}
```

## Sharding: deploying "close to" another contract

The `createMessage` interface also supports initializing contracts in specific shards. Say you're writing sharded jettons, and you want every jetton wallet to be in the same shard as the owner's wallet.

In other words, your intention is:

* a jetton wallet must be **close to** the owner's wallet
* this *closeness* is determined by a shard depth (syn. *fixed prefix length*, syn. *split depth*)

Let's illustrate it with numbers for `shard depth` = 8:

| Title                | Addr hash (256 bits) | Comment                              |
| -------------------- | -------------------- | ------------------------------------ |
| closeTo (owner addr) | `01010101...xxx`     | owner's wallet                       |
| shardPrefix          | `01010101`           | first 8 bits of closeTo              |
| stateInitHash        | `yyyyyyyy...yyy`     | calculated by code+data              |
| result (JW addr)     | `01010101...yyy`     | jetton wallet in same shard as owner |

That's how you do it:

```tolk theme={null}
dest: {
    stateInit: walletInitialState,
    toShard: {
        closeTo: ownerAddress,
        fixedPrefixLength: 8
    }
}
```

Technically, **shard depth** must be a part of `StateInit` (besides code+data) — for correct initialization inside the blockchain. The compiler automatically embeds it.

But semantically, **shard depth** alone makes no sense. That's why **shard depth + closeTo** is a single entity:

```tolk theme={null}
// how it is declared in stdlib
struct AutoDeployAddress {
    ...
    toShard: AddressShardingOptions? = null;
}

struct AddressShardingOptions {
    fixedPrefixLength: uint5;    // shard depth, formerly splitDepth
    closeTo: address;
}
```

## Body ref or not: compile-time calculation

In TON Blockchain, according to the specification, a message is a cell (flags, dest address, stateInit, etc.), and its *body* can be either inlined into the same cell or can be placed into its own cell (and be a ref).

In FunC, you had to manually calculate whether it's safe to embed body (you did it *on paper* or dynamically). In Tolk, you just pass `body`, and the compiler does all calculations for you:

```tolk theme={null}
createMessage({
    ...
    body: RequestedInfo { ... }    // no `toCell`! just pass an object
});
```

The rules are the following:

1. if `body` is small, it's embedded directly into a message cell
2. if `body` is large or unpredictable, it's wrapped into a ref

Why not make a ref always? Because creating cells is expensive. Avoiding cells for small bodies is crucial for gas consumption.

Interestingly, whether the body is **small** is determined **AT COMPILE TIME — no runtime checks are needed**. How? Thanks to generics! Here’s how `createMessage` is declared:

```tolk theme={null}
fun createMessage<TBody>(options: CreateMessageOptions<TBody>): OutMessage;

struct CreateMessageOptions<TBody> {
    ...
    body: TBody;
}
```

Hence, when you pass `body: RequestedInfo {...}`, then `TBody = RequestedInfo`, and the compiler estimates its size:

* it's **small** if its maximum size is less than 500 bits and 2 refs — then **no ref**
* it's **large** if >= 500 bits or >= 2 refs — then "ref"
* it's **unpredictable** if contains `builder` or `slice` inside — then **ref**

**Even if body is large/unpredictable, you can force it to be inlined** by wrapping into a special type:

```tolk theme={null}
// potentialy 620 bits (if all coins are billions of billions)
// by default, compiler will make a ref
struct ProbablyLarge {
    a: (coins, coins, coins, coins, coins)
}

val contents: ProbablyLarge = { ... };  // but you are sure: coins are small
createMessage({                         // so, you take the risks
    body: UnsafeBodyNoRef {             // and force "no ref"
        forceInline: contents,
    }

// here TBody = UnsafeBodyNoRef<ProbablyLarge>
```

If `body` is already a cell, it will be left as a ref, without any surprise:

```tolk theme={null}
createMessage({
    body: someCell,       // ok, just a cell, keep it as a ref

// here TBody = cell
```

That's why, don't pass `body: someObj.toCell()`, pass just `body: someObj`, let the compiler take care of everything.

## Body is not restricted to structures

In practice, you use `createMessage` to send a message (sic!) to another contract — in the exact format as the receiver expects.
You declare a struct with 32-bit opcode and some data in it.

```tolk theme={null}
struct (0xd53276db) Excesses {
    queryId: uint64;
}

val excessesMsg = createMessage({
   ...
   body: Excesses {
       queryId: input.queryId,
   }
});
excessesMsg.send(SEND_MODE_IGNORE_ERRORS);
```

This works perfectly, as expected. But an interesting fact—this also works:

```tolk theme={null}
// just an example, that even this would work
val excessesMsg = createMessage({
   ...
   body: (0xd53276db as int32, input.queryId)
});
excessesMsg.send(SEND_MODE_IGNORE_ERRORS);
```

Even this is okay, it is inferred as `createMessage<(int32, uint64)>(...)` and encoded correctly.

The example above just illustrates the power of the type system, no more.

## Body can be empty

If you don't need any `body` at all, just leave it out:

```tolk theme={null}
createMessage({
    bounce: BounceMode.NoBounce,
    dest: somewhere,
    value: remainingBalance
});
```

A curious reader might ask, "what's the type of `body` here? How is it expressed in the type system?" The answer is: `void`.

Actually, `CreateMessageOptions` is declared like this:

```tolk theme={null}
// declared in stdlib
struct CreateMessageOptions<TBody = void> {
    ...
    body: TBody;
}
```

Hence, omitting `body` in `createMessage` defaults `TBody` to `void`.
And by convention, fields having `void` type are not required in a literal.

## Don't confuse `StateInit` and code+data, they are different

It's incorrect to say that **`StateInit` is code+data**, because in TON, a full `StateInit` cell contents is richer (consider `block.tlb`):

* it also contains fixed\_prefix\_length (formerly split\_depth),
* it also contains ticktock info
* it also contains a library cell
* code and data are actually optional

For instance, when sending a message to another shard, fixed\_prefix\_length is automatically set by the compiler (from `toShard.fixedPrefixLength`).

That's why a structure **code+data** is named `ContractState`, NOT `StateInit`:

```tolk theme={null}
// in stdlib
struct ContractState {
    code: cell;
    data: cell;
}
```

And that's why a field `stateInit: ContractState | cell` is named **stateInit**, emphasizing that `StateInit` can be initialized automatically from `ContractState` (or can be a well-formed **rich** cell).

## Why not send, but createMessage?

You might ask: "why do we follow the pattern `val msg = createMessage(...); msg.send(mode)` instead of just `send(... + mode)` ?"

Typically, yes — you send a message immediately after composing it. But there are also advanced use cases:

* not just send, but send and estimate fees,
* or estimate fees without sending,
* or get a message hash,
* or save a message cell to storage for later sending,
* or even push it to an action phase.

So, composing a message cell and THEN doing some action with it is a more flexible pattern.

Moreover, following this pattern requires you to give **a name** to a variable. Advice is not to name it "m" or "msg," but to give a descriptive name like "excessesMsg" or "transferMsg":

```tolk theme={null}
val excessesMsg = createMessage({
    ...
});
excessesMsg.send(mode);
// also possible
excessesMsg.sendAndEstimateFee(mode);
```

This strategy makes the code **easier to read** later. You see — okay, this is about excesses, this one is about burn notification, etc. As opposed to a potential `send(...)` function, you have to dig into what body is actually being sent to understand what’s going on.

## Why not provide a separate deploy function?

You might also ask: why do we join `stateInit` as a **destination** for other use cases? Why not make a `deploy()` function that accepts code+data and drops stateInit from a **regular** createMessage?

The answer lies in terminology. Yes, **attaching stateInit** is often referred to as **deployment**, but it's an inaccurate term. **TON Blockchain doesn't have a dedicated deployment mechanism.** You send a message to some *void*  — and if this *void* doesn't exist, but you've attached a way to initialize it (code+data) — it's initialized immediately and accepts your message.

If you wish to emphasize the deployment, give it *a name*:

```tolk theme={null}
val deployMsg = createMessage({
    ...
});
deployMsg.send(mode);
```

## Universal createExternalLogMessage

The philosophy is similar to `createMessage`. But **external outs** don't have **bounce**; you don't attach tons, etc. So, options for creating are different.

**Currently, external messages are used only for emitting logs (for viewing them in indexers).** But theoretically, they can be extended to **send messages to the offchain**.

Example:

```tolk theme={null}
val emitMsg = createExternalLogMessage({
    dest: createAddressNone(),
    body: DepositEvent { ... }
});
emitMsg.send(SEND_MODE_REGULAR);
```

**Available options for external-out messages** are only `dest` and `body`, actually:

```tolk theme={null}
struct CreateExternalLogMessageOptions<TBody = void> {
    /// destination is either an external address or a pattern to calculate it
    dest: any_address |     // either some valid external/none address (not internal!)
          builder |         // ... or a manually constructed builder with a valid external address
          ExtOutLogBucket;  // ... or encode topic/eventID in destination

    /// body is any serializable object (or just miss this field for empty body)
    body: TBody;
}
```

So, as for `createMessage` — just pass `someObject`, do NOT call `toCell()`, let the compiler decide whether it fits into the same cell or not. `UnsafeBodyNoRef` is also applicable.

**Emitting external logs, example 1**:

```tolk theme={null}
struct DepositData {
    amount: coins;
    ...
}

val emitMsg = createExternalLogMessage({
    dest: ExtOutLogBucket { topic: 123 },   // 123 for indexers
    body: DepositData { ... }
});
emitMsg.send(SEND_MODE_REGULAR);
```

**Emitting external logs, example 2**:

```tolk theme={null}
struct (0x12345678) DepositEvent {
    amount: coins;
    ...
}

createExternalLogMessage({
    dest: createAddressNone(),
    body: DepositEvent { ... }   // 0x12345678 for indexers
});
```

`ExtOutLogBucket` is a variant of a custom external address for emitting logs **to the outer world.** It includes some **topic** (arbitrary number), that determines the format of the message body. In the example above, you emit **deposit event** (reserving topic `deposit` = 123) — and external indexers will index your emitted logs by destination address without parsing body.
