How to Adapt the Dynamic Energy Model?

TRON Core Devs
TRON
Published in
7 min readJan 12, 2023

The dynamic energy model has been deployed and taken effect on the Nile testnet, this article will take the TRC-20 contract of BTT as an example to demonstrate how to adapt to the model for dApp users, developers, wallets, and exchanges. The contract address of BTT on the Nile testnet is TVSvjZdyDSNocHm7dP3jvCmMNsCnMTPa5W, obtain the BTT test coins: Faucet.

The parameters of the Nile testnet dynamic energy model are set in consideration of the current state of the testnet and the convenience of developer testing, and have nothing to do with the parameters of dynamic resource model will be depolyed and opened in the future on the mainnet. The parameters that will be implemented on the mainnet need to be discussed and voted on in the future.

This model dynamically adjusts the future energy consumption of the contract based on the known energy usage of the contract, users call popular contracts to generate additional energy consumption. This additional energy consumption will change with the popularity of the contract. The dynamic energy model increases the use cost of resource-intensive contracts without affecting other dApps, so as to reduce the future resource occupation of these contracts, make the allocation of energy resources on the chain more reasonable, and prevent excessive concentration of network resources on a few contracts, as well as ensure the robustness, diversity, and balanced development of the ecosystem. Before reading this article, please understand the principle and parameter introduction of the dynamic energy model: Introduction to Dynamic Energy Model.

By reading this article, you will learn the following:

  • How to obtain the network parameters related to the dynamic energy model?
  • How to get the energy_factor of the contract?
  • How to set the feelimit of smart contract transactions?
  • How to estimate the energy consumption of calling smart contracts?
  • How to query the detailed fee structure of smart contract transactions?

How to obtain the network parameters related to the dynamic model on the Nile testnet?

Call /wallet/getchainparameters to get the values of threshold, increase_factor, and max_factor on the Nile testnet.

$ curl -X POST  https://nile.trongrid.io/wallet/getchainparameters
{
"chainParameter": [
……
{
"key": "getDynamicEnergyThreshold",
"value": 2000000
},
{
"key": "getDynamicEnergyIncreaseFactor",
"value": 2000
},
{
"key": "getDynamicEnergyMaxFactor",
"value": 25000
}
]
}

Parameters explanation,

  • threshold: getDynamicEnergyThreshold = 2000000, the unit is energy, a contract that consumes more than 2,000,000 energy during the maintenance period is a popular contract. The contract will increase the penalty consumption by a certain percentage in the next maintenance period.
  • increase_factor: getDynamicEnergyIncreaseFactor = 2000, the precision is 10,000. The 2,000 in the above example means that the increase_factor is 0.2. During the maintenance period of the Nile testnet, the energy consumed by the contract exceeds the threshold of 2,000,000 energy, and the energy_factor variable of the contract will be increased by 20%.
  • max_factor: getDynamicEnergyMaxFactor = 25000, the precision is 10000, 25000 in the above example means max_factor is 2.5. The energy_factor variable of the Nile testnet smart contract will not exceed 2.5 at most.

How to get the energy_factor parameter of the Nile testnet BTT token contract?

Call /wallet/getcontractinfo to obtain energy_factorenergy_usage of the BTT contract on the Nile testnet.

$ curl -X POST  https://nile.trongrid.io/wallet/getcontractinfo -d '{"value": "TVSvjZdyDSNocHm7dP3jvCmMNsCnMTPa5W", "visible":true}'

{
……

"runtimecode": "",
"smart_contract": {},
"contract_state": {
"energy_usage": 4002406,
"energy_factor": 25000
"update_cycle": 167814,
}
}

energy_usage indicates that the BTT contract has consumed 4,002,406 energy during the current maintenance period. The precision of energy_factor is 10000, 25000 means the actual value of energy_factor is 2.5. And update_cycle is the current maintenance period number.

How to set the feelimit parameter of a smart contract transaction?

After the dynamic energy model is enabled, the energy consumption of calling popular contracts fluctuates, so calling the same contract in different time periods requires setting different feelimit value. In this case, developers can use the following three methods to set the feelimit of the transaction:

  1. Before each transaction is sent, the total energy consumption is estimated through the Java-tron estimated energy API, and feelimit of the transaction is determined according to the estimated total energy consumption. Assuming that the estimated total energy consumption is 1000 energy, then the transaction feelimit = 1000 * EnergyPrice, the currently EnergyPrice is 420 sun
  2. First, determine the basic energy consumption of a contract function through the Java-tron estimated energy API or past historical experience of the contract. And then get the energy_factor parameter of the contract once every maintenance period, then feelimit for calling this contract transaction = estimated basic energy consumption * (1 + energy_factor) * EnergyPrice, the currently EnergyPrice is 420 sun
  3. First estimate the basic energy consumption of the function of a contract through the Java-tron estimated energy API or past historical experience of the contract, and then obtain the max_factor parameter of the chain, max_factor is the maximum ratio of the energy penalty factor, so no matter how the energy consumption of popular contracts fluctuates, it will not exceed this maximum ratio, then the feelimit of calling this contract transaction = estimated basic energy consumption * (1 + max_factor) * EnergyPrice, the currently EnergyPrice is 420 sun

