Skip to content

Commit a728c1b

Browse files
committed
Handling feedback over existing lessons
1 parent 0f0753c commit a728c1b

File tree

17 files changed

+661
-24
lines changed

17 files changed

+661
-24
lines changed

src/routes/(examples)/01-the-deployable-trait/content.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Tact doesn't support classical class inheritance, but contracts can implement *t
44

55
All contracts are deployed by sending them a message. This can be any message, but best practice is to designate the special `Deploy` message for this purpose.
66

7-
This message has a single field, `queryId`, which is provided by the deployer. If the deploy succeeds, the contract will reply with the message `DeployOk` and echo the same `queryId` in the response.
7+
This message has a single field, `queryId`, which is provided by the deployer (normally zero). If the deploy succeeds, the contract will reply with the message `DeployOk` and echo the same `queryId` in the response.
88

9-
If you're using TypeScript to deploy, sending the deploy message should look like:
9+
If you're using Tact's [auto-generated](https://docs.tact-lang.org/tools/typescript#tact-contract-in-typescript) TypeScript classes to deploy, sending the deploy message should look like:
1010

1111
```ts
1212
const msg = { $$type: "Deploy", queryId: 0n };

src/routes/(examples)/02-addresses/content.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22

33
`Address` is another primitive data type. It represents standard addresses on the TON blockchain. Every smart contract on TON is identifiable by its address. Think of this as a unique id.
44

5-
TON is divided into multiple chains called *workchains*. One of the internal fields of the address is the workchain id:
5+
TON is divided into multiple chains called *workchains*. This allows to balance the load more effectively. One of the internal fields of the address is the workchain id:
66

7-
* `0` - The standard workchain, for regular users.
7+
* `0` - The standard workchain, for regular users. Your contracts will be here.
88

9-
* `-1` - The masterchain, usually for validators.
9+
* `-1` - The masterchain, usually for validators. Gas on this chain is significantly more expensive, but you'll probably never use it.
1010

11-
There are multiple ways to [represent](https://ton.org/docs/learn/overviews/addresses) the same address. Notice in the contract that the bouncable and non-bouncable representations of the same address actually generate the exact same value. It doesn't matter which representation you use.
11+
There are multiple ways on TON to [represent](https://docs.ton.org/learn/overviews/addresses#bounceable-vs-non-bounceable-addresses) the same address. Notice in the contract that the bouncable and non-bouncable representations of the same address actually generate the exact same value. Inside the contract, it doesn't matter which representation you use.
12+
13+
## State costs
14+
15+
Most addresses take 264-bit to store (8-bit for the workchain id and 256-bit for the account id). This means that storing 1000 addresses [costs](https://ton.org/docs/develop/smart-contracts/fees#how-to-calculate-fees) about 0.189 TON per year.

src/routes/(examples)/02-bools/content.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ This primitive data type can hold the values `true` or `false`.
44

55
`Bool` is convenient for boolean and logical operations. It is also useful for storing flags.
66

7-
Persisting bools to state is very space-efficient, they only take 1 bit.
7+
The only supported operations with booleans are `&&` `||` `!` - if you try to add them, for example, the code will not compile.
8+
9+
## State costs
10+
11+
Persisting bools to state is very space-efficient, they only take 1-bit. Storing 1000 bools in state [costs](https://ton.org/docs/develop/smart-contracts/fees#how-to-calculate-fees) about 0.00072 TON per year.

src/routes/(examples)/02-constants/content.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ Constant initializations must be relatively simple and only rely on values known
66

77
You can read constants both in *receivers* and in *getters*.
88

9-
Unlike contract variables, constants don't consume space in persistent state. Their values are stored directly in the code cell.
9+
Unlike contract variables, constants don't consume space in persistent state. Their values are stored directly in the code cell.
10+
11+
There isn't much difference between constants defined outside of a contract and inside the contract. Those defined outside can be used by other contracts in your project.
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
# Integer Operations
22

3-
Since all runtime calculations with integers are done at 257-bit, overflows are quite rare.
3+
Since all runtime calculations with integers are done at 257-bit, overflows are quite rare. An overflow can happen if the result of a math operation is too big to fit. For example, multiplying 2^256 by 2^256 will not fit within 257-bit.
44

5-
Nevertheless, if any math operation overflows, an exception will be thrown and the transaction will revert. You can say that Tact's math is safe by default.
5+
Nevertheless, if any math operation overflows, an exception will be thrown and the transaction will fail. You can say that Tact's math is safe by default.
66

7-
There's no problem with mixing variables of different state sizes in the same calculation. In runtime, they are all the same type - always 257-bit signed. This is the largest supported integer type, so they all fit.
7+
There's no problem with mixing variables of different state sizes in the same calculation. In runtime, they are all the same type - always 257-bit signed. This is the largest supported integer type, so they all fit.
8+
9+
## Decimal point with integers
10+
11+
Arithmetics with dollars, for example, requires 2 decimal places. How can we represent the number `1.25` if we can only work with integers? The answer is to work with *cents*. So `1.25` becomes `125`. We just remember that the two lowest digits are coming after the decimal point.
12+
13+
In the same way, working with TON coins has 9 decimal places instead of 2. So the amount 1.25 TON which can be coded in Tact as `ton("1.25")` is actually the number `1250000000` - we call these *nano-tons* instead of cents.

src/routes/(examples)/02-integer-ops/contract.tact

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ contract Integers with Deployable {
1515
i = self.i1 * 3 + (self.i2 - i); // basic math expressions
1616
dump(i);
1717

18-
i = self.i1 % 10; // modulo (remainder after division)
18+
i = self.i1 % 10; // modulo (remainder after division), 3001 % 10 = 1
1919
dump(i);
2020

21-
i = self.i1 / 1000; // integer division (truncation toward zero)
21+
i = self.i1 / 1000; // integer division (truncation toward zero), 3001 / 1000 = 3
2222
dump(i);
2323

2424
i = self.i1 >> 3; // shift right (multiply by 2^n)

src/routes/(examples)/02-integers/content.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22

33
Tact supports a number of primitive data types that are tailored for smart contract use.
44

5-
`Int` is the primary number type. Math in smart contracts is always done with integers and no floating points.
5+
`Int` is the primary number type. Math in smart contracts is always done with integers and never with floating points since floats are [unpredictable](https://learn.microsoft.com/en-us/cpp/build/why-floating-point-numbers-may-lose-precision).
66

7-
The runtime type `Int` is *always* 257-bit signed, so all runtime calculations are done at 257-bit. This should be enough for everything as it's large enough to hold the number of atoms in the universe.
7+
The runtime type `Int` is *always* 257-bit signed, so all runtime calculations are done at 257-bit. This should be large enough for pretty much anything you need as it's large enough to hold the number of atoms in the universe.
8+
9+
Persistent state variables can be initialized inline or inside `init()`. If you forget to initialize a state variable, the code will not compile.
10+
11+
## State costs
812

913
When encoding `Int` to persistent state, we will usually use smaller representations than 257-bit to reduce storage cost. The persistent state size is specified in every declaration of a state variable after the `as` keyword.
1014

11-
Persistent state variables can be initialized inline or inside `init()`. If you forget to initialize a state variable, the code will not compile.
15+
Storing 1000 257-bit integers in state [costs](https://ton.org/docs/develop/smart-contracts/fees#how-to-calculate-fees) about 0.184 TON per year. Storing 1000 32-bit integers only costs 0.023 TON per year by comparison.

src/routes/(examples)/02-integers/contract.tact

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ contract Integers with Deployable {
2020
i14: Int as int8 = 0; // range -128 to 127 (takes 8 bit = 1 byte)
2121

2222
init() {
23-
self.i2 = 0x83dfd552e63729b472fcbcc8c45ebcc6691702558b68ec7527e1ba403a0f31a8;
24-
self.i4 = 1507998500293440234999;
23+
self.i2 = 0x83dfd552e63729b472fcbcc8c45ebcc6691702558b68ec7527e1ba403a0f31a8; // we can define numbers in hex (base 16)
24+
self.i4 = 1507998500293440234999; // we can define numbers in decimal (base 10)
2525
self.i5 = pow(10, 9); // this is 10^9 = 1,000,000,000
2626
self.i6 = ton("1.23"); // easy to read coin balances (coins type is nano-tons, like cents, just with 9 decimals)
2727
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# Strings
22

3-
Tact has basic support for strings. Strings support unicode and don't have any special escape characters like `\n`. The use of strings in smart contracts should be quite limited.
3+
Tact has basic support for strings. Strings support unicode and don't have any special escape characters like `\n`.
4+
5+
The use of strings in smart contracts should be quite limited. Smart contracts are very exact programs for managing money, they're not intended for interactive CLI.
46

57
Strings are immutable. Once a sequence of characters is created, this sequence cannot be modified.
68

7-
If you need to concatenate strings in run-time, you can use a `StringBuilder`. This object handles gas efficiently.
9+
If you need to concatenate strings in run-time, you can use a `StringBuilder`. This object handles gas efficiently and supports `append()` of various types to the string.

src/routes/(examples)/03-receivers/content.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ In TON, users interact with contracts by sending them messages. Different contra
44

55
Since users actually use wallet contracts, messages from users are actually messages coming from just another contract.
66

7-
Sending a message to a contract costs gas and is processed in the course of a transaction. The transaction executes when validators add the transaction to a new block. This can take a few seconds. Messages are also able to change the contract persistent state.
7+
Sending a message to a contract costs gas and is processed in the course of a transaction. The transaction executes when validators add the transaction to a new block. This can take a few seconds. Messages are also able to change the contract's persistent state.
88

99
## Receivers
1010

1111
When designing your contract, make a list of every operation that your contract supports, then, define a message for each operation, and finally, implement a handler for each message containing the logic of what to do when it arrives.
1212

13-
Contract methods named `receive()` are the handlers that process each incoming message type. Tact will automatically route every incoming message to the correct receiver listening for it according to its type.
13+
Contract methods named `receive()` are the handlers that process each incoming message type. Tact will automatically route every incoming message to the correct receiver listening for it according to its type. A message is only handled by one receiver.
1414

1515
Messages are defined using the `message` keyword. They can carry input arguments. Notice that for integers, you must define the encoding size, just like in state variables. When somebody sends the message, they serialize it over the wire.

0 commit comments

Comments
 (0)