diff --git a/pages/book/_meta.js b/pages/book/_meta.js
index aa405dae..eaf2f54a 100644
--- a/pages/book/_meta.js
+++ b/pages/book/_meta.js
@@ -7,10 +7,11 @@ export default {
type: 'separator',
},
types: 'Type system overview',
+ integers: 'Integers',
functions: 'Functions',
statements: 'Statements',
constants: 'Constants',
- 'defining-types': 'Defining composite types',
+ 'composite-types': 'Composite types',
receive: 'Receive Messages',
bounced: 'Bounced Messages',
external: 'External Messages',
diff --git a/pages/book/defining-types.mdx b/pages/book/composite-types.mdx
similarity index 99%
rename from pages/book/defining-types.mdx
rename to pages/book/composite-types.mdx
index 0c02631d..37ed71f8 100644
--- a/pages/book/defining-types.mdx
+++ b/pages/book/composite-types.mdx
@@ -1,4 +1,4 @@
-# Defining composite types
+# Composite types
import { Callout } from 'nextra/components'
diff --git a/pages/book/integers.mdx b/pages/book/integers.mdx
new file mode 100644
index 00000000..62594b62
--- /dev/null
+++ b/pages/book/integers.mdx
@@ -0,0 +1,139 @@
+# Integers
+
+import { Callout } from 'nextra/components'
+
+Arithmetic in smart contracts on TON is always done with integers and never with floating-point numbers since the floats are [unpredictable](https://learn.microsoft.com/en-us/cpp/build/why-floating-point-numbers-may-lose-precision). Therefore, the big accent goes on integers and their handling.
+
+The only primitive number type in Tact is `Int{:tact}`, for $257$-bit signed integers.\
+It's capable of storing integers between $-2^{256}$ and $2^{256} - 1.$
+
+## Notation
+
+Tact supports various ways of writing primitive values of `Int{:tact}` (integer literals).
+
+Most of the notations allow adding underscores (`_`) in-between digits, except for:
+* Representations in strings, as seen in [nano-tons](#nano-tons) case.
+* Decimal numbers written with a leading zero $0.$ Their use is generally discouraged, see [below](#decimal).
+
+Additionally, several underscores in a row as in $4\_\_2$, or trailing underscores as in $42\_$ are **not** allowed.
+
+### Decimal
+
+Most common and most used way of representing numbers, using the [decimal numeral system](https://en.wikipedia.org/wiki/Decimal): $123456789.$\
+You can use underscores (`_`) to improve readability: $123\_456\_789$ is equal to $123456789.$
+
+
+ Alternatively, you can prefix the number with one $0$, which prohibits use of underscores and only allows decimal digits: $0123 = 123.$
+ Note, that using this notation with leading zero is **strongly discouraged** due to possible confusion with octal integer literals in TypeScript, which is often used alongside Tact to develop and test contracts.
+
+
+### Hexadecimal
+
+Represent numbers using [hexadecimal numeral system](https://en.wikipedia.org/wiki/Hexadecimal), denoted by the $\mathrm{0x}$ prefix: $\mathrm{0xFFFFFFFFF}.$\
+Use underscores (`_`) to improve readability: $\mathrm{0xFFF\_FFF\_FFF}$ is equal to $\mathrm{0xFFFFFFFFF}.$
+
+### Octal
+
+Represent numbers using [octal numeral system](https://en.wikipedia.org/wiki/Octal), denoted by the $\mathrm{0o}$ prefix: $\mathrm{0o777777777.}$\
+Use underscores (`_`) to improve readability: $\mathrm{0o777\_777\_777}$ is equal to $\mathrm{0o777777777}.$
+
+### Binary
+
+Represent numbers using [binary numeral system](https://en.wikipedia.org/wiki/Binary_number), denoted by the $\mathrm{0b}$ prefix: $\mathrm{0b111111111.}$\
+Use underscores (`_`) to improve readability: $\mathrm{0b111\_111\_111}$ is equal to $\mathrm{0b111111111}.$
+
+### Nano-tons
+
+For example, arithmetic with dollars requires two decimal places after the dot — those are used for the cents value. But how would we represent the number \$$1.25$ if we're only able to work with integers? The solution is to work with _cents_ directly. This way, \$$1.25$ becomes $125$ cents. We simply memorize that the two rightmost digits represent the numbers after the decimal point.
+
+Similarly, working with Toncoins requires nine decimal places instead of the two. Therefore, the amount of $1.25$ TON, which can be represented in Tact as [`ton("1.25"){:tact}`](/language/ref/common#ton), is actually the number $1250000000$. We refer to such numbers as _nano-tons_ (or _nanoToncoins_) rather than _cents_.
+
+## Serialization
+
+When encoding `Int{:tact}` values to persistent state (fields of [Contracts](/book/types#contracts) and [Traits](/book/types#traits)), it's usually better to use smaller representations than $257$-bits to reduce storage costs. Usage of such representations is also called "serialization" due to them representing the native [TL-B](https://docs.ton.org/develop/data-formats/tl-b-languagehttps://docs.ton.org/develop/data-formats/tl-b-language) types which TON Blockchain operates on.
+
+The persistent state size is specified in every declaration of a state variable after the `as{:tact}` keyword:
+
+```tact
+contract SerializationExample {
+ // contract persistent state variables
+ oneByte: Int as int8 = 0; // ranges from -128 to 127 (takes 8 bit = 1 byte)
+ twoBytes: Int as int16; // ranges from -32,768 to 32,767 (takes 16 bit = 2 bytes)
+
+ init() {
+ // needs to be initialized in the init() because it doesn't have the default value
+ self.twoBytes = 55*55;
+ }
+}
+```
+
+Integer serialization is also available for the fields of [Structs](/book/composite-types#structs) and [Messages](/book/composite-types#structs), as well as in key/value types of [maps](/book/types#maps):
+
+```tact
+struct StSerialization {
+ martin: Int as int8;
+}
+
+message MsgSerialization {
+ seamus: Int as int8;
+ mcFly: map;
+}
+```
+
+Motivation is very simple:
+* Storing $1000$ $257$-bit integers in state [costs](https://docs.ton.org/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.
+
+### Serialization types
+
+Name | Inclusive range | Space taken
+:--------------- | :-------------------------: | :------------------------:
+`uint8{:tact}` | $0$ to $2^{8} - 1$ | 8 bit = 1 byte
+`uint16{:tact}` | $0$ to $2^{16} - 1$ | 16 bit = 2 bytes
+`uint32{:tact}` | $0$ to $2^{32} - 1$ | 32 bit = 4 bytes
+`uint64{:tact}` | $0$ to $2^{64} - 1$ | 64 bit = 8 bytes
+`uint128{:tact}` | $0$ to $2^{128} - 1$ | 128 bit = 16 bytes
+`uint256{:tact}` | $0$ to $2^{256} - 1$ | 256 bit = 32 bytes
+`int8{:tact}` | $-2^{7}$ to $2^{7} - 1$ | 8 bit = 1 byte
+`int16{:tact}` | $-2^{15}$ to $2^{15} - 1$ | 16 bit = 2 bytes
+`int32{:tact}` | $-2^{31}$ to $2^{31} - 1$ | 32 bit = 4 bytes
+`int64{:tact}` | $-2^{63}$ to $2^{63} - 1$ | 64 bit = 8 bytes
+`int128{:tact}` | $-2^{127}$ to $2^{127} - 1$ | 128 bit = 16 bytes
+`int256{:tact}` | $-2^{255}$ to $2^{255} - 1$ | 256 bit = 32 bytes
+`int257{:tact}` | $-2^{256}$ to $2^{256} - 1$ | 257 bit = 32 bytes + 1 bit
+`coins{:tact}` | $0$ to $2^{120} - 1$ | 120 bit = 15 bytes
+
+
+ Read more on serialization here: [Compatibility with FunC](/book/func##convert-serialization)
+
+
+## Operations
+
+All runtime calculations with numbers are done at 257-bits, so [overflows](https://en.wikipedia.org/wiki/Integer_overflow) are quite rare. Nevertheless, if any math operation overflows, an exception will be thrown, and the transaction will fail. You could say that Tact's math is safe by default.
+
+Note, that there is no problem with mixing variables of [different state sizes](#serialization) in the same calculation. At runtime they are all the same type no matter what — $257$-bit signed, so overflows won't happen then.
+
+However, this can still lead to **errors** in the [compute phase](https://docs.ton.org/learn/tvm-instructions/tvm-overview#compute-phase) of the transaction. Consider the following example:
+
+```tact
+import "@stdlib/deploy";
+
+contract ComputeErrorsOhNo with Deployable {
+ oneByte: Int as uint8; // persistent state variable, max value is 255
+
+ init() {
+ self.oneByte = 255; // initial value is 255, everything fits
+ }
+
+ receive("lets break it") {
+ let tmp: Int = self.oneByte * 256; // no runtime overflow
+ self.oneByte = tmp; // whoops, tmp value is out of the expected range of oneByte
+ }
+}
+```
+
+Here, `oneByte` is serialized as a [`uint8`](#serialization-types), which occupies only one byte and ranges from $0$ to $2^{8} - 1$, which is $255$. And when used in runtime calculations no overflow happens and everything is calculated as a $257$-bit signed integers. But the very moment we decide to store the value of `tmp` back into `oneByte` we get an error with the [exit code](https://docs.ton.org/learn/tvm-instructions/tvm-exit-codes) 5, which states the following: `Integer out of the expected range`.
+
+
+ Therefore, be **very** careful with numbers and always double-check calculations when using serialization.
+
\ No newline at end of file
diff --git a/pages/book/types.mdx b/pages/book/types.mdx
index bfa025af..9643e747 100644
--- a/pages/book/types.mdx
+++ b/pages/book/types.mdx
@@ -9,20 +9,58 @@ Every variable, item, and value in Tact programs has a type. They can be:
* Composite types, such as [Structs and Messages](#structs-and-messages)
* or [Contracts](#contracts) and [Traits](#traits)
-Also, many of those types [can be made nullable](/book/defining-types#optionals).
+Also, many of those types [can be made nullable](/book/composite-types#optionals).
## Primitive types
-* Int — all numbers in Tact are 257-bit signed integers, but [smaller representations](/book/integers#serialization) can be used to reduce storage costs.
-* Bool — classical boolean with `true` and `false` values.
-* Address — standard [smart contract address](https://docs.ton.org/learn/overviews/addresses#address-of-smart-contract) in TON Blockchain.
-* Slice, Cell, Builder — low-level primitives of TON VM.
-* String — represents text strings in TON VM.
-* StringBuilder — helper type that allows you to concatenate strings in a gas-efficient way.
+* [`Int{:tact}`](/book/integers) — all numbers in Tact are $257$-bit signed integers, but [smaller representations](/book/integers#serialization) can be used to reduce storage costs.
+* [`Bool{:tact}`](#booleans) — classical boolean with `true{:tact}` and `false{:tact}` values.
+* `Address{:tact}` — standard [smart contract address](https://docs.ton.org/learn/overviews/addresses#address-of-smart-contract) in TON Blockchain.
+* `Slice{:tact}`, `Cell{:tact}`, `Builder{:tact}` — low-level primitives of TON VM.
+* `String{:tact}` — represents text strings in TON VM.
+* `StringBuilder{:tact}` — helper type that allows you to concatenate strings in a gas-efficient way.
+
+## Booleans
+
+The primitive type `Bool{:tact}` can hold only the two values: `true{:tact}` and `false{:tact}`. It's convenient for boolean and logical operations, as well as for storing flags.
+
+There are no implicit type conversions in Tact, so addition (`+`) of two boolean values isn't possible. Hovewer, many comparison [operators](/book/statements#operators) are available, such as:
+
+* `&&` for logical `AND`,
+* `||` for logical `OR`,
+* and `!` for logical inversion.
+
+Persisting bools to state is very space-efficient, as 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.
+
+## Maps
+
+The type `map{:tact}` is used as a way to associate data with corresponding keys.
+
+Possible key types:
+
+* [`Int{:tact}`](/book/integers)
+* `Address{:tact}`
+
+Possible value types:
+
+* [`Int{:tact}`](/book/integers)
+* [`Bool{:tact}`](#booleans)
+* `Cell{:tact}`
+* `Address{:tact}`
+* [Struct](#structs-and-messages)
+* [Message](#structs-and-messages)
+
+```tact
+contract HelloWorld {
+ counters: map;
+}
+```
## Structs and Messages
-[Struct](/book/defining-types#structs) example:
+[Structs][structs] and [Messages][messages] are two main ways of combining multiple [primitive types](#primitive-types) into a composite one.
+
+Example of a [Struct][structs]:
```tact
struct Point {
@@ -31,46 +69,28 @@ struct Point {
}
```
-[Message](/book/defining-types#messages) example:
+Example of a [Message][messages]:
```tact
// Custom numeric id of the Message
message(0x11111111) SetValue {
key: Int;
- value: Int?; // Optional
+ value: Int?; // Optional, Int or null
coins: Int as coins; // Serialization into TL-B types
}
```
-Learn more about them on a dedicated page about [defining composite types](/book/defining-types).
+Learn more about them on a dedicated page about [composite types](/book/composite-types).
-## Maps
-
-The type `map{:tact}` is used as a way to associate data with corresponding keys.
-
-Possible key types:
-* Int
-* Address
-
-Possible value types:
-* Int
-* Bool
-* Cell
-* Address
-* [Struct](/book/defining-types#structs)
-* [Message](/book/defining-types#messages)
-
-```tact
-contract HelloWorld {
- counters: map;
-}
-```
+[structs]: /book/composite-types#structs
+[messages]: /book/composite-types#messages
## Contracts
-Contracts are the main entry of a smart contract on the TON blockchain. It holds all functions, getters, and receivers of a TON contract.
+Contracts are the main entry of a smart contract on the TON blockchain. It holds all [functions](/book/functions), [getters](/book/functions#getter-functions), and [receivers](/book/functions#receiver-functions) of a TON contract.
```tact
+// Basic example of a counter contract:
contract HelloWorld {
counter: Int;
diff --git a/scripts/redirects-generate.js b/scripts/redirects-generate.js
index fc6b87b6..3be66ffd 100644
--- a/scripts/redirects-generate.js
+++ b/scripts/redirects-generate.js
@@ -105,6 +105,21 @@ const getRedirects = () => [
subSources: undefined,
destination: '/ecosystem/tools/vscode',
},
+ {
+ source: '/book/ints',
+ subSources: undefined,
+ destination: '/book/integers',
+ },
+ {
+ source: '/book/numbers',
+ subSources: undefined,
+ destination: '/book/integers',
+ },
+ {
+ source: '/book/defining-types',
+ subSources: undefined,
+ destination: '/book/composite-types',
+ },
];
/**