The advantage of the first method above is that the feelimit setting is very accurate, but the disadvantage is that the operation is more cumbersome, and each transaction needs to be estimated. Compared with the first method, the second method maintains the accuracy of the feelimit setting, but still needs to obtain the energy_factor parameter of the contract every maintenance period (6 hours). The advantage of the third method is that it does not need to obtain the max_factor parameter frequently, because max_factor is a network parameter, and generally after an adjustment, it will not change for a long time, but the feelimit calculated by the third method will be greater than the actual energy cost, because the energy amplification factor energy_factor of most contracts will not reach max_factor.

To sum up, after the dynamic energy model takes effect, the best strategy for feelimit parameter settings of a transaction is to use the third method for popular contracts, and the first or second method for non-popular contracts.

How to estimate the energy consumption of calling smart contracts?

Developers can call wallet/triggerconstantcontract API to estimate the energy consumption value of calling contracts.

An example is listed as follows:

$ 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
}'

{
……
"energy_used": 46236,
"energy_penalty": 32983,
……

}

The result.result in the example stands for the successful execution of estimating operation, the value of energy_used is the estimated energy consumption of the transaction, where the basic energy consumption value is (energy_used energy_penalty), and value of energy_penalty is the additional energy consumption.

The wallet/triggerconstantcontract API can be used to estimate the energy consumption value of calling most smart contracts on the chain, such as USDD, USDT, USDC, TUSD, etc. Meanwhile, in the Java-tron 4.7.0.1 version, a new API of wallet/estimateEnergy is added. Compared to the existing wallet/triggerconstantcontract API, the new API will be more accurate in estimating the energy consumption of calling a small number of special contract. But for FullNode, enabling the wallet/estimateEnergy API is optional. So please pay attention that when developers call wallet/estimateEnergy, if the error message shows that the node does not support this function when calling the new API (this node does not support estimate energy), it is recommended to continue using the wallet/triggerconstantcontract API to estimate energy consumption.

An example is listed as follows:

$ 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
}

The result.result in the example stands for the successful execution of estimating operation, the value of energy_equired is the estimated energy consumption of the transaction, it contains the basic energy consumption and additional energy consumption.

The appropriate feelimit can be determined according to the estimated energy consumption value obtained from these two methods shown before:

  • feelimit = estimated energy consumption * energy unit price

The energy unit price could be queried by calling wallet/getchainparameters API, which is 420 sun at present.

NOTE: the ratio of punitive consumption for popular contracts may vary for each maintenance period (6 hours), so the estimation operations spanning two periods need to be redone.

How to query the fee of calling smart contracts?

After the dynamic energy model is enabled, when wallets, exchanges, and dApps show users the cost composition details of smart contract call transactions, they should consider the cost of penalty consumption.

Take this BTT transfer transaction on the Nile testnet as an example, 50e99121ca7cfa408434d8c452d3c9eeafa63d44b389f9663bd44c78c9addbe1, call /wallet/gettransactioninfobyid to get the consumption of the transaction:

$ curl -X POST  https://nile.trongrid.io/wallet/gettransactioninfobyid -d '{"value": "50e99121ca7cfa408434d8c452d3c9eeafa63d44b389f9663bd44c78c9addbe1","visible": true}'

{
……
"id": "50e99121ca7cfa408434d8c452d3c9eeafa63d44b389f9663bd44c78c9addbe1",
"fee": 19684740,
"receipt": {
"energy_usage": 189,
"net_usage": 0,
"energy_fee": 19339740,
"energy_usage_total": 46236,
"net_fee": 345000,
"origin_energy_usage": 0,
"result": "SUCCESS",
"energy_penalty_total": 32983
},
……

}

Note: the actual call to the above API will not contain a field with a value of 0 in the return value, so if the field described below does not exist in the actual call, it means that the value of the field is 0.

The resource consumption details of this transaction are as follows:

1. Total energy consumption: receipt.energy_usage_total = 46,236

  • Penalty energy consumption: receipt.energy_penalty_total = 32,983
  • Basic energy consumption: receipt.energy_usage_totalreceipt.energy_penalty_total = 46,236–32,983 = 13,253

2. Total bandwidth consumption: receipt.net_fee/ bandwidth price + receipt.net_usage = 345000/1000 + 0 = 345

The resource consumption source of this transaction is as follows:

1. Energy

  • Energy from TRX staked: receipt.energy_usage = 189
  • Energy from TRX burned: receipt.energy_usage_totalreceipt.energy_usage = 46,236–189 = 46,047
  • Energy from contract deployer: receipt.origin_energy_usage = 0

2. Bandwidth

  • Bandwidth from TRX staked: receipt.net_usage = 0
  • Bandwidth from TRX burned: receipt.net_fee/ bandwidth price = 345000/1000 = 345

The fees for this transaction are broken down as follows:

1. Total cost = 19,684,740 (19.684740 TRX)

  • Energy cost: receipt.energy_fee = 19,339,740 (19.339740 TRX)
  • Bandwidth cost: receipt.net_fee = 345,000 (0.345TRX)

--

--