Расчёт комиссии
Когда ваш контракт начинает обрабатывать входящее сообщение, важно проверить, достаточно ли прикрепленных к нему токенов TON для покрытия всех типов комиссий. Для этого необходимо рассчитать или спрогнозировать комиссию за текущую транзакцию.
В этой статье мы разберём, как рассчитывать комиссии в контрактах FunC с ис пользованием новых опкодов (кодов операций) TVM.
Полный список опкодов TVM, включая упомянутые ниже, вы можете найти на странице инструкций по TVM.
Комиссия за хранение
Обзор
storage fees
- это плата за размещение смарт-контракта в блокчейне. Она взимается за каждую секунду его хранения.
Для получения значений комиссии, используйте опкод GETSTORAGEFEE
со следующими параметрами:
Параметр | Описание |
---|---|
cells | Количество ячеек контракта |
bits | Количество битов контракта |
is_mc | Флаг, принимает значение True, если источник или получатель находятся в мастерчейне |
В частности, происходит дедупликация данных: если в разных ветвях есть несколько одинаковых подъячеек, их содержимое сохраняется только один раз.
Последовательность расчёта
У каждого контракта есть свой баланс. Можно рассчитать, сколько TON (токенов) потребуется, чтобы контракт оставался активным в течение указанного времени seconds
, с помощью следующей функции:
int get_storage_fee(int workchain, int seconds, int bits, int cells) asm(cells bits seconds workchain) "GETSTORAGEFEE";
Затем это значение можно вписать в код контракта и рассчитать актуальную комиссию за хранение следующим образом:
;; functions from func stdlib (not presented on mainnet)
() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
int get_storage_fee(int workchain, int seconds, int bits, int cells) asm(cells bits seconds workchain) "GETSTORAGEFEE";
int my_storage_due() asm "DUEPAYMENT";
;; constants from stdlib
;;; Creates an output action which would reserve exactly x nanograms (if y = 0).
const int RESERVE_REGULAR = 0;
;;; Creates an output action which would reserve at most x nanograms (if y = 2).
;;; Bit +2 in y means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved.
const int RESERVE_AT_MOST = 2;
;;; in the case of action fail - bounce transaction. No effect if RESERVE_AT_MOST (+2) is used. TVM UPGRADE 2023-07. v3/documentation/tvm/changelog/tvm-upgrade-2023-07#sending-messages
const int RESERVE_BOUNCE_ON_ACTION_FAIL = 16;
() calculate_and_reserve_at_most_storage_fee(int balance, int msg_value, int workchain, int seconds, int bits, int cells) inline {
int on_balance_before_msg = my_ton_balance - msg_value;
int min_storage_fee = get_storage_fee(workchain, seconds, bits, cells); ;; can be hardcoded IF CODE OF THE CONTRACT WILL NOT BE UPDATED
raw_reserve(max(on_balance_before_msg, min_storage_fee + my_storage_due()), RESERVE_AT_MOST);
}
Если значение storage_fee
задано в виде константы, не забудьте его обновить при изменении контракта. Поскольку не все контракты поддерживают обновление, это не обязательное требование.