You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -136,8 +137,8 @@ Navigate to [Tonviewer](https://testnet.tonviewer.com/) and paste your address i
136
137
## Sending NFTs
137
138
138
139
[Non-fungible tokens](/v3/guidelines/dapps/asset-processing/nft-processing/nfts/) (NFTs) are assets like a piece of art, digital content, or video that have been tokenized via a blockchain. In TON, NFTs are represented via a collection of smart contracts:
139
-
-**NFT Collection**: Stores information about the NFT collection.
140
-
-**NFT Item**: Stores information about the NFT item that the user owns.
140
+
-**NFT Collection**: stores information about the NFT collection.
141
+
-**NFT Item**: stores information about the NFT item that the user owns.
141
142
142
143
To send an NFT, we should first acquire one. The easiest way to do that is to create and deploy your own NFT through [TON Tools](https://ton-collection-edit.vercel.app/deploy-nft-single). Note that the `owner` addresses of your NFT must be your wallet address to be able to perform operations on it.
@@ -12,7 +12,7 @@ For more details, refer to the [Tact documentation](https://docs.tact-lang.org/#
12
12
:::
13
13
14
14
15
-
Smart contracts often need to store data, like counters or ownership information, and provide a way to read or update it through messages. In this section, you’ll learn how to define and initialize contract storage, receive and handle incoming messages, restrict access using traits, and create getter functions to read contract states outside the blockchain.
15
+
Smart contracts often need to store data, like counters or ownership information, and provide a way to read or update it through messages. In this section, you’ll learn how to define and initialize contract storage, receive and handle incoming messages, and create getter functions to read contract states outside the blockchain.
16
16
17
17
Let's create and modify our smart contract following the standard steps described in the previous [Blueprint overview](/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-blueprint-sdk-overview/) section.
18
18
@@ -63,7 +63,6 @@ message(0x7e8764ef) Add {
63
63
64
64
65
65
66
-
67
66
#### Defining the contract
68
67
69
68
The [contract](https://docs.tact-lang.org/book/contracts/) definition in Tact follows an object-oriented programming style:
@@ -84,12 +83,14 @@ counter: Int as uint32;
84
83
```
85
84
These fields are serialized similarly to structures and stored in the contract's data register.
86
85
86
+
Use `self.id` and `self.counter` to access them within contract functions.
87
+
87
88
#### Initializing the contract
88
89
89
-
Define an [`init()`](https://docs.tact-lang.org/book/contracts/#init-function/) function to do this:
90
+
Define an [`init()`](https://docs.tact-lang.org/book/contracts/#init-function/) function to set initial values:
90
91
91
92
```tact title="/contracts/hello_world.tact"
92
-
init(id: Int, owner: Address) {
93
+
init(id: Int) {
93
94
self.id = id;
94
95
self.counter = 0;
95
96
}
@@ -114,32 +115,6 @@ receive() {
114
115
}
115
116
```
116
117
117
-
#### Restricting access
118
-
119
-
Tact also provides handy ways to share the same logic through [traits](https://docs.tact-lang.org/book/types/#traits) reusable code blocks similar to abstract classes in other languages. Tact doesn’t use classical inheritance, but traits let you define shared logic without duplicating code. They look like contracts but can’t store persistent state.
120
-
For example, you can use the `Ownable` trait, which provides built-in ownership checks, to ensure that only the contract owner can send messages.
121
-
122
-
```tact title="/contracts/hello_world.tact"
123
-
// Import library to use trait
124
-
import "@stdlib/ownable";
125
-
126
-
// Ownable trait introduced here
127
-
contract HelloWorld with Ownable {
128
-
129
-
...
130
-
131
-
receive(msg: Add) {
132
-
self.requireOwner();
133
-
self.counter += msg.amount;
134
-
self.notify("Cashback".asComment());
135
-
}
136
-
}
137
-
```
138
-
139
-
:::info
140
-
[Identity validation](https://docs.tact-lang.org/book/security-best-practices/#identity-validation) plays a key role in secure contract interactions. You can read more about identity validation and its importance in the linked documentation.
141
-
:::
142
-
143
118
#### Getter functions
144
119
145
120
Tact supports [getter functions](https://docs.tact-lang.org/book/functions/#getter-functions) for retrieving contract state off-chain:
@@ -154,32 +129,26 @@ get fun counter(): Int {
154
129
}
155
130
```
156
131
157
-
Note, that the `owner` getter is automatically defined via the `Ownable` trait.
158
-
159
132
#### Complete contract
160
133
161
134
```tact title="/contracts/hello_world.tact"
162
-
import "@stdlib/ownable";
163
-
164
135
// message with opcode
165
136
message(0x7e8764ef) Add {
166
137
queryId: Int as uint64;
167
138
amount: Int as uint32;
168
139
}
169
140
170
-
// Contract defenition. `Ownable` is a trait to share functionality.
171
-
contract HelloWorld with Ownable {
141
+
// Contract defenition
142
+
contract HelloWorld {
172
143
173
144
// storage variables
174
145
id: Int as uint32;
175
146
counter: Int as uint32;
176
-
owner: Address;
177
147
178
148
// init function.
179
-
init(id: Int, owner: Address) {
149
+
init(id: Int) {
180
150
self.id = id;
181
151
self.counter = 0;
182
-
self.owner = owner;
183
152
}
184
153
185
154
// default(null) recieve for deploy
@@ -189,8 +158,6 @@ contract HelloWorld with Ownable {
189
158
190
159
// function to recive messages from other contracts
191
160
receive(msg: Add) {
192
-
// function from `Ownable` trait to assert, that only owner may call this
193
-
self.requireOwner();
194
161
self.counter += msg.amount;
195
162
196
163
// Notify the caller that the receiver was executed and forward remaining value back
@@ -246,10 +213,12 @@ This code exports everything inside the `tact_HelloWorld.ts` file in the build f
246
213
<details>
247
214
<summary><b>Updating tests</b></summary>
248
215
249
-
Now let's ensure that our smart contract code fails when we try to send `add` message from non-owner:
250
-
- Create `HelloWorld` with some owner.
251
-
- Create another smart contract that will have different address - `nonOwner`.
252
-
- Try to send an internal message to `HelloWorld` and enusre that it fails with expected `exitCode` and counter field remains the same.
216
+
Now let's ensure that our smart contract correctly updates the counter:
217
+
- Deploy the `HelloWorld` contract with an initial ID.
218
+
- Check that the initial counter value is `0`.
219
+
- Send an `Add` message to increment the counter.
220
+
- Verify that the counter value increases by the expected amount.
221
+
253
222
254
223
Implementation of test should look like this:
255
224
@@ -262,130 +231,61 @@ This code exports everything inside the `tact_HelloWorld.ts` file in the build f
0 commit comments