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

# How to use on-chain libraries

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>
    </>;
};

Before using on-chain libraries, read about [library cells](/foundations/serialization/library). That page explains the cell format that on-chain libraries use.

<Aside type="danger" title="Funds at risk">
  Keep enough TON on the account that hosts the library to cover at least 10 years of storage. If the balance becomes too low, the library freezes and becomes inaccessible.
</Aside>

## When to use

Use library cells when multiple contracts share the same code and forwarding or storage costs need to be reduced, *resulting in fee savings*.

For example, in [jettons](/standard/tokens/jettons/overview), the [`StateInit`](/foundations/messages/deploy) must be forwarded with each transfer, which increases forwarding fees. Moving the code into a library cell reduces that overhead.

However, a library must be hosted in the masterchain, where storage is more expensive than in the basechain. If fewer than about 1,000 contracts share the same code, storing a copy in the basechain can be cheaper.

The exact ratio depends on blockchain [config parameter 18](/foundations/config#param-18-storage-prices). Compare storage and forwarding costs before choosing this approach.

### Common use cases

Everything in TON is stored in cells, including the account code. A common use case for libraries is shared code across multiple contracts. When a library cell is part of an account's `code`, the runtime dereferences it on first access. This makes it possible to replace part of the contract code, or even the entire code, with a library cell.

Replacing the entire code with a library cell is used in TON smart contracts. Examples include:

1. USDT and other jetton wallet contracts;
2. Multisig v2 order contracts;
3. NFT item contracts in popular collections.

### Check for library usage

Check whether a contract uses a library as its code by inspecting its `code` cell in an [explorer](/ecosystem/explorers/overview).

```txt title="Partial explorer snippet of a USDT jetton wallet account" theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
...
code:(just
      value:(raw@^Cell
        x{}
         SPECIAL x{028F452D7A4DFD74066B682365177259ED05734435BE76B5FD4BD5D8AF2B7C3D68}
        ))
...
```

The exact representation in the [TON Explorer](https://explorer.toncoin.org/) is not important. The key point is that the contract code contains a single `SPECIAL` cell, which indicates an exotic cell. The first byte equals `2`, which marks a library cell. The remaining bytes contain the hash of the referenced cell.

In this form, the entire contract code consists of the 8-bit tag `2` and the 256-bit representation hash of the referenced cell.

If only part of the code should live in a library cell, move the shared function into a library instead. This approach is used when multiple contracts reuse the same function. The build process for this setup may require custom tooling.

## Use `@ton/core`

Construct a library cell in TypeScript with the `@ton/core` library. The following example shows the pattern in a Blueprint project:

```ts title="TypeScript" theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import { Cell, beginCell } from '@ton/core';

const libPrep = beginCell().storeUint(2, 8).storeBuffer(jwalletCodeRaw.hash()).endCell();
const jwalletCode = new Cell({ exotic: true, bits: libPrep.bits, refs: libPrep.refs });
```

Reference implementation: [`JettonWallet.spec.ts`](https://github.com/ton-blockchain/stablecoin-contract/blob/de08b905214eb253d27009db6a124fd1feadbf72/sandbox_tests/JettonWallet.spec.ts#L104C1-L105C90).

## Publish an ordinary cell in the masterchain library context

The following Tolk example is based on the librarian contract from the [multisig v2 repository](https://github.com/ton-blockchain/multisig-contract-v2/blob/master/contracts/helper/librarian.func).

```tolk title="Tolk" expandable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import "@stdlib/gas-payments"

const DEFAULT_DURATION = 3600 * 24 * 365 * 10  // 10 years, can top-up any time
const MAX_LIBRARY_CELLS = 1000 // Network config limit for library cells
const PUBLIC_LIBRARY_MODE = 2 // Public library mode for masterchain contracts

// https://docs.ton.org/tvm/instructions#fb06-setlibcode
fun setLibCode(code: cell, mode: int): void
    asm "SETLIBCODE"

fun onInternalMessage(in: InMessage) {
    val senderAddress = in.senderAddress;
    val libToPublish = contract.getData();

    val initialGas = getGasConsumedAtTheMoment();
    val (orderCells, orderBits, _) = libToPublish.calculateSizeStrict(MAX_LIBRARY_CELLS);
    val sizeCountingGas = getGasConsumedAtTheMoment() - initialGas;

    val toReserve =
        calculateGasFeeWithoutFlatPrice(-1, sizeCountingGas) +
        calculateStorageFee(-1, DEFAULT_DURATION, orderBits, orderCells);

    reserveToncoinsOnBalance(toReserve, RESERVE_MODE_BOUNCE_ON_ACTION_FAIL);

    val reply = createMessage({
        bounce: BounceMode.NoBounce,
        dest: senderAddress,
        value: 0
    });
    reply.send(SEND_MODE_CARRY_ALL_BALANCE);

    setLibCode(libToPublish, PUBLIC_LIBRARY_MODE);

    contract.setCodePostponed(createEmptyCell());
    contract.setData(createEmptyCell());
}
```

This contract requires enough TON for at least 10 years of storage. That prevents the library from freezing shortly after publication and becoming inaccessible.

The key line is `setLibCode(libToPublish, PUBLIC_LIBRARY_MODE);`. This call publishes an ordinary cell with the flag set to `2`, which makes the library public.

<Aside type="note">
  After publication, the contract becomes bricked, so no further operations are possible.
</Aside>

## Test libraries with Acton

Refer to the [on-chain libraries guide](https://ton-blockchain.github.io/acton/docs/libraries) in Acton documentation.

## Test libraries with Blueprint

When testing smart contracts locally, there are two ways to register libraries in the blockchain environment: automatically and manually.

### Automatic library deployment

Enable automatic library detection by passing the `autoDeployLibs` flag when creating the blockchain:

```ts title="TypeScript" theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
const blockchain = await Blockchain.create({ autoDeployLibs: true });
```

For contracts deployed in the masterchain, publish the library with the librarian example above.

This lets the contract install and register the library at runtime, while the environment tracks and uses it automatically.

### Manual library deployment

If `autoDeployLibs` is not enabled, register libraries manually:

```ts title="TypeScript" theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
const blockchain = await Blockchain.create();
const code = await compile('Contract');

// Create a dictionary of library hash → library cell
const libsDict = Dictionary.empty(Dictionary.Keys.Buffer(32), Dictionary.Values.Cell());
libsDict.set(code.hash(), code);

// Manually assign the libraries
blockchain.libs = beginCell().storeDictDirect(libsDict).endCell();
```

This approach gives full control, but it requires explicit management of the libraries available during testing.

Reference implementation: [`JettonWallet.spec.ts`](https://github.com/ton-blockchain/stablecoin-contract/blob/de08b905214eb253d27009db6a124fd1feadbf72/sandbox_tests/JettonWallet.spec.ts#L100C9-L103C32).

## Get methods for library-backed contracts

When working with a jetton wallet whose code is stored in a library cell, check its balance by executing a get method.

When methods run through the [HTTP API](/ecosystem/api/overview) or [liteserver](/ecosystem/nodes/overview), the library cell is resolved automatically and the method runs against the resolved code.

For local execution, pull the account state and resolve every library reference cell first. In most cases, the entire code cell is itself a library reference.
To resolve a library, call the [`/getLibraries` method](/ecosystem/api/toncenter/v2/configuration/get-libraries).

### Retrieve a library cell with Acton

To inspect an existing library or read its code, use `acton library fetch`:

```bash theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
acton library fetch <LIBRARY_HASH>
```

See the [on-chain libraries guide](https://ton-blockchain.github.io/acton/docs/libraries) in Acton documentation for more.

### Retrieve a library cell with liteserver

To retrieve library cells from liteserver, use the [`liteServer.getLibraries`](https://github.com/ton-blockchain/ton/blob/4cfe1d1a96acf956e28e2bbc696a143489e23631/tl/generate/scheme/lite_api.tl#L96) method.

```ts title="TypeScript" expandable theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import { LiteClient, LiteRoundRobinEngine, LiteSingleEngine } from "ton-lite-client";
import { Cell } from "@ton/core";
import { z } from "zod";

function intToIP(int: number): string {
    const buf = Buffer.alloc(4);
    buf.writeUInt32BE(int >>> 0, 0);
    return Array.from(buf).join(".");
}

const Server = z.object({
    ip: z.number(),
    port: z.number(),
    id: z.object({ key: z.string() }),
});

const Response = z.object({
    liteservers: z.array(Server),
});

// testnet https://ton.org/testnet-global.config.json
// mainnet https://ton.org/global.config.json
const configEndpoint = "https://ton.org/global.config.json";

async function getServers() {
    const data = Response.parse(await (await fetch(configEndpoint)).json());
    return data.liteservers.map((server) => {
        return new LiteSingleEngine({
            host: `tcp://${intToIP(server.ip)}:${server.port}`,
            publicKey: Buffer.from(server.id.key, 'base64'),
        });
    });
}

async function getLibraryByHash(hash: Buffer) {
    const engine = new LiteRoundRobinEngine(await getServers());
    const client = new LiteClient({ engine });
    const libs = await client.getLibraries([hash]);
    const lib = libs.result[0];
    if (!lib || libs.result.length !== 1) {
        throw new Error("Library not found");
    }
    const roots = Cell.fromBoc(lib.data);
    const root = roots[0];
    if (!root || roots.length !== 1) {
        throw new Error("Malformed BoC for a library");
    }
    return root.toBoc().toString("hex");
}

async function main() {
    const hash = Buffer.from("8F452D7A4DFD74066B682365177259ED05734435BE76B5FD4BD5D8AF2B7C3D68", "hex");
    const code = await getLibraryByHash(hash);
    console.log(code);
}

void main();
```
