费用计算
当您的合约开始处理收到的报文时,您应该检查报文所附的 TON 数,以确保它们足以支付所有类型的费用。为此,您需要计算(或预测)当前交易的费用。
本文档描述了如何使用新的 TVM 操作码 (opcode) 计算FunC 合约的费用。
有关操作码的更多信息
有关 TVM 操作码(包括下面提到的操作码)的完整列表,请查看 TVM 指令页面。
存储费
概述
简而言之,存储费
是您为在区块链上存储智能合约而支付的费用。智能合约在区块链上存储的每一秒都需要付费。
使用带有以下参数的 GETSTORAGEFEE
操作码:
参数名称 | 说明 |
---|---|
cells | 合约 cell 数 |
bits | 合约位数 |
is_mc | 如果源或目标位于主链中,则为 True |
存储和转发费用只计算唯一的哈希 cell ,即 3 个相同的哈希 cell 算作一个。
特别是,它可以重复数据:如果在不同分支中引用了多个等效子 cell ,则其内容只需存储一次。
计算流程
每份合约都有余额。您可以使用函数计算在指定的 "秒 "时间内,您的合约需要多少 TON 才能继续有效:
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
是硬编码,记得在合约更新过程中更新它。并非所有合约都支持更新,因此这是一个可选要求。