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

# Wallets history

export const Aside = ({type = 'note', title = "", children}) => {
  const asideVariants = ['note', 'tip', 'caution', 'danger'];
  if (!asideVariants.includes(type)) {
    throw new Error('Invalid `type` prop passed to the `<Aside>` component.\n' + `Received: ${JSON.stringify(type)}\n` + `Expected one of ${asideVariants.map(i => JSON.stringify(i)).join(', ')}`);
  }
  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>
    }
  };
  return <>
    <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[type].outerStyle}`} data-callout-type={asideComponents[type].calloutType}>
      <div className="mt-0.5 w-4" data-component-part="callout-icon">{asideComponents[type].icon}</div>
      <div className={`text-sm prose min-w-0 w-full ${asideComponents[type].innerStyle}`} data-component-part="callout-content">
        {title && <p className="font-bold">{title}</p>}
        {children}</div>
    </div>
  </>;
};

You may have heard about different versions of wallets on TON Blockchain. But what do these versions actually mean, and how do they differ?

In this article, we will explore the various versions and modifications of TON wallets.

## Common concept

We should first understand that wallets are not a specific entity in the TON ecosystem. They are still just smart contracts consisting of code and data, and, in that sense, are equal to any other actor (i.e., smart contract) in TON.

Read more about [differences](/guidebook/from-ethereum).

Like your own custom smart contract, or any other one, wallets can receive external and internal messages, send internal messages and logs, and provide `get methods`.
So the question is: what functionality do they provide and how do they differ between versions?

You can consider each wallet version as a smart contract implementation providing a standard external interface, allowing different external clients to interact with the wallets in the same way. You can find these implementations in FunC and Fift languages in the main TON monorepo:

* [ton/crypto/smartcont/](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/)

## Basic wallets

### Wallet contract hashes

Here, you can find the current hashes of the wallet contract code versions.
For detailed specifications of each wallet contract, please refer further down the page or check the [ContractSources.md](https://github.com/toncenter/tonweb/blob/update_contracts/src/contract/ContractSources.md).

| Contract version    | Hash                                                               |
| ------------------- | ------------------------------------------------------------------ |
| [V1 R1](#wallet-v1) | `a0cfc2c48aee16a271f2cfc0b7382d81756cecb1017d077faaab3bb602f6868c` |
| [V1 R2](#wallet-v1) | `d4902fcc9fad74698fa8e353220a68da0dcf72e32bcb2eb9ee04217c17d3062c` |
| [V1 R3](#wallet-v1) | `587cc789eff1c84f46ec3797e45fc809a14ff5ae24f1e0c7a6a99cc9dc9061ff` |
| [V2 R1](#wallet-v2) | `5c9a5e68c108e18721a07c42f9956bfb39ad77ec6d624b60c576ec88eee65329` |
| [V2 R2](#wallet-v2) | `fe9530d3243853083ef2ef0b4c2908c0abf6fa1c31ea243aacaa5bf8c7d753f1` |
| [V3 R1](#wallet-v3) | `b61041a58a7980b946e8fb9e198e3c904d24799ffa36574ea4251c41a566f581` |
| [V3 R2](#wallet-v3) | `84dafa449f98a6987789ba232358072bc0f76dc4524002a5d0918b9a75d2d599` |
| [V4 R1](#wallet-v4) | `64dd54805522c5be8a9db59cea0105ccf0d08786ca79beb8cb79e880a8d7322d` |
| [V4 R2](#wallet-v4) | `feb5ff6820e2ff0d9483e7e0d62c817d846789fb4ae580c878866d959dabd5c0` |
| [V5 R1](#wallet-v5) | `20834b7b72b112147e1b2fb457b84e74d1a30f04f737d4f62a668e9552d2b72f` |

**Note:** These hashes can also be found in the explorers.

### Wallet V1

This is the simplest one. It only allows you to send four transactions at a time and doesn't check anything besides your signature and seqno.

Wallet source code:

* [ton/crypto/smartcont/new-wallet.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif)

This version isn't even used in regular apps because it has some major issues:

* No easy way to retrieve the seqno and public key from the contract.
* No `valid_until` check, so you can't be sure that the transaction won't be confirmed too late.

The first issue was fixed in `V1R2` and `V1R3`. The `R` stands for **revision**. Usually, revisions are just small updates that only add get methods; you can find all of those in the changes history of [new-wallet.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif). Hereinafter, we will consider only the latest revisions.

Nevertheless, because each subsequent version inherits the functionality of the previous one, we should still stick to it, as this will help us with later versions.

#### Official code hashes

| Contract version | Hash                                                               |
| ---------------- | ------------------------------------------------------------------ |
| V1 R1            | `a0cfc2c48aee16a271f2cfc0b7382d81756cecb1017d077faaab3bb602f6868c` |
| V1 R2            | `d4902fcc9fad74698fa8e353220a68da0dcf72e32bcb2eb9ee04217c17d3062c` |
| V1 R3            | `587cc789eff1c84f46ec3797e45fc809a14ff5ae24f1e0c7a6a99cc9dc9061ff` |

#### Persistent memory layout

* <b>seqno</b>: 32-bit long sequence number.
* <b>public-key</b>: 256-bit long public key.

#### External message body layout

1. Data:
   * <b>signature</b>: 512-bit long Ed25519 signature.
   * <b>msg-seqno</b>: 32-bit long sequence number.
   * <b>(0-4) mode</b>: up to four 8-bit long integers defining sending mode for each message.
2. Up to 4 references to cells containing messages.

As you can see, the main functionality of the wallet is to provide a safe way to communicate with TON Blockchain from the outside world. The `seqno` mechanism protects against replay attacks, and the `Ed25519 signature` provides authorized access to wallet functionality. The payload data consists of up to 4 references to cells and the corresponding number of modes, which will be directly transferred to the `send_raw_message` method.

<Aside>
  Note that the wallet doesn't provide any validation for internal messages you send through it. It is the programmer's (i.e., the external client's) responsibility to serialize the data according to the internal message layout.
</Aside>

#### Exit codes

| Exit code | Description                                      |
| --------- | ------------------------------------------------ |
| 33        | `seqno` check failed, replay protection occurred |
| 34        | `Ed25519 signature` check failed                 |
| 0         | Standard successful execution exit code.         |

#### Get methods

1. `int seqno()` returns current stored seqno.
2. `int get_public_key()` returns current stored public key.

### Wallet V2

Wallet source code:

* [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-code.fc)

<Aside>
  Originally in FunC; compiled to Fift assembly; later optimized `get methods`. \
  Final Fift source: [ton/crypto/smartcont/new-wallet-v2.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet-v2.fif).
</Aside>

This version introduces the `valid_until` parameter, which is used to set a time limit for a transaction in case you don't want it to be confirmed too late. This version also does not have a get method for the public key, which was added in `V2R2`.

All differences compared to the previous version are a consequence of adding the `valid_until` functionality. A new exit code was added: `35`, marking the failure of the `valid_until` check. Additionally, a new Unix time field has been added to the external message body layout, setting the time limit for the transaction. All get methods remain the same.

#### Official code hashes

| Contract version | Hash                                                               |
| ---------------- | ------------------------------------------------------------------ |
| V2 R1            | `5c9a5e68c108e18721a07c42f9956bfb39ad77ec6d624b60c576ec88eee65329` |
| V2 R2            | `fe9530d3243853083ef2ef0b4c2908c0abf6fa1c31ea243aacaa5bf8c7d753f1` |

#### External message body layout

1. Data:
   * <b>signature</b>: 512-bit long Ed25519 signature.
   * <b>msg-seqno</b>: 32-bit long sequence number.
   * <b>valid-until</b>: 32-bit long Unix time integer.
   * <b>(0-4) mode</b>: up to four 8-bit integers defining the sending mode for each message.
2. Up to 4 references to cells containing messages.

### Wallet V3

This version introduces the `subwallet_id` parameter, which allows you to create multiple wallets using the same public key (so you can have only one seed phrase and multiple wallets). As before, `V3R2` only adds the get method for the public key.

Wallet source code:

* [ton/crypto/smartcont/wallet3-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc)

<Aside>
  Originally in FunC; compiled to Fift assembly; later optimized `get methods`. \
  Final Fift source: [ton/crypto/smartcont/wallet-v3-code.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-v3-code.fif).
</Aside>

Essentially, `subwallet_id` is just a number added to the contract state when it’s deployed. Since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. This version is the most widely used right now. It covers most use cases and remains clean, simple, and mostly the same as previous versions. All get methods remain the same.

#### Official code hashes

| Contract version | Hash                                                               |
| ---------------- | ------------------------------------------------------------------ |
| V3 R1            | `b61041a58a7980b946e8fb9e198e3c904d24799ffa36574ea4251c41a566f581` |
| V3 R2            | `84dafa449f98a6987789ba232358072bc0f76dc4524002a5d0918b9a75d2d599` |

#### Persistent memory layout

* <b>seqno</b>: 32-bit sequence number.
* <b>subwallet\_id</b>: 32-bit subwallet ID.
* <b>public-key</b>: 256-bit public key.

#### External message body layout

1. Data:
   * <b>signature</b>: 512-bit Ed25519 signature.
   * <b>subwallet\_id</b>: 32-bit subwallet ID.
   * <b>msg-seqno</b>: 32-bit sequence number.
   * <b>valid-until</b>: 32-bit Unix time integer.
   * <b>(0-4) mode</b>: up to four 8-bit integers defining the sending mode for each message.
2. Up to 4 references to cells containing messages.

#### Exit codes

| Exit code | Description                                                             |
| --------- | ----------------------------------------------------------------------- |
| 33        | `seqno` check failed; replay protection triggered                       |
| 34        | `subwallet_id` does not match the stored one                            |
| 35        | `valid_until` check failed; transaction confirmation attempted too late |
| 35        | `Ed25519 signature` check failed                                        |
| 0         | Standard successful execution exit code.                                |

<Aside>
  In V3, exit code `35` is intentionally re-used for two checks. This is not a typo. In V4 they are split: `35` = signature check failed; `36` = `valid_until` check failed.
</Aside>

### Wallet V4

This version retains all the functionality of the previous versions but also introduces something very powerful: `plugins`.

Wallet source code:

* [ton-blockchain/wallet-contract](https://github.com/ton-blockchain/wallet-contract)

This feature allows developers to implement complex logic that works in tandem with a user's wallet. For example, a DApp may require a user to pay a small amount of coins every day to use certain features. In this case, the user would need to install the plugin on their wallet by signing a transaction. The plugin would then send coins to the destination address daily when requested by an external message.

#### Official code hashes

| Contract version | Hash                                                               |
| ---------------- | ------------------------------------------------------------------ |
| V4 R1            | `64dd54805522c5be8a9db59cea0105ccf0d08786ca79beb8cb79e880a8d7322d` |
| V4 R2            | `feb5ff6820e2ff0d9483e7e0d62c817d846789fb4ae580c878866d959dabd5c0` |

#### Plugins

Plugins are essentially other smart contracts on TON that developers are free to implement as they wish. In relation to the wallet, they are simply addresses of smart contracts stored in a dictionary in the wallet's persistent memory. These plugins are allowed to request funds and remove themselves from the "allowed list" by sending internal messages to the wallet.

#### Persistent memory layout

* <b>seqno</b>: 32-bit long sequence number.
* <b>subwallet\_id</b>: 32-bit long subwallet\_id.
* <b>public-key</b>: 256-bit long public key.
* <b>plugins</b>: dictionary containing plugins (may be empty)

#### Receiving internal messages

All previous versions of wallets had a straightforward implementation for receiving internal messages. They simply accepted incoming funds from any sender, ignoring the internal message body if present, or in other words, they had an empty `recv_internal` method. However, as mentioned earlier, the fourth version of the wallet introduces two additional available operations. Let's take a look at the internal message body layout:

* <b>opcode?</b>: 32-bit long operation code. This is an optional field. Any message containing less than 32 bits in the message body, an incorrect opcode, or a sender address that isn't registered as a plugin will be considered a simple transfer, similar to previous wallet versions.
* <b>query-id</b>: 64-bit long integer. This field has no effect on the smart contract's behavior; it is used to track chains of messages between contracts.

1. opcode = 0x706c7567, request funds operation code.
   * <b>Toncoin</b>: VARUINT16 amount of requested Toncoin.
   * <b>extra\_currencies</b>: dictionary containing the amount of requested extra currencies (may be empty).
2. opcode = 0x64737472, request removal of plugin-sender from the "allowed list".

#### External message body layout

* <b>signature</b>: 512-bit long Ed25519 signature.
* <b>subwallet\_id</b>: 32-bit long subwallet ID.
* <b>valid-until</b>: 32-bit long Unix time integer.
* <b>msg-seqno</b>: 32-bit long sequence number.
* <b>opcode</b>: 32-bit long operation code.

1. opcode = 0x0, simple send.
   * <b>(0-4) mode</b>: up to four 8-bit integers defining the sending mode for each message.
   * <b>(0-4) messages</b>: up to four references to cells containing messages.
2. opcode = 0x1, deploy and install plugin.
   * <b>workchain</b>: 8-bit long integer.
   * <b>balance</b>: VARUINT16 Toncoin amount of initial balance.
   * <b>state\_init</b>: cell reference containing plugin initial state.
   * <b>body</b>: cell reference containing body.
3. opcode = 0x2/0x3, install plugin/remove plugin.
   * <b>wc\_n\_address</b>: 8-bit long compact workchain ID specific to this layout + 256-bit long plugin address.
   * <b>balance</b>: VARUINT16 Toncoin amount of initial balance.
   * <b>query-id</b>: 64-bit long integer.

As you can see, the fourth version still provides standard functionality through the `0x0` opcode, similar to previous versions. The `0x2` and `0x3` operations allow manipulation of the plugin dictionary. Note that in the case of `0x2`, you need to deploy the plugin with that address yourself. In contrast, the `0x1` opcode also handles the deployment process with the `state_init` field.

#### Exit codes

| Exit code | Description                                                             |
| --------- | ----------------------------------------------------------------------- |
| 33        | `seqno` check failed, replay protection triggered                       |
| 34        | `subwallet_id` does not match the stored one                            |
| 35        | `Ed25519 signature` check failed                                        |
| 36        | `valid_until` check failed, transaction confirmation attempted too late |
| 39        | Plugins dictionary manipulation failed (0x1-0x3 recv\_external opcodes) |
| 80        | Not enough funds for the funds request                                  |
| 0         | Standard successful execution exit code.                                |

#### Get methods

1. `int seqno()` returns current stored seqno.
2. `int get_public_key()` returns current stored public key.
3. `int get_subwallet_id()` returns current subwallet ID.
4. `int is_plugin_installed(int wc, int addr_hash)` checks if plugin with defined workchain\_id and address hash is installed.
5. `tuple get_plugin_list()` returns list of plugins.

### Wallet V5

It is the most modern wallet version at the moment, developed by the Tonkeeper team, aimed at replacing V4 and allowing arbitrary extensions.

<img src="https://mintcdn.com/companyname-a7d5b98e-cex-integration-docs/qeBQPkNJwV-cO0e2/resources/images/wallets/wallet-contract-V5.png?fit=max&auto=format&n=qeBQPkNJwV-cO0e2&q=85&s=b47eba50e18cfb3fc2ca39bd3fffc241" alt="v5" width="5964" height="2614" data-path="resources/images/wallets/wallet-contract-V5.png" />

The V5 wallet standard offers many benefits that improve the experience for both users and merchants. V5 supports gasless transactions, account delegation and recovery, subscription payments using tokens and Toncoin, and low-cost multi-transfers. In addition to retaining the previous functionality (V4), the new contract allows you to send up to 255 messages at a time.

Wallet source code:

* [ton-blockchain/wallet-contract-v5](https://github.com/ton-blockchain/wallet-contract-v5)

TL-B scheme:

* [ton-blockchain/wallet-contract-v5/types.tlb](https://github.com/ton-blockchain/wallet-contract-v5/blob/main/types.tlb)

#### Official code hash

| Contract version | Hash                                                               |
| ---------------- | ------------------------------------------------------------------ |
| V5 R1            | `20834b7b72b112147e1b2fb457b84e74d1a30f04f737d4f62a668e9552d2b72f` |

#### Persistent memory layout

```tlb theme={null}
contract_state$_
    is_signature_allowed:(## 1)
    seqno:#
    wallet_id:(## 32)
    public_key:(## 256)
    extensions_dict:(HashmapE 256 int1) = ContractState;
```

As you can see, the `ContractState`, compared to previous versions, hasn't undergone major changes. The main difference is the new `is_signature_allowed` 1-bit flag, which restricts or allows access through the signature and stored public key. We will describe the importance of this change in later topics.

#### Authentication process

```tlb theme={null}
signed_request$_             // 32 (opcode from outer)
  wallet_id:    #            // 32
  valid_until:  #            // 32
  msg_seqno:    #            // 32
  inner:        InnerRequest //
  signature:    bits512      // 512
= SignedRequest;             // Total: 688 .. 976 + ^Cell

internal_signed#73696e74 signed:SignedRequest = InternalMsgBody;

internal_extension#6578746e
    query_id:(## 64)
    inner:InnerRequest = InternalMsgBody;

external_signed#7369676e signed:SignedRequest = ExternalMsgBody;
```

Before we get to the actual payload of our messages — `InnerRequest` — let's first look at how version 5 differs from previous versions in the authentication process. The `InternalMsgBody` combinator describes two ways to access wallet actions through internal messages. The first method is one we are already familiar with from version 4: authentication as a previously registered extension, the address of which is stored in `extensions_dict`. The second method is authentication through the stored public key and signature, similar to external requests.

At first, this might seem like an unnecessary feature, but it actually enables requests to be processed through external services (smart contracts) that are not part of your wallet's extension infrastructure — a key feature of V5. Gasless transactions rely on this functionality.

Note that simply receiving funds is still an option. Practically, any received internal message that doesn't pass the authentication process will be considered a transfer.

#### Actions

The first thing that we should notice is `InnerRequest`, which we have already seen in the authentication process. In contrast to the previous version, both external and internal messages have access to the same functionality, except for changing the signature mode (i.e., the `is_signature_allowed` flag).

```tlb theme={null}
out_list_empty$_ = OutList 0;
out_list$_ {n:#}
    prev:^(OutList n)
    action:OutAction = OutList (n + 1);

action_send_msg#0ec3c86d mode:(## 8) out_msg:^(MessageRelaxed Any) = OutAction;

// Extended actions in V5:
action_list_basic$_ {n:#} actions:^(OutList n) = ActionList n 0;
action_list_extended$_ {m:#} {n:#} action:ExtendedAction prev:^(ActionList n m) = ActionList n (m+1);

action_add_ext#02 addr:MsgAddressInt = ExtendedAction;
action_delete_ext#03 addr:MsgAddressInt = ExtendedAction;
action_set_signature_auth_allowed#04 allowed:(## 1) = ExtendedAction;

actions$_ out_actions:(Maybe OutList) has_other_actions:(## 1) {m:#} {n:#} other_actions:(ActionList n m) = InnerRequest;
```

We can consider `InnerRequest` as two lists of actions: the first, `OutList`, is an optional chain of cell references, each containing a send message request led by the message mode. The second, `ActionList,` is led by a one-bit flag, `has_other_actions`, which marks the presence of extended actions, starting from the first cell and continuing as a chain of cell references. We are already familiar with the first two extended actions, `action_add_ext` and `action_delete_ext`, followed by the internal address that we want to add or delete from the extensions dictionary. The third, `action_set_signature_auth_allowed`, restricts or allows authentication through the public key, leaving the only way to interact with the wallet through extensions. This functionality might be extremely important in the case of a lost or compromised private key.

#### Exit codes

| Exit code | Description                                                                        |
| --------- | ---------------------------------------------------------------------------------- |
| 132       | Authentication attempt through signature while it's disabled                       |
| 133       | `seqno` check failed, replay protection occurred                                   |
| 134       | `wallet_id` does not correspond to the stored one                                  |
| 135       | `Ed25519 signature` check failed                                                   |
| 136       | `valid-until` check failed                                                         |
| 137       | Enforce that `send_mode` has the +2 bit (ignore errors) set for external messages. |
| 138       | `external_signed` prefix doesn't correspond to the received one                    |
| 139       | Add extension operation was not successful                                         |
| 140       | Remove extension operation was not successful                                      |
| 141       | Unsupported extended message prefix                                                |
| 142       | Tried to disable auth by signature while the extension dictionary is empty         |
| 143       | Attempt to set signature to an already set state                                   |
| 144       | Tried to remove the last extension when signature is disabled                      |
| 145       | Extension has the wrong workchain                                                  |
| 146       | Tried to change signature mode through external message                            |
| 147       | Invalid `c5`, `action_send_msg` verification failed                                |
| 0         | Standard successful execution exit code.                                           |

<Aside type="caution">
  Note that the `142`, `144`, and `146` wallet exit codes are designed to prevent you from losing access to wallet functionality. Nevertheless, you should still remember that the wallet doesn't check whether the stored extension addresses actually exist in TON. You can also deploy a wallet with initial data consisting of an empty extensions dictionary and restricted signature mode. In that case, you will still be able to access the wallet through the public key until you add your first extension. So, be careful with these scenarios.
</Aside>

#### Get methods

1. `int is_signature_allowed()` returns stored `is_signature_allowed` flag.
2. `int seqno()` returns current stored seqno.
3. `int get_wallet_id()` returns current wallet ID.
4. `int get_public_key()` returns current stored public key.
5. `cell get_extensions()` returns extensions dictionary.

#### Preparing for gasless transactions

Starting with v5, the wallet smart contract supports owner-signed internal messages (`internal_signed`), which enables gasless transactions—for example, paying network fees in USDt when transferring USDt. The common scheme looks like this:

<img src="https://mintcdn.com/companyname-a7d5b98e-cex-integration-docs/qeBQPkNJwV-cO0e2/resources/images/wallets/gasless.jpg?fit=max&auto=format&n=qeBQPkNJwV-cO0e2&q=85&s=da05f4d85e9eca63b894f2cdc3b0b487" alt="Gasless transaction flow diagram" width="653" height="262" data-path="resources/images/wallets/gasless.jpg" />

#### Flow

1. When sending USDt, the user signs one message containing two outgoing USDt transfers:
   1. USDt transfer to the recipient's address.
   2. Transfer of a small amount of USDt in favor of the service.
2. This signed message is sent off-chain by HTTPS to the service backend. The service backend sends it to the TON Blockchain, paying Toncoin for network fees.

The beta version of the gasless backend API is available at [tonapi.io/api-v2](https://tonapi.io/api-v2). If you are developing a wallet app and have feedback about these methods, please share it in [@tonapitech](https://t.me/tonapitech) chat.

Wallet source code:

* [ton-blockchain/wallet-contract-v5](https://github.com/ton-blockchain/wallet-contract-v5)

## Special wallets

Sometimes the functionality of basic wallets isn't enough. That's why there are several types of specialized wallet: `high-load`, `lockup` and `restricted`.

Let's have a look at them.

### Highload wallets

When working with many messages in a short period, there is a need for a special wallet called a Highload Wallet. Read [the article](/standard/wallets/highload) for more information.

### Lockup wallet

If you, for some reason, need to lock coins in a wallet for some time without the possibility to withdraw them before that time passes, have a look at the lockup wallet.

It allows you to set the time until which you won't be able to withdraw anything from the wallet. You can also customize it by setting unlock periods so that you will be able to spend some coins during these set periods.

For example: you can create a wallet which will hold 1 million coins with total vesting time of 10 years. Set the cliff duration to one year, so the funds will be locked for the first year after the wallet is created. Then, you can set the unlock period to one month, so `1'000'000 Toncoin / 120 months = ~8333 Toncoin` will unlock every month.

Wallet source code:

* [ton-blockchain/lockup-wallet-contract](https://github.com/ton-blockchain/lockup-wallet-contract)

### Restricted wallet

This wallet's function is to act like a regular wallet, but restrict transfers to only one pre-defined destination address. You can set the destination when you create this wallet and then you'll only be able to transfer funds from it to that address. But note that you can still transfer funds to validation contracts so you can run a validator with this wallet.

Wallet source code:

* [EmelyanenkoK/nomination-contract/restricted-wallet](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet)

## Conclusion

As you see, there are many different versions of wallets in TON. For new deployments, prefer `V5`. Use `V3R2` or `V4R2` only for legacy compatibility or specific constraints. You can also use one of the special wallets if you want additional functionality like periodic unlocking of funds.

## See also

* [Sources of basic wallets](https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont)
* [More technical description of versions](https://github.com/toncenter/tonweb/blob/master/src/contract/wallet/WalletSources.md)
* [Wallet V4 sources and detailed description](https://github.com/ton-blockchain/wallet-contract)
* [Lockup wallet sources and detailed description](https://github.com/ton-blockchain/lockup-wallet-contract)
* [Restricted wallet sources](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet)
* [Gasless transactions on TON](https://medium.com/@buidlingmachine/gasless-transactions-on-ton-75469259eff2)
