TON DocsTON Docs
OnboardingNodesApplicationsAPIsContractsSmart contractsTolkTolk languageTVMTON Virtual MachineFoundationsBlockchain foundations

WalletTg code and storage

Every deployed wallet stores an immutable trampoline code. The trampoline code hash is 9149AE51C1E4689710CEBF7830297B16ACFBADB363A920A537893E7FFEECA768. It is the root-cell hash of WalletTrampoline.boc.

Trampoline

The trampoline loads and executes the shared implementation from configuration parameter -123. The -123 PUSHINT CONFIGOPTPARAM instructions fetch the code cell, the trampoline turns it into a continuation and starts executing the code that processes incoming signed internal or external requests, and get-method calls.

Excerpt from the WalletTrampoline.fif
SETCP0
DUP IFNOT:<{        // method_id 0 = internal
  s1 PUSH           // copy body_slice
  SBITS             // n_bits of body_slice
  9 PUSHPOW2 LESS   // n_bits < 512, -1 or 0
  0 THROWIF         // n_bits < 512: exit 0
}>
-123 PUSHINT        // ... idx-in-config
CONFIGOPTPARAM      // ... cell | null, but we suppose it exists
CTOS BLESS          // ... continuation
DUP c3 POPCTR       // ... continuation
JMPX                // ... jump to WalletTg code to process
//                         an internal or external signed request
//                         or a getter call

Validators can change the active shared implementation by voting. Every mainnet WalletTg account uses this implementation — a wallet owner cannot pin a version, change the code, or opt out of code updates.

Initial state

TON derives the address from the hash of the original StateInit, which contains the trampoline code and initial Storage data. The fields serialize in this order:

Current storage

FieldWidthInitial valueCurrent meaning
Revision prefix8 bits0x00 (Rev00_Initial)Storage schema revision
seqno32 bits0Expected sequence number for the next signed request
subwalletId32 bitsChosen by the clientWallet ID checked in each request header
publicKey256 bitsAnchor public keyCurrent request-signing key

The source defines mainnet default subwalletId 0x7FFF7F11 and testnet default 0x7FFF7FFD. The selected ID is part of StateInit and must match each request header.

publicKey starts with the anchor key. Rotation replaces it with the new signing key; the anchor is not stored separately. Rotation changes storage only, so the original StateInit, address, and trampoline code hash stay the same. Rebuilding StateInit with the new key derives a different address.

Getters

GetterResultBehavior
revision()uint8Reads the stored revision prefix; does not call Storage.load().
seqno()uint32Calls Storage.load() and returns seqno.
get_subwallet_id()uint32Calls Storage.load() and returns subwalletId.
get_public_key()uint256Calls Storage.load() and returns publicKey.

After rotation, the get_public_key() getter returns the active signing key, not the anchor key.

Storage and migration

Storage.load() runs runMigrationAndUpdateC4() when the stored prefix differs from LAST_REVISION. A transaction persists the migration when it commits account data

See request failure behavior for external-send commit timing.

Revision 0 stores prefix 0x00, has no old layouts in UnionOfOldStorages, and uses a no-op runMigrationAndUpdateC4(). Later revisions must preserve prior layouts and define migrations to the current schema. The migration rules also require existing messages and getters to remain compatible as new ones are added.

The call to a revision() get-method can report an older storage revision while the account already executes newer shared code. It does not identify the active implementation.

Source files

On this page