Storage and get methods
Summary: In the previous steps, we learned how to use the
Blueprint SDK
and its project structure.
Tact is a high-level programming language for the TON Blockchain, focused on efficiency and simplicity. It is designed to be easy to learn and use while being well-suited for smart contract development. Tact is a statically typed language with a simple syntax and a powerful type system.
For more details, refer to the Tact documentation and Tact By Example.
Let's create and modify our smart contract following standard steps described in the previous Blueprint SDK overview section.
Step 1: edit smart contract code
At the top of the generated contract file: hello_world.tact
, you may see a message definition:
message Add {
queryId: Int as uint64;
amount: Int as uint32;
}
A message is a basic structure for communication between contracts. Tact automatically serializes and deserializes messages into cells. To ensure that opcodes will be the same during message structure changes, it may be added like below:
message(0x7e8764ef) Add {
queryId: Int as uint64;
amount: Int as uint32;
}
Tact will serialize it as follows:
begin_cell()
.store_uint(0x7e8764ef, 32) ;; message opcode
.store_uint(query_id, 64)
.store_uint(amount, 32)
.end_cell()
Using this structure, a message can be sent to the contract from FunC.
Defining the contract
The contract definition in Tact follows an object-oriented programming style:
contract HelloWorld {
...
}
Contract storage
A contract may store its state variables as follows. They may be accessed with Self reference
id: Int as uint32;
counter: Int as uint32;
To ensure that only the contract owner can interact with specific functions, add an owner
field:
id: Int as uint32;
counter: Int as uint32;
owner: Address;
These fields are serialized similarly to structures and stored in the contract's data register.
Initializing the contract
If you compile the contract at this stage, you will encounter the error: Field "owner" is not set
. This is because the contract needs to initialize its fields upon deployment. Define an init()
function to do this:
init(id: Int, owner: Address) {
self.id = id;
self.counter = 0;
self.owner = owner;
}
Handling messages
To accept messages from other contracts, use a receiver function. Receiver functions automatically match the message's opcode and invoke the corresponding function:
receive(msg: Add) {
self.counter += msg.amount;
self.notify("Cashback".asComment());
}