FeeLimit参数设置

FeeLimit是智能合约交易的一个参数,用于设置调用者愿意承担的智能合约部署或调用所消耗的能量成本的上限,默认值为0,以sun为单位 (1TRX = 1e6 sun),目前可设置的能量费用上限为15000 TRX。

由于执行合约时,Energy的计算和扣除是逐条进行的,一但能量用量超出允许的上限,则合约执行失败,已扣除的Energy不退还,因此在部署或者调用合约之前,建议为交易设置一个合适的feelimit,以保证合约交易的正常执行。下面详细介绍如何预估智能合约交易的能量消耗,以及设置feelimit参数。

如何确定FeeLimit参数?

由于动态能量模型机制,热门合约产生的能量消耗是动态变化的,所以在不同的时间段调用同一个合约,产生的能量消耗可能是不同的,所以在不同时间段调用热门合约的交易需要设置不同的feelimit参数。我们这里介绍三种设置feelimit的方法:

  • 每次合约调用前均预估能量
    每次发送交易之前都先通过API来预估交易的总能量消耗,根据预估的能量消耗来确定交易的feelimit参数:

    合约交易的FeeLimit = 预估的总能量消耗量  * EnergyPrice
    
  • 每个维护周期均获取一次合约energy_factor
    首先,通过triggerconstantcontract API预估或者以往对该合约的历史经验来确定某合约的某函数的基础能量消耗量, 然后在每一个维护周期获取一次合约的energy_factor参数:

    合约交易的FeeLimit = 预估的基础能量消耗 * (1 + energy_factor)* EnergyPrice
    
  • 根据max_factor设置feelimit
    首先,通过triggerconstantcontract API预估或者以往对该合约的历史经验来确定某合约的某函数的基础能量消耗量,然后获取链的max_factor参数,max_factor是能量惩罚系数的最大比例,所以不管热门合约的能量消耗量如何波动,都不会超过这个最大比例:

    合约交易的FeeLimit = 预估的基础能量消耗 *(1 + max_factor)* EnergyPrice
    

上述第1种方法的优点是是feelimit设置非常准确,缺点是操作比较繁琐,每次发送交易都需要进行预估。第2种方法相比与第1种方法保持了feelimit设置的准确性,但仍然需要每一个维护周期(6小时)都获取一次合约的energy_factor参数。第3种方法的优点是操作简单,不需频繁获取max_factor参数,但计算的feelimit会大于实际的能量费用,因为大多数合约的energy_factor不会达到max_factor

如何预估能量消耗?

用户可以调用wallet/triggerconstantcontract 接口预估调用合约交易的能量消耗量,然后根据预估的能量消耗来为交易设置feelimit 参数。

下面是一个例子:

$ curl -X POST  https://nile.trongrid.io/wallet/triggerconstantcontract -d '{
    "owner_address": "TTGhREx2pDSxFX555NWz1YwGpiBVPvQA7e",
    "contract_address": "TVSvjZdyDSNocHm7dP3jvCmMNsCnMTPa5W",
    "function_selector": "transfer(address,uint256)",
    "parameter": "0000000000000000000000002ce5de57373427f799cc0a3dd03b841322514a8c00000000000000000000000000000000000000000000000000038d7ea4c68000",
    "visible": true
}'

执行结果为:

{
   ……
   "result": {
       "result": true
   },
   "energy_used": 46236,
   "energy_penalty": 32983,
   ……


}

上述返回值中result.result字段为true表示预估操作执行成功,energy_used是该交易能量消耗量的预估值,其中基础能量消耗量是(energy_used - energy_penalty),额外消耗量是 energy_penalty

triggerconstantcontract 接口可以预估链上绝大多数智能合约调用交易的能量消耗量,例如USDD、USDT、USDC、TUSD等,Java-tron 4.7.0.1版本还新增了一个 estimateEnery 接口, 该接口相对已有的 triggerconstantcontract 接口在给少数特殊合约预估能量消耗时会更准确。但 estimateEnergy 是可选接口, 可能有些 FullNode 节点没有开启该接口,因此,开发者在使用过程中需要注意,如若调用 estimateEnergy 接口时捕获到节点不支持此功能的错误信息 (this node does not support estimate energy),建议继续使用 triggerconstantcontract 接口预估能量消耗。

$ curl -X POST  https://nile.trongrid.io/wallet/estimateenergy -d '{
    "owner_address": "TTGhREx2pDSxFX555NWz1YwGpiBVPvQA7e",
    "contract_address": "TVSvjZdyDSNocHm7dP3jvCmMNsCnMTPa5W",
    "function_selector": "transfer(address,uint256)",
    "parameter": "0000000000000000000000002ce5de57373427f799cc0a3dd03b841322514a8c00000000000000000000000000000000000000000000000000038d7ea4c68000",
    "visible": true
}'

执行结果:

{
   "result": {
      "result": true
   },
   "energy_required": 34830
}

返回结果中的result.result 字段值为 true 表示预估能量执行成功,energy_required字段值表示该交易的能量消耗量的预估值,其中包含了执行该合约交易的能量基础消耗量和额外消耗量。