onInternalMessage
Contracts primarily handle internal messages. Users interact with contracts through their wallets, which send internal messages to the contract. The entrypoint is declared as follows:
- For each incoming message, declare a
structwith a unique 32-bit prefix, opcode. - Declare a union type that represents all supported messages.
- Parse this union from
in.bodyandmatchover structures.
Example breakdown
structdeclares business data, including messages and storage.(0x12345678)defines a message opcode, 32-bit. Unique prefixes are used to route binary data inin.body.AllowedMessageis a type alias for a union type.in: InMessageprovides access to message properties such asin.bodyandin.senderAddress.T.fromSliceparses binary data intoT. When combined withlazy, parsing is performed on demand.matchroutes a union type. Within each branch, the type ofmsgis narrowed, smart cast.throw 0xFFFFis a standard reaction to an unrecognized message. Contracts typically ignore empty messages, which represent balance top-ups with an empty body. For this reason,throwis guarded byiforassert.
onInternalMessage.
Define and modify contract storage
Contract storage is defined as a regular structure. Storage types commonly defineload and save methods to access persistent contract data:
match cases, invoke those methods:
match statement and reused across branches.
Legacy onInternalMessage
In FunC, a handler is declared as:
InMessage type. It simplifies message handling and reduces gas consumption. Migrating from the legacy code is:
myBalance->contract.getOriginalBalance(), contract state, not a message propertymsgValue->in.valueCoinsmsgFull-> usein.senderAddressetc., without manual parsingmsgBody->in.body
onBouncedMessage
onBouncedMessage is a special entrypoint for handling bounced messages.
InMessageBounced is similar to InMessage. The difference is that in.bouncedBody has a different layout, depending on how the original message is sent.
BounceMode in createMessage
When sending a message using createMessage, the bounce behavior must be specified:
BounceMode is an enum with the following options:
BounceMode.NoBounce.BounceMode.Only256BitsOfBody—in.bouncedBodycontains0xFFFFFFFFfollowed by the first 256 bits; lowest gas cost, often sufficient.BounceMode.RichBounce— provides access to the entireoriginalBody;gasUsed,exitCode, and other failure-related properties are also available; highest gas cost.BounceMode.RichBounceOnlyRootCell— similar toRichBounce, butoriginalBodycontains only the root cell.
Handle in.bouncedBody
The structure of in.bouncedBody depends on the BounceMode.
When all bounceable messages are sent using Only256BitsOfBody:
RichBounce is used:
TransferMessage, is returned either as in.bouncedBody with a 256-bit limit or as rich.originalBody, which contains the full slice. To handle this consistently:
- define a union type that includes all message types that may be bounced;
- handle it using
lazyinonBouncedMessage.
onExternalMessage
In addition to internal messages, a contract can handle external messages originating off-chain.
For example, wallet contracts process external messages and perform signature validation using a public key.
acceptExternalMessage() to increase the available gas. The commitContractDataAndActions() function can also be used. Both functions are part of the standard library and are documented inline.
Additional reserved entrypoints
Tolk defines several reserved entrypoints:fun onTickTockis invoked on tick-tock transactions;fun onSplitPrepareandfun onSplitInstallare reserved for split and install transactions; currently not used by the blockchain;fun mainis used for simple snippets and demos.
method_id is 0.