Your first smart contract
Welcome to your journey into TON smart contract development! In this comprehensive tutorial, you’ll learn to build, deploy, and interact with a smart contract from scratch.What you’ll learn
By the end of this tutorial, you’ll have:- ✅ Built a complete smart contract in Tolk
- ✅ Deployed it to TON testnet
- ✅ Interacted with it using TypeScript scripts
- ✅ Mastered the fundamentals of TON development
What is a TON smart contract?
Understanding the basics
A smart contract is a computer program stored on TON Blockchain — distributed database that many computers maintain together. It runs on the TVM (TON Virtual Machine) — the “computer” that runs smart contract code on TON. The contract is made of two parts:- Code (compiled TVM instructions) - the “rules” or “program logic”
- Data (persistent state) - the “memory” that remembers things between interactions
Prerequisites
- Basic programming - Understanding of variables, functions, if/else statements
- Command line basics - Comfortable opening terminal and running commands
- Node.js (v22 or later) — Download here
- Check if installed:
node -v
in terminal - TON wallet - We’ll set this up together in Step 5 (TODO: NOT DONE YET, WAIT FOR FAUCET COMPONENT)
Tutorial overview
This tutorial is organized into 6 clear steps that build upon each other:Step | What You’ll Do | Key Skills |
---|---|---|
Step 1 | Set up Blueprint toolkit | Project structure, development environment |
Step 2 | Learn contract architecture | Storage, messages, getters concept |
Step 3 | Write contract in Tolk | Programming, message handling, data structures |
Step 4 | Compile to bytecode | Build process, TVM compilation |
Step 5 | Deploy to blockchain | Testnet deployment, wallet integration |
Step 6 | Interact with contract | Message sending, get methods, TypeScript integration |
Step 1: Development environment setup
We’ll use Blueprint as our development toolkit for smart contracts. Start a new project with:TON provides plugins that add syntax support for various IDEs and code editors.
Check out the IDE & plugins section for VS Code and JetBrains support.
Step 2: Understanding smart contract architecture
Every smart contract in TON is typically divided into three sections: storage, messages, and getters.- Storage: Defines the contract’s persistent data. For example, our counter variable must keep its value across calls from different users.
- Messages: Define how the contract reacts to incoming messages. On TON, the primary way to interact with contracts is by sending messages. Each processed message produces a transaction — a recorded change on the blockchain (like “Alice sent 5 TON to Bob”).
- Getters: Provide read-only access to contract data without modifying state. For example, we’ll create a getter to return the current value of the counter.
Due to the TON architecture, getters cannot be called from other contracts.
Inter-contract communication is possible only through messages.
Step 3: Writing the smart contract
We’ll build a simple counter contract:- The counter starts from an initial number.
- Users can send an
increase
message to increment it, or areset
message to drop it to zero. - A
getter
function will let anyone query the current counter value.
3.1 Defining contract storage
First, we need a way to store the counter value. Tolk makes this simple with :./contracts/first_contract.tolk
fromCell
and toCell
functions - Tolk automatically converts between your nice structures and the cell format that TON understands.
You may think of cells like containers that hold data on TON:
- Each cell can store up to 1023 bits of data.
- Cells can reference other cells (like links).
- Everything on TON (contracts, messages, storage) is made of cells.
3.2 Implementing message handlers
The main entrypoint for processing messages in a Tolk contract is theonInternalMessage
function. It receives one argument — the incoming message. Among its fields, the most important one for us is body
, which contains the payload sent by a user or another contract.
Tolk structures are also useful for defining message bodies. In our case we’ll define two messages:
IncreaseCounter
— with one fieldincreaseBy
, used to increment the counter.ResetCounter
— used to reset the counter to zero.
0x7e8764ef
and 0x3a752f06
), widely called opcodes, that lets the contract distinguish between them.
./contracts/first_contract.tolk
./contracts/first_contract.tolk
./contracts/first_contract.tolk
📚 Learn More About Tolk
- Tolk Language Guide - Complete language documentation
- View the complete contract on GitHub
3.3 Adding getter functions
Finally, let’s implement a getter so users can read the current counter value:./contracts/first_contract.tolk
3.4 Complete contract code
We now have a complete smart contract with:- Storage: persistent
counter
value - Messages:
IncreaseCounter
andResetCounter
handlers - Getter:
currentCounter
contracts/first_contract.tolk
:
./contracts/first_contract.tolk
📁 Complete Example CodeYou can find the full working code for this tutorial in our GitHub repository. This includes all contract files, scripts, and wrappers ready to use.
Step 4: Compiling your contract
The next step is to build our contract — compile it into bytecode that can be executed by the TVM. With Blueprint, this takes one command:Step 5: Deploying to testnet
Ready to put your contract on-chain? 🚀 To deploy, we first need a wrapper class. Wrappers implement theContract
interface and make it easy to interact with contracts from TypeScript.
Create a file ./wrappers/FirstContract.ts
with the following code:
./wrappers/FirstContract.ts
5.1 Understanding the wrapper class
- We depend on
@ton/core
— a library with base TON types. - The function
createFromConfig
constructs a wrapper using code (compiled bytecode) and data (the initial storage layout). - The contract address is derived deterministically from
code + data
usingcontractAddress
. If two contracts have the same code and init data, the calculation of address will result in the same value. - The method
sendDeploy
sends the first message withstateInit
, which triggers deployment. In practice, this can be an empty message with some TON coins attached.
5.2 Choosing your network
TON has two networks available for deployment:- testnet — developer sandbox.
- mainnet — production blockchain.
5.3 Creating the deployment script
Blueprint makes deployment simple. Create a new script./scripts/deployFirstContract.ts
:
./scripts/deployFirstContract.ts
sendDeploy
method accepts three arguments, but we only pass two because provider.open
automatically supplies the ContractProvider as the first argument.
Run the script with (learn more about Blueprint deployment):
Step 6: Contract interaction
Technically speaking, we’ve already sent messages to the contract - the deploy message in previous steps. Now let’s see how to send messages with body. First of all, we should update our wrapper class with three methods:sendIncrease
, sendReset
, and getCounter
:
./wrappers/FirstContract.ts
Building message bodies
Construction of cells starts with thebeginCell
method (learn more about cell serialization):
beginCell()
- creates a new cell builderstoreUint(value, bits)
- adds an unsigned integer of specified bit lengthendCell()
- finalizes the cell
beginCell().storeUint(0x7e8764ef, 32).storeUint(42, 32).endCell()
- First 32 bits:
0x7e8764ef
(opcode for “increase”) - Next 32 bits:
42
(increase by this amount)
6.1 Sending messages to your contract
Now that our contract is deployed and we have wrapper methods, let’s interact with it by sending messages. Let’s create a script./scripts/sendIncrease.ts
that would increase the counter:
./scripts/sendIncrease.ts
<CONTRACT_ADDRESS>
your actual contract address from Step 5!
Understanding the script breakdown:
- Address parsing:
Address.parse()
converts the string address to a TON Address object - Contract opening:
provider.open()
creates a connection to the deployed contract - Value attachment:
toNano('0.05')
converts 0.05 TON to nanotons (the smallest TON unit) - Message parameters:
increaseBy: 42
tells the contract to increase the counter by 42 - Transaction waiting:
waitForLastTransaction()
waits for the transaction to be processed on-chain
What happens during execution:
- Wallet Connection: Blueprint connects to your wallet using TON Connect protocol
- Transaction Building: The script creates a transaction with the message body containing the opcode
0x7e8764ef
and the value42
- User Approval: Your wallet app shows the transaction details for approval
- Blockchain Processing: Once approved, the transaction is sent to the TON network
- Validator Consensus: Validators need to produce a new block containing your transaction
- Contract Execution: The contract receives the message, processes it in the
onInternalMessage
function, and updates the counter - Confirmation: The transaction hash is returned, and you can view it on the explorer
Composability: Messages can be sent to your contract by other contracts too! This means different contracts can increment your counter, allowing the TON ecosystem to create composable apps and protocols that build on top of each other and interact in unforeseen ways.
./scripts/sendReset.ts
that would reset the counter:
./scripts/sendReset.ts
6.2 Reading contract data with get methods
Get methods are special functions in TON smart contracts that allow you to read data without modifying the contract state or spending gas fees. Unlike message-based interactions, get methods:- Cost nothing: No gas fees required since they don’t modify blockchain state
- Execute instantly: No need to wait for blockchain confirmation
- Read-only: Cannot change contract storage or send messages
provider.get(<GET_METHOD_NAME>)
:
./scripts/getCounter.ts
Understanding the get method execution:
- Direct contract call: The
getCounter()
method directly calls the contract’scurrentCounter
getter - Instant response: The result is returned immediately without blockchain confirmation
- Data parsing: Our wrapper automatically converts the returned stack value to a JavaScript number
Getters are only accessible off-chain (from JavaScript clients, web apps, etc.) through RPC service providers. Contracts cannot call getters on other contracts - inter-contract communication must use messages only.
🎉 Tutorial complete!
Congratulations! You’ve successfully built, deployed, and interacted with your first TON smart contract from scratch. This is a significant achievement in your blockchain development journey!Continue Your Learning Journey
Ready to build more advanced contracts? Here’s your roadmap:Next Steps
- Tolk Language Guide - Master advanced Tolk features and syntax
- Blueprint Documentation - Learn advanced development patterns
- Tutorial Example Repository - Complete working code from this tutorial
- Smart Contract Examples - Study real-world contract implementations
Advanced Topics
- Gas Optimization - Reduce transaction costs
- Security Best Practices - Protect your contracts
Tutorial CreditsThis tutorial was enhanced with insights from the excellent TON Hello World series by Tal Kol and the TON community. For additional examples and alternative approaches, check out the original series.