struct, serialized into persistent blockchain data. Tolk does not enforce any specific storage layout.
Common pattern
Addload and store methods to struct Storage:
fun Storage.f(self)defines an instance method.T.fromCell()deserializes a cell intoT, andobj.toCell()packs it back into a cell.- The
lazyoperator does the parsing on demand. contract.getData()fetches persistent data.
Default values
In TON, a contract’s address depends on its initial storage when it is created on-chain. Assign default values to fields that must be defined at deployment:Multiple contracts
When developing multiple contracts in one project simultaneously, for example, a jetton minter and a jetton wallet, each contract has its own storage shape described by astruct.
Name these structures descriptively, for example, MinterStorage and WalletStorage. Place these structures in a single file storage.tolk along with their methods.
Contracts may deploy other contracts, requiring initial storage to be provided at deployment. For example, a minter deploys a wallet, so WalletStorage becomes accessible through an import:
Changing storage shape
Contracts may start with a storage layout and extend it after deployment. For example:- At deployment, storage contains only
a,b,c. - Followed by a message supplying
dande, storage becomesa,b,c,d,e.
int8? or cell? serialize with an explicit null marker 0 bit. In this case, fields are absent entirely, and no extra bits appear in serialization.
This pattern is common in NFT contracts. Initially, an NFT contains only itemIndex and collectionAddress. After initialization, ownerAddress and content are added to the storage.
Since arbitrary imperative code is allowed, the approach is:
- Define two structures: initialized and uninitialized storages.
- Start loading using
contract.getData(). - Determine whether the storage is initialized based on its bits and refs counts.
- Parse into the corresponding struct.
onInternalMessage: