diff --git a/func.html.markdown b/func.html.markdown index 13f58839..da1b2214 100644 --- a/func.html.markdown +++ b/func.html.markdown @@ -19,54 +19,74 @@ FunC is a statically typed, which is similar to C. {- this is a comment in the comment -} -} - (int) sum(int a, int b) { ;; This is a function that gets two integer parameters and return integer result - return a + b; ;; All integers are signed and are 257 bit long. Overflow throws exception - ;; expressions must end with a semicolon + (int) sum(int a, int b) { + ;; This is a function that gets two integer parameters + ;; and return integer result + return a + b; + ;; All integers are signed and are 257 bit long. Overflow throws exception + ;; expressions must end with a semicolon } () f(int i, cell c, slice s, builder b, cont c, tuple t) { ;; FunC has 7 atomic types: ;; int - 257 bit signed integers, - ;; cell - basic for TON opaque data structure, which contains up to 1,023 bits and up to 4 references to other cells, + ;; cell - basic for TON opaque data structure, + ;; which contains up to 1,023 bits and up to 4 references to other cells, ;; slice and builder - special objects to read from and write to cells, - ;; continuation - another flavor of cell that contains ready-to-execute TVM byte-code - ;; tuple is an ordered collection of up to 255 components, having arbitrary value types, possibly distinct. - ;; Finally tensor type (A,B, ...) is an ordered collection ready for mass assigning like: (int, int) a = (3, 5); + ;; continuation - another flavor of cell that contains + ;; ready-to-execute TVM byte-code. + ;; tuple is an ordered collection of up to 255 components, + ;; having arbitrary value types, possibly distinct. + ;; Finally tensor type (A,B, ...) is an ordered collection ready for + ;; mass assigning like: (int, int) a = (3, 5); ;; Special case of tensor type is the unit type (). - ;; It represents that a function doesn’t return any value, or has no arguments. + ;; It represents that a function doesn’t return any value, + ;; or has no arguments. } - ;; During execution, the contract has read access to local context: its storage, balance, time, network config, etc. - ;; Contract may change its storage and code, and also may send messages to other contracts + ;; During execution, the contract has read access to local context: + ;; its storage, balance, time, network config, etc. + ;; Contract may change its storage and code, + ;; and also may send messages to other contracts - ;; Let’s write a counter smart contract that gets a number from an incoming message, + ;; Let’s write a counter smart contract that gets a number + ;; from an incoming message, ;; adds to already stored numbers and stores result in “storage” ;; For handling special events, smart contracts have reserved methods: ;; recv_internal() handles internal messages from other smart contracts - ;; recv_external() handles external messages from the outside world — e.g., from a user. + ;; recv_external() handles external messages from the outside world — + ;; e.g., from a user. () recv_internal(slice in_msg_body) { - ;; Cells play the role of memory in the stack-based TVM. A cell can be transformed into a slice, - ;; and then the data bits and references to other cells from the cell can be obtained - ;; by loading them from the slice. Data bits and references to other cells can be stored + ;; Cells play the role of memory in the stack-based TVM. + ;; A cell can be transformed into a slice, + ;; and then the data bits and references to + ;; other cells from the cell can be obtained + ;; by loading them from the slice. + ;; Data bits and references to other cells can be stored ;; into a builder, and then the builder can be finalized into a new cell. - ;; recv_internal gets the slice with incoming message data as an argument. + ;; recv_internal gets the slice + ;; with incoming message data as an argument. ;; As everything else on TON, permanent storage data is stored as a cell. ;; It can be retrieved via the get_data() method ;; begin_parse - converts a cell with data into a readable slice - slice ds = get_data().begin_parse(); ;; `.` is a syntax sugar: a.b() is equivalent to b(a) + slice ds = get_data().begin_parse(); + ;; `.` is a syntax sugar: a.b() is equivalent to b(a) - ;; load_uint is a function from the FunC standard library; it loads an unsigned n-bit integer from a slice + ;; load_uint is a function from the FunC standard library; + ;; it loads an unsigned n-bit integer from a slice int total = ds~load_uint(64); ;; `~` is a "modifying" method: - ;; essentially, it is a syntax sugar: `r = a~b(x)` is equivalent to (a,r) = b(a,x) + ;; essentially, it is a syntax sugar: `r = a~b(x)` + ;; is equivalent to (a,r) = b(a,x) ;; Now let’s read the incoming value from the message body slice int n = in_msg_body~load_uint(32); - total += n; ;; integers support usual +-*/ operations as well as (+-*/)= syntax sugar + total += n; + ;; integers support usual +-*/ operations as well as (+-*/)= syntax sugar ;; In order to keep a store integer value, we need to do four things: ;; create a Builder for the future cell - begin_cell() @@ -79,25 +99,32 @@ FunC is a statically typed, which is similar to C. - ;; The FunC program is essentially a list of function declarations/definitions and global variable declarations. + ;; The FunC program is essentially a list of + function declarations/definitions and global variable declarations. ;; Any function in FunC matches the following pattern: ;; [] () ;; Specifiers: - ;; The impure specifier indicates that function calls should not be optimized (whether its result is used or not) - ;; it is important for methods that change the smart contract data or send messages + ;; The impure specifier indicates that + ;; function calls should not be optimized + ;; (whether its result is used or not) + ;; it is important for methods that change the smart contract data + ;; or send messages ;; The method_id specifier allows you to call a GET function by name - ;; For instance, we can create a get method for the contract above to allow outside viewers to read counter + ;; For instance, we can create a get method for the contract above + ;; to allow outside viewers to read counter int get_total() method_id { slice ds = get_data().begin_parse(); int total = ds~load_uint(64); - ;; Note that (int) and int is the same, thus brackets in the function declaration and in the return statement are omitted. + ;; Note that (int) and int is the same, + ;; thus brackets in the function declaration + ;; and in the return statement are omitted. return total; } ;; Now any observer can read get_total value via lite-client or explorer @@ -108,20 +135,25 @@ FunC is a statically typed, which is similar to C. The actor model is a model of concurrent computation and is at the heart of TON smart contracts. Each smart contract can process one message at a time, change its own state, or send one or several messages. Processing of the message occurs in one transaction, that is, it cannot be interrupted. Messages to one contract are processed consequently one by one. As a result, the execution of each transaction is local and can be parallelized at the blockchain level, which allows for on-demand throughput horizontal scaling and hosting an unlimited number of users and transactions. ```c -;; For normal internal message-triggered transactions, before passing control to recv_internal TVM puts the following +;; For normal internal message-triggered transactions, +;; before passing control to recv_internal TVM puts the following ;; elements on stack. ;;;; Smart contract balance (in nanoTons) ;;;; Incoming message balance (in nanoTons) ;;;; Cell with an incoming message ;;;; Incoming message body, slice type -;; In turn, recv_internal may use only the required number of fields (like 1 in the example above or 4 below) +;; In turn, recv_internal may use only +;; the required number of fields (like 1 in the example above or 4 below) ;; Let’s dive into message sending -() recv_internal (int balance, int msg_value, cell in_msg_full, slice in_msg_body) { +() recv_internal ( + int balance, int msg_value, cell in_msg_full, slice in_msg_body) { ;; - ;; Every message has a strict layout, thus by parsing it, we can get the sender’s address - ;; first, we need to read some tech flags and then take the address using load_msg_addr + ;; Every message has a strict layout, thus by parsing it, + ;; we can get the sender’s address + ;; first, we need to read some tech flags and + ;; then take the address using load_msg_addr ;; function from FunC standard library - () var cs = in_msg_full.begin_parse(); var flags = cs~load_uint(4); @@ -141,15 +173,20 @@ The actor model is a model of concurrent computation and is at the heart of TON ;; it accepts two arguments message and mode send_raw_message(msg, 64); - ;; mode parameter specifies how to process the funds passed into the smart contract with the message and the smart contract funds - ;; 64 means send everything from the incoming message — what’s left after the commission is deducted + ;; mode parameter specifies how to process the funds passed into + ;; the smart contract with the message and the smart contract funds + ;; 64 means send everything from the incoming message — + ;; what’s left after the commission is deducted - ;; Exceptions can be thrown by conditional primitives throw_if and throw_unless and by unconditional throw + ;; Exceptions can be thrown by conditional primitives throw_if and + ;; throw_unless and by unconditional throw ;; by default, it will automatically cause a bounce message with 64 mode var some = 7; - throw_if(102, some == 10); ;; Throw exception with code 102 conditionally - throw_unless(103, some != 10); ;; Throw exception with code 103 conditionally + throw_if(102, some == 10); + ;; Throw exception with code 102 conditionally + throw_unless(103, some != 10); + ;; Throw exception with code 103 conditionally throw(101); ;; Throw exception with code 101 unconditionally } ``` @@ -167,9 +204,11 @@ else { ;;do_alternative(); } -;; If statements are often used as an operation identifier for a smart contract, for example: +;; If statements are often used as an operation identifier +;; for a smart contract, for example: -() recv_internal (int balance, int msg_value, cell in_msg_full, slice in_msg_body) { +() recv_internal ( + int balance, int msg_value, cell in_msg_full, slice in_msg_body) { int op = in_msg_body~load_int(32); if (op == 1) { ;; smth here @@ -183,7 +222,8 @@ else { } ;; Loops -;; FunC supports repeat, while and do { ... } until loops. for loop is not supported. +;; FunC supports repeat, while and do { ... } until loops. +;; for loop is not supported. ;; repeat int x = 1; @@ -206,11 +246,15 @@ do { } until (x % 17 == 0); ;; x = 51 -;; In practice, loops in TON smart contracts are often used to work with dictionaries, or as they are also called in TON hashmaps +;; In practice, loops in TON smart contracts are often used to work with +;; dictionaries, or as they are also called in TON hashmaps -;; A hashmap is a data structure represented by a tree. Hashmap maps keys to values ​​of arbitrary type so that quick lookup and modification are possible. +;; A hashmap is a data structure represented by a tree. +;; Hashmap maps keys to values ​​of arbitrary type so that +;; quick lookup and modification are possible. -;; udict_get_next? from FunC standard library in combination with the loop will help, go through the dictionary +;; udict_get_next? from FunC standard library in combination with +;; the loop will help, go through the dictionary int key = -1; do { @@ -218,33 +262,48 @@ do { } until (~ f); -;; udict_get_next? - Calculates the minimum key k in the dictionary dict that is greater than some given value and returns k, the associated value, and a flag indicating success. If the dictionary is empty, returns (null, null, 0). +;; udict_get_next? - Calculates the minimum key k in the dictionary dict +;; that is greater than some given value and returns k, +;; the associated value, and a flag indicating success. +;; If the dictionary is empty, returns (null, null, 0). ``` # Functions ```c -;; Most useful functions are slice reader and builder writer primitives, storage handlers and sending messages +;; Most useful functions are slice reader and builder writer primitives, +;; storage handlers and sending messages ;; slice begin_parse(cell c) - Converts a cell into a slice -;; (slice, int) load_int(slice s, int len) - Loads a signed len-bit integer from a slice. -;; (slice, int) load_uint(slice s, int len) - Loads a unsigned len-bit integer from a slice. -;; (slice, slice) load_bits(slice s, int len) - Loads the first 0 ≤ len ≤ 1023 bits from slice into a separate slice. +;; (slice, int) load_int(slice s, int len) - +;; Loads a signed len-bit integer from a slice. +;; (slice, int) load_uint(slice s, int len) - +;; Loads a unsigned len-bit integer from a slice. +;; (slice, slice) load_bits(slice s, int len) - +;; Loads the first 0 ≤ len ≤ 1023 bits from slice into a separate slice. ;; (slice, cell) load_ref(slice s) - Loads the reference cell from the slice. ;; builder begin_cell() - Creates a new empty builder. ;; cell end_cell(builder b) - Converts a builder into an ordinary cell. -;; builder store_int(builder b, int x, int len) - Stores a signed len-bit integer x into b for 0 ≤ len ≤ 257. -;; builder store_uint(builder b, int x, int len) - Stores an unsigned len-bit integer x into b for 0 ≤ len ≤ 256. +;; builder store_int(builder b, int x, int len) - +;; Stores a signed len-bit integer x into b for 0 ≤ len ≤ 257. +;; builder store_uint(builder b, int x, int len) - +;; Stores an unsigned len-bit integer x into b for 0 ≤ len ≤ 256. ;; builder store_slice(builder b, slice s) - Stores slice s into builder b. -;; builder store_ref(builder b, cell c) - Stores a reference to cell c into builder b. +;; builder store_ref(builder b, cell c) - +;; Stores a reference to cell c into builder b. ;; cell get_data() - Returns the persistent contract storage cell. ;; () set_data(cell c) - Sets cell c as persistent contract data. -;; () send_raw_message(cell msg, int mode) - put message msg into sending queue with mode. Note, that message will be sent after a successful execution of the whole transaction +;; () send_raw_message(cell msg, int mode) - +;; put message msg into sending queue with mode. +;; Note, that message will be sent after a successful execution +;; of the whole transaction -;; Detailed descriptions of all standard functions can be found in docs https://ton.org/docs/#/func/stdlib +;; Detailed descriptions of all standard functions can be found +;; in docs https://ton.org/docs/#/func/stdlib +;; ``` ## Additional resources