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

# Idioms and conventions

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

This section summarizes common patterns and conventions used in idiomatic Tolk code.

While [Basic syntax](/languages/tolk/basic-syntax) introduces the language itself,
this page outlines the preferred **ways of expressing ideas** and **best practices** in Tolk.
It may serve as a style reference throughout development.

## Auto-serialization instead of slices/builders

Tolk [type system](/languages/tolk/types/list-of-types) is designed to entirely avoid manual cell parsing.
The presence of `beginCell()` indicates a possibly wrong approach.
All practical use cases in contract interaction are expressed with structures, unions, and references.

```tolk theme={null}
struct Holder {
    owner: address
    lastUpdated: uint32
    extra: Cell<ExtraInfo>
}

fun demo(data: Holder) {
    // make a cell with 299 bits and 1 ref
    val c = data.toCell();

    // unpack it back
    val holder = Holder.fromCell(c);
}
```

<Aside type="tip" title={"Familiar with TL-B?"}>
  The type system is considered as a **replacement** for TL-B.<br />
  Read [Tolk vs TL-B](/languages/tolk/from-func/tolk-vs-tlb).
</Aside>

See: [automatic serialization](/languages/tolk/features/auto-serialization).

## Cell\<T> — a "cell with known shape"

All data in TON is stored in cells that reference each other.
To express clear data relation, use **typed cells** — `Cell<T>`.

Literally, it means: a cell whose contents is `T`:

```tolk theme={null}
struct Holder {
    // ...
    extra: Cell<ExtraInfo>
}

struct ExtraInfo {
    someField: int8
    // ...
}

fun getDeepData(value: Holder) {
    // `value.extra` is a reference
    // use `load()` to access its contents
    val data = value.extra.load();
    return data.someField;
}
```

