Skip to main content
This article provides overview of V4 wallet standard. This version retains all the functionality of the previous versions but also introduces something very powerful: plugins. Wallet source code: 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 versionHash
V4 R164dd54805522c5be8a9db59cea0105ccf0d08786ca79beb8cb79e880a8d7322d
V4 R2feb5ff6820e2ff0d9483e7e0d62c817d846789fb4ae580c878866d959dabd5c0

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

  • seqno: 32-bit long sequence number.
  • subwallet_id: 32-bit long subwallet_id.
  • public-key: 256-bit long public key.
  • plugins: 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:
  • opcode?: 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.
  • query-id: 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.
    • Toncoin: VARUINT16 amount of requested Toncoin.
    • extra_currencies: 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

  • signature: 512-bit long Ed25519 signature.
  • subwallet_id: 32-bit long subwallet ID.
  • valid-until: 32-bit long Unix time integer.
  • msg-seqno: 32-bit long sequence number.
  • opcode: 32-bit long operation code.
  1. opcode = 0x0, simple send.
    • (0-4) mode: up to four 8-bit integers defining the sending mode for each message.
    • (0-4) messages: up to four references to cells containing messages.
  2. opcode = 0x1, deploy and install plugin.
    • workchain: 8-bit long integer.
    • balance: VARUINT16 Toncoin amount of initial balance.
    • state_init: cell reference containing plugin initial state.
    • body: cell reference containing body.
  3. opcode = 0x2/0x3, install plugin/remove plugin.
    • wc_n_address: 8-bit long compact workchain ID specific to this layout + 256-bit long plugin address.
    • balance: VARUINT16 Toncoin amount of initial balance.
    • query-id: 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 codeDescription
33seqno check failed, replay protection triggered
34subwallet_id does not match the stored one
35Ed25519 signature check failed
36valid_until check failed, transaction confirmation attempted too late
39Plugins dictionary manipulation failed (0x1-0x3 recv_external opcodes)
80Not enough funds for the funds request
0Standard 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.
I