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.
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 callValidators 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
| Field | Width | Initial value | Current meaning |
|---|---|---|---|
| Revision prefix | 8 bits | 0x00 (Rev00_Initial) | Storage schema revision |
seqno | 32 bits | 0 | Expected sequence number for the next signed request |
subwalletId | 32 bits | Chosen by the client | Wallet ID checked in each request header |
publicKey | 256 bits | Anchor public key | Current 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
| Getter | Result | Behavior |
|---|---|---|
revision() | uint8 | Reads the stored revision prefix; does not call Storage.load(). |
seqno() | uint32 | Calls Storage.load() and returns seqno. |
get_subwallet_id() | uint32 | Calls Storage.load() and returns subwalletId. |
get_public_key() | uint256 | Calls 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.