See: [cell references in serialization](/languages/tolk/features/auto-serialization#controlling-cell-references-typed-cells).

## Not "fromCell", but "lazy fromCell"

In practice, when reading data from cells, prefer `lazy`:

* `lazy SomeStruct.fromCell(c)` over `SomeStruct.fromCell(c)`
* `lazy typedCell.load()` over `typedCell.load()`

The compiler loads only requested fields, skipping the rest.
It reduces gas consumption and bytecode size.

```tolk theme={null}
get fun publicKey() {
    val st = lazy Storage.load();
    // <-- here "skip 65 bits, preload uint256" is inserted
    return st.publicKey
}
```

See: [lazy loading](/languages/tolk/features/lazy-loading).

## Custom serializers — if can't express with types

Even though the type system is very rich, there still may occur situations where
binary serialization is non-standard.
Tolk allows to declare custom types with arbitrary serialization rules.

```tolk theme={null}
type MyString = slice

fun MyString.packToBuilder(self, mutate b: builder) {
    // custom logic
}

fun MyString.unpackFromSlice(mutate s: slice) {
    // custom logic
}
```

And just use `MyString` as a regular type — everywhere:

```tolk theme={null}
struct Everywhere {
    tokenName: MyString
    fullDomain: Cell<MyString>
}
```

An interesting example. Imagine a structure which tail is signed:

```tolk theme={null}
struct SignedRequest {
    signature: uint256
    // hash of all data below is signed
    field1: int32
    field2: address?
    // ...
}
```

The task is to parse it and check signature.
A manual solution is obvious: read uint256, calculate the hash of the remainder, read other fields.

What about the type system?
Even this complex scenario can be expressed by introducing a synthetic field that is populated on loading:

```tolk theme={null}
type HashOfRemainder = uint256

struct SignedRequest {
    signature: uint256
    restHash: HashOfRemainder   // populated on load
    field1: int32
    field2: address?
    // ...
}

fun HashOfRemainder.unpackFromSlice(mutate s: slice) {
    // `s` is after reading `signature` in our case;
    // we don't need to load anything —
    // just calculate the hash on the fly
    return s.hash()
}

fun demo(input: slice) {
    val req = SignedRequest.fromSlice(input);
    assert (req.signature == req.restHash) throw XXX;
}
```

See: [serialization of type aliases](/languages/tolk/types/overall-serialization#type-aliases).

## Contract storage = struct + load + save

Contract storage is a regular `struct`, serialized into persistent on-chain data.
It is convenient to add `load` and `store` methods:

```tolk theme={null}
struct Storage {
    counterValue: int64
}

fun Storage.load() {
    return Storage.fromCell(contract.getData())
}

fun Storage.save(self) {
    contract.setData(self.toCell())
}
```

See: [contract storage](/languages/tolk/features/contract-storage).

## Message = struct with a 32-bit prefix

By convention, every message in TON has an **opcode** — a unique 32-bit number.
In Tolk, every struct can have a "serialization prefix" of arbitrary length.
32-bit prefixes are called opcodes.

So, every incoming and outgoing message is a struct with a prefix:

```tolk theme={null}
struct (0x12345678) CounterIncrement {
    // ...
}
```

<Aside type="tip" title={"Guidelines for choosing opcodes"}>
  * When implementing jettons, NFTs, and other standards, use predefined prefixes according to the specification of each TEP.
  * When developing custom protocols, use any random numbers.
</Aside>

See: [structures](/languages/tolk/syntax/structures-fields).

## Handle a message = structs + union + match

The suggested pattern to handle messages:

* each incoming message is a struct with an opcode
* combine these structs into a union
* parse it via `lazy fromSlice` and `match` over variants

```tolk theme={null}
struct (0x12345678) CounterIncrement {
    incBy: uint32
}

struct (0x23456789) CounterReset {
    initialValue: int64
}

type AllowedMessage = CounterIncrement | CounterReset

fun onInternalMessage(in: InMessage) {
    val msg = lazy AllowedMessage.fromSlice(in.body);
    match (msg) {
        CounterIncrement => {
            // use `msg.incBy`
        }
        CounterReset => {
            // use `msg.initialValue`
        }
        else => {
            // invalid input; a typical reaction is:
            // ignore empty messages, "wrong opcode" if not
            assert (in.body.isEmpty()) throw 0xFFFF
        }
    }
}
```

Notice `lazy`: it also works with unions and does "lazy match" by a slice prefix.
It's much more efficient than manual parsing an opcode and branching via `if (op == TRANSFER_OP)`.

See: [handling messages](/languages/tolk/features/message-handling) and [pattern matching](/languages/tolk/syntax/pattern-matching).

## Send a message = struct + createMessage

To send a message from contract A to contract B,

* declare a struct, specify an opcode and fields expected by a receiver
* use `createMessage` + `send`

```tolk theme={null}
struct (0x98765432) RequestedInfo {
    // ...
}

fun respond(/* ... */) {
    val reply = createMessage({
        bounce: BounceMode.NoBounce,
        value: ton("0.05"),
        dest: addressOfB,
        body: RequestedInfo {
            // ... initialize fields
        }
    });
    reply.send(SEND_MODE_REGULAR);
}
```

<Aside type="tip">
  When both contracts are developed in the same project (sharing common codebase),
  such a struct is both an outgoing message for A and an incoming message for B.
</Aside>

## Deploy another contract = createMessage

A common case: a minter deploys a jetton wallet, knowing wallet's code and initial state.
This "deployment" is actually sending a message, auto-attaching code+data, and auto-calculating its address:

```tolk theme={null}
val deployMsg = createMessage({
    // address auto-calculated, code+data auto-attached
    dest: {
        stateInit: {
            code: jettonWalletCode,
            data: emptyWalletStorage.toCell(),
        }
    }
});
```

A preferred way is to extract generating `stateInit` to a separate function, because
it's used not only to send a message, but also to calculate/validate an address without sending.

```tolk theme={null}
fun calcDeployedJettonWallet(/* ... */): AutoDeployAddress {
    val emptyWalletStorage: WalletStorage = {
        // ... initialize fields from parameters
    };

    return {
        stateInit: {
            code: jettonWalletCode,
            data: emptyWalletStorage.toCell()
        }
    }
}

fun demoDeploy() {
    val deployMsg = createMessage({
        // address auto-calculated, code+data auto-attached
        dest: calcDeployedJettonWallet(...),
        // ...
    });
    deployMsg.send(mode);
}
```

See: [tolk-bench repo](https://github.com/ton-blockchain/tolk-bench) for reference jettons.

## Shard optimization = createMessage

"Deploy a contract to a specific shard" is also done with the same technique.
For example, in sharded jettons, a jetton wallet must be deployed to the same shard as the owner's wallet.

```tolk theme={null}
val deployMsg = createMessage({
    dest: {
        stateInit: { code, data },
        toShard: {
            closeTo: ownerAddress,
            fixedPrefixLength: 8
        }
    }
});
```

Following the guideline above, the task is resolved by adding just a couple lines of code.
Sharding will automatically be supported in `createMessage` and other address calculations.

```tolk theme={null}
fun calcDeployedJettonWallet(/* ... */): AutoDeployAddress {
    // ...
    return {
        stateInit: ...,
        toShard: {
            closeTo: ownerAddress,
            fixedPrefixLength: SHARD_DEPTH
        }
    }
}
```

See: [sharding in createMessage](/languages/tolk/features/message-sending#sharding:-deploying-%E2%80%9Cclose-to%E2%80%9D-another-contract).

## Emitting events/logs to off-chain

Emitting events and logs "to the outer world" is done via **external messages**.
They are useful for monitoring: being indexed by TON indexers,
they show "a picture of on-chain activity".
These are also messages and also cost gas, but are constructed in a slightly different way.

1. Create a `struct` to represent the message body
2. Use `createExternalLogMessage` + `send`

```tolk theme={null}
struct DepositEvent {
    // ...
}

fun demo() {
    val emitMsg = createExternalLogMessage({
        dest: createAddressNone(),
        body: DepositEvent {
            // ...
        }
    });
    emitMsg.send(SEND_MODE_REGULAR);
}
```

See: [sending external messages](/languages/tolk/features/message-sending#universal-createexternallogmessage).

## Return a struct from a get method

When a contract getter (`get fun`) needs to return several values — introduce a structure and return it.
Do not return unnamed tensors like `(int, int, int)`.
Field names provide clear metadata for client wrappers and human readers.

```tolk theme={null}
struct JettonWalletDataReply {
    jettonBalance: coins
    ownerAddress: address
    minterAddress: address
    jettonWalletCode: cell
}

get fun get_wallet_data(): JettonWalletDataReply {
    return {
        jettonBalance: ...,
        ownerAddress: ...,
        minterAddress: ...,
        jettonWalletCode: ..,
    }
}
```

See: [contract getters](/languages/tolk/features/contract-getters).

## Use assertions to validate user input

After parsing an incoming message, validate required fields with `assert`:

```tolk theme={null}
assert (msg.seqno == storage.seqno) throw E_INVALID_SEQNO;
assert (msg.validUntil > blockchain.now()) throw E_EXPIRED;
```

Execution will terminate with some `errCode`, and a contract will be ready to serve the next request.
This is the standard mechanism for reacting on invalid input.

See: [exceptions](/languages/tolk/syntax/exceptions).

## Organize a project into several files

No matter whether a project contains one contract or multiple — split it into files.
Having identical file structure across all projects simplifies navigation:

* `errors.tolk` with constants or enums
* `storage.tolk` with a storage and helper methods
* `messages.tolk` with incoming/outgoing messages
* `some-contract.tolk` as an entrypoint
* probably, some other

When several contracts are developed simultaneously, their share the same codebase.
For instance, struct `SomeMessage`, outgoing for contract A, is incoming for contract B.
Or for deployment, contract A should know B's storage to assign `stateInit`.

<Aside type="tip" title={"Use only minimal declarations inside each contract.tolk"}>
  Typically, each `some-contract.tolk` file contains:

  * a union with available incoming messages
  * entrypoints: `onInternalMessage`, `get fun`
  * structures for complex replies from getters

  The remaining codebase is shared.
</Aside>

See: [imports](/languages/tolk/syntax/imports).

## Prefer methods to functions

All symbols across different files share the same namespace and must have unique names project-wise.
There are no "modules" or "exports".

Using methods avoids name collisions:

```tolk theme={null}
fun Struct1.validate(self) { /* ... */ }
fun Struct2.validate(self) { /* ... */ }
```

Methods are also more convenient: `obj.someMethod()` looks nicer than `someFunction(obj)`:

```tolk theme={null}
struct AuctionConfig {
    // ...
}

// NOT
// fun isAuctionConfigInvalid(config: AuctionConfig)
// BUT
fun AuctionConfig.isInvalid(self) {
    // ...
}
```

Same for static methods: `Auction.createFrom(...)` seems better than `createAuctionFrom(...)`.
A method without `self` is a static one:

```tolk theme={null}
fun Auction.createFrom(config: cell, minBid: coins) {
    // ...
}
```

Static methods may also be used to group various utility functions.
For example, standard functions `blockchain.now()` and others are essentially static methods of an empty struct.

```tolk theme={null}
struct blockchain

fun blockchain.now(): int /* ... */;
fun blockchain.logicalTime(): int /* ... */;
```

In large projects, this technique may be used to emulate namespaces.

See: [functions and methods](/languages/tolk/syntax/functions-methods).

## How to describe "forward payload" in jettons

By a standard, a jetton transfer may have `forwardPayload` attached, which TL-B format is `(Either Cell ^Cell)`.
How to describe this in Tolk?

```tolk theme={null}
struct Transfer {
    // ...
    forwardPayload: RemainingBitsAndRefs | cell
}
```

The union above is exactly what TL-B's `Either` means. It will work, but has some disadvantages in gas consumption and validation (for a `cell` we also need to check that no extra data exists besides the ref).

Actually, no universal solution exists — it depends on particular requirements:

* is the validation needed?
* are custom error codes needed on error?
* should it be convenient to be assigned from code?

All these cases are described on a separate page.

See: [forward payload in jettons](/languages/tolk/features/jetton-payload).

## How to describe "address or none" in a field

A nullable address — `address?` — is a pattern to say "optional address", sometimes called "maybe address".

* `null` is "none", serialized as '00' (two zero bits)
* `address` is "internal", serialized as 267 bits: '100' + workchain + hash

See: [addresses](/languages/tolk/types/address).

## How to calculate crc32/sha256 at compile-time

Several built-in functions operate on strings and work at compile-time:

```tolk theme={null}
// calculates crc32 of a string
const crc32 = stringCrc32("some_str")

// calculates sha256 of a string and returns 256-bit integer
const hash = stringSha256("some_crypto_key")

// and more
```

See: [standard library](/languages/tolk/features/standard-library).

## How to return a string from a contract

TVM has no strings, it has only slices.
A binary slice must be encoded in a specific way to be parsed and interpreted correctly as a string.

1. Fixed-size strings via `bitsN` — possible if the size is predefined.
2. Snake strings: portion of data → the rest in a ref cell, recursively.
3. Variable-length encoding via custom serializers.

See: [strings](/languages/tolk/types/strings).

## Final suggestion: do not micro-optimize

Tolk compiler is smart.
It targets "zero overhead": clean, consistent logic must be as efficient as low-level code.
It automatically inlines functions, reduces stack permutations, and does a lot of underlying work
to let a developer focus on business logic.
And it works.
Any attempts to overtrick the compiler result either in negligible or even in negative effect.

That's why, follow the "**readability-first principle**":

* use one-line methods without any worries — they are auto-inlined
* use small structures — they are as efficient as raw stack values
* extract constants and variables for clarity
* do not use assembler functions unless being absolutely sure

<Aside type="tip">
  Use Tolk as intended — gas will take care of itself.<br />
  But if the logic is hard to follow — it's where the inefficiency hides.
</Aside>

See: [compiler optimizations](/languages/tolk/features/compiler-optimizations).
