---
# System prepended metadata

title: FunС

---

# FunС

### Общая инфа
На текущий момент нет официальной документации по языку. FunC позволяет на более высоком уровне чем Fift создать смарт-контракт, используя такие примитивы как функции

### Пример из доки

``` 
;; Heavy-duty wallet for mass transfers (e.g., for cryptocurrency exchanges)
;; accepts orders for up to 254 internal messages (transfers) in one external message

() recv_internal(slice in_msg) impure {
  ;; do nothing for internal messages
}

() recv_external(slice in_msg) impure {
  var signature = in_msg~load_bits(512);
  var cs = in_msg;
  var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
  throw_if(35, valid_until <= now());
  var ds = get_data().begin_parse();
  var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256));
  ds.end_parse();
  throw_unless(33, msg_seqno == stored_seqno);
  throw_unless(34, subwallet_id == stored_subwallet);
  throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));
  var dict = cs~load_dict();
  cs.end_parse();
  accept_message();
  int i = -1;
  do {
    (i, var cs, var f) = dict.idict_get_next?(16, i);
    if (f) {
      var mode = cs~load_uint(8);
      send_raw_message(cs~load_ref(), mode);
    }
  } until (~ f);
  set_data(begin_cell()
    .store_uint(stored_seqno + 1, 32)
    .store_uint(stored_subwallet, 32)
    .store_uint(public_key, 256)
    .end_cell());
}

;; Get methods

int seqno() method_id {
  return get_data().begin_parse().preload_uint(32);
}

```

## Построчно разберем код

Первая функция:

```
() recv_internal(slice in_msg) impure {
  ;; do nothing for internal messages
}
```

Она принимает внутреннее (internal) сообщение от контракта в сети TON. Нужна для коммункации между контрактами. 

```
Указывает на то, что функция ничего не возвращает void
|
|                    Принимает slice объект от другого контракта 
|                    |
|                    |             Декоратор, видимо говорящий о том, что функция не явлеятся getter,  деталей пока нет
V                    V             V
() recv_internal(slice in_msg) impure { 
}
```

Фактически функция игнорирует любой запрос со стороны контракта, а не пользователя. Пользователь делает external сообщения в сеть. Оба типа сообщений даже у нод по-разному хранятся.

Важно понимать, что slice тут, по факту просто куча байтов произвольной длины

____

```
() recv_external(slice in_msg) impure {
```

Имеет такую же логику как и internal, отличается лишь неймингом, который очень ВАЖЕН!

```
 var signature = in_msg~load_bits(512);
```

Обозначем переменную signature, которая грузится из первых 512 бит slice переменной in_msg, которую нам передали

По guidelines от создателей они решили разбить на участки slice in_msg

Первый участок - подпись 512 бит

```
a~load_bits(b);
```
load_bits возвращает первые (мб и нет) b бит из slice переменной a

```
 var cs = in_msg;
 var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
```

Тут сначала непонятно зачем создается cs переменная из in_msg, это может быть связано с тем, что in_msg и cs находятся в разных областях памяти и cs переменная на чтение будет требовать меньше или 0 газа в отличии от in_msg (а может и нет, просто по фану сделали)

```
 var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
```

Массовое создание и присвоение значений 

var (a, b, c ... , d) = (z, y, x, ... , f)

Тут опять загружается 32 бита из slice переменной

Видимо после заргрузки N бит, переменная slice уменьшается на эти N бит

Собственно создаются переменные:

subwallet_id - некий id кошелька

valid_until - момент, до какого числа сообщение external будет действительным. Иначе злоумышленник может похитить ваше сообщение из пула всех сообщений и выполнить его в любое время

msg_seqno - так называемый nonce. Некое число, которое отображает количество уже подписанных и отправленных тобой транзакций. Если его не будет, то злоумышленник может украсть твою подпись, сумму, автора и повторять заносить эти данные как новые транзакции

```
 throw_if(35, valid_until <= now());
```
 
throw_if выбрасывает ошибку с кодом 35, если условие valid_until <= now() не выполняется

now() - позволяет получить текущее время

Проверка нужна на то, что не просрачилась транзакция

```
  var ds = get_data().begin_parse();
  var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256));
  ds.end_parse();
```

get_data() - метод для того, чтобы начать считывать данные из клеток (я так понимаю, что за контрактом закреплен некий storage, то, как из него читать и писать примерно известно)


get_data() - открывает некий поток, а ля io.open / close 

get_data().begin_parse() - позволяет из него читать

```
 var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256));
```

Тут мы получем уже сохранненные данные из клетки в memory переменные

stored_seqno, stored_subwallet, public_key - очевидно, что это такое 


```
  throw_unless(33, msg_seqno == stored_seqno);
  throw_unless(34, subwallet_id == stored_subwallet);
  throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));
```

  проверяем, что nonce сходится, иначе кидаем ошибку с кодом 33
  проверяем, что subwallet_id сходится, иначе кидаем ошибку с кодом 34
  проверяем, что подпись сходится с публичным ключом владельца, иначе кидаем ошибку с кодом 35
  
 ```
 check_signature(slice_hash(in_msg), signature, public_key)
 ```
 Функция проверки подписи, где нужно передать подпись, публичный ключ и hash от сообщения отправителя
 
 
```
 var dict = cs~load_dict();
  cs.end_parse();
```

Идет загрузка dictionary объекта (hashmap видимо). У него есть отдельный метод для загрузки. Видимо в памяти он аллоцирован иначе чем slice данные и читается оттуда как из потока



