FeeLimit & Energy cost
How fee_limit caps your TRX exposure for smart contract transactions, how it relates to the deployer-side origin_energy_limit, and three practical strategies for sizing it before every deploy or call.
Prerequisites
When you deploy or call a smart contract on TRON, you set a parameter called fee_limit. Setting it wrong is one of the most common ways to lose TRX or have a transaction fail. This page explains what fee_limit actually does, how it differs from origin_energy_limit (a related but different parameter set by the contract deployer), and how to size fee_limit for your transaction before broadcasting.
What fee_limit actually does
fee_limit actually doesfee_limit is a single number you attach to a smart contract transaction. The most useful way to think about it:
fee_limitcaps the Energy budget that the caller can cover for this transaction, expressed in sun.
maxCallerEnergyFromFeeLimit = fee_limit / EnergyPriceThe network compares the Energy derived from fee_limit with the Energy the caller can actually provide through staking and their TRX balance, then uses the smaller value as the maximum the caller can cover for the transaction. If execution has not completed when the caller's required Energy reaches that limit, the transaction fails with OUT_OF_ENERGY. A low fee_limit can therefore cause failure even when the caller has ample staked Energy; conversely, insufficient staked Energy and TRX balance can cause failure even when fee_limit is high enough. In either case, the TRX burned for the call's Energy consumption will not exceed fee_limit. Thus, fee_limit plays two roles:
- A safety cap against runaway Energy caused by buggy code or an attack
- A per-transaction Energy budget, denominated in TRX so developers can control costs without working directly in chain-internal units
Three things to remember
- It is set in sun — not TRX. 1 TRX = 1,000,000 sun.
- The maximum allowed value is currently 15,000 TRX on Mainnet (15 × 10⁹ sun) — but this is a chain parameter (
getMaxFeeLimit, parameter #47). Settingfee_limithigher than the currentgetMaxFeeLimitreturns an error. fee_limitalways applies, regardless of how much Energy you have staked. The VM determines the caller's usable Energy by taking the minimum of two values:The first term is what the caller can cover from staked Energy plus TRX burn; the second term is thecallerEnergyLimit = min(callerStakedEnergy + (balance − callValue) / sunPerEnergy, fee_limit / sunPerEnergy)fee_limitconverted to an Energy ceiling. Taking the minimum means that even with ample staked Energy, a lowfee_limitcan still causeOUT_OF_ENERGY. For details, see "Howfee_limitaffects available Energy" below.
EnergyPrice is also a chain parameter
EnergyPrice(the conversion rate from Energy to sun) is governed by the chain parametergetEnergyFee. The current value is 100 sun per Energy (0.0001 TRX). All examples on this page assume the default — querygetEnergyFeefor the current value when sizingfee_limitfor production.
fee_limit (caller side) vs origin_energy_limit (deployer side)
fee_limit (caller side) vs origin_energy_limit (deployer side)fee_limit caps the Energy the caller can cover for this transaction; origin_energy_limit caps the Energy subsidy the deployer can provide for a single contract call. The former is set per transaction, while the latter is stored in the contract's on-chain information.
| Dimension | fee_limit | origin_energy_limit |
|---|---|---|
| Belongs to | Transaction | Contract |
| Set by | Caller (per transaction) | Deployer (at deploy or via update) |
| Unit | sun (10⁻⁶ TRX) | Energy (unitless) |
| Maximum value | Currently 15,000 TRX on Mainnet (chain parameter, can change) | The update actuator has no hard cap, but requires > 0; 10,000,000 is the SDK fill value described below, not a protocol ceiling |
| Default if not set | Raw HTTP endpoints: 0; TronWeb 6.5.1: the instance's feeLimit, initially 150,000,000 sun (150 TRX), which can be changed | TronWeb 6.5.1 createSmartContract: uses 10,000,000 Energy when originEnergyLimit is omitted or set to 0; when calling /wallet/deploycontract directly, explicitly set origin_energy_limit to a value greater than 0 |
| How to update | Just set a new value on the next transaction | Submit an UpdateEnergyLimitContract system transaction; once effective, subsequent calls use the new cap when calculating the deployer's subsidy |
| Update frequency in practice | High — every transaction, often re-estimated based on call complexity | Low — only when the deployer adjusts operational policy |
| Risk it limits | Per-transaction Energy ceiling on the caller's side | Per-call Energy ceiling on the deployer's side |
| Mental model | "How much energy I'm carrying for this transaction" | "My contract's reimbursement policy" |
When the caller and deployer are different accounts, these parameters limit the Energy each can cover. An insufficient origin_energy_limit reduces the deployer's subsidy, leaving the remainder to the caller. If their combined available Energy cannot complete execution, the transaction fails with OUT_OF_ENERGY.
When the deployer calls their own contract, all Energy is covered by the caller's budget and is subject to that transaction's fee_limit; no separate deployer subsidy is added. The sharing formulas and example below assume the caller and deployer are different accounts.
When using TronWeb, set feeLimit explicitly for deployments and calls, and check raw_data.fee_limit in the generated transaction before signing.
Why scope matters
The single most common source of confusion is treating these as two flavors of the same parameter. They are not.
origin_energy_limit is contract configuration, set at deployment and stored in the contract's on-chain information. The contract owner can update it through UpdateEnergyLimitContract. Once the update takes effect, subsequent calls use the new cap when calculating the deployer's subsidy.
fee_limit is a per-transaction parameter stored in the transaction's raw_data. TVM converts it to the maximum Energy the caller can cover for that execution. It affects only the current transaction: it does not change the contract's resource-sharing settings or carry over to later transactions.
This difference shapes how you think about each:
- If you are building a DApp and want to make calls cheap for users, you tune
origin_energy_limitandconsume_user_resource_percentonce at the contract level — these decisions affect everyone using your contract. - If you are calling a contract and want to bound your own spend, you tune
fee_limitper call — your decision affects only your transaction.
consume_user_resource_percent — the bridge between them
consume_user_resource_percent — the bridge between themA third field, consume_user_resource_percent, sits at the contract level and decides how the call's Energy gets split between caller and deployer. It is an integer between 0 and 100:
100→ caller pays for all Energy. The deployer contributes nothing. This is what most popular contracts set, because subsidizing every call would drain the deployer's account.60→ caller pays 60%, deployer pays 40%.0→ deployer pays for everything. Useful for DApps that subsidize users, but exposes the deployer to drain attacks iforigin_energy_limitis not set carefully.
Like origin_energy_limit, consume_user_resource_percent is also mutable post-deploy through wallet/updatesetting.
How a single call settles both ceilings
When a transaction needs X Energy total, the protocol splits the cost between deployer and caller:
Deployer's Actual Payment = min(
X × (100 - consume_user_resource_percent) / 100 # theoretical share
origin_energy_limit # deployer's per-call cap
deployer_available_Energy # what's actually in deployer's account
)
Caller's Actual Payment = X − Deployer's Actual PaymentThe caller then pays their share from their Energy first, and falls back to burning TRX (capped by fee_limit) for any shortfall.
The maximum Energy the caller can cover is the smaller of fee_limit / EnergyPrice and the sum of the caller's available staked Energy plus the Energy that can be purchased with the available TRX balance. If the caller's required share exceeds that limit, execution fails with OUT_OF_ENERGY.
In one sentence
fee_limitprotects the caller from runaway Energy consumption (and the resulting TRX burn) on this transaction.origin_energy_limitprotects the deployer from drain attacks across all calls to the contract. They limit the caller's budget and the deployer's subsidy respectively and are not substitutes.
A worked example
Suppose:
- A contract call requires
X = 80 Energytotal consume_user_resource_percent = 60→ caller's theoretical share is 60%, deployer's is 40%- Deployer set
origin_energy_limit = 40Energy at deploy time - Deployer's account currently has 10 Energy available
- Caller has 0 staked Energy and sets
fee_limit = 1,000,000 sun(1 TRX, equivalent to 10,000 Energy at the chain default of 100 sun/Energy)
Walking through the formula:
Deployer's Actual Payment = min(
80 × 40% = 32 Energy # theoretical share
40 Energy # origin_energy_limit
10 Energy # available
) = 10 EnergyThe deployer covers only 10 Energy because their account is depleted. The caller covers the remaining 70 Energy.
Caller's Actual Payment = 80 − 10 = 70 EnergyThe caller has 0 staked Energy, so all 70 Energy must come from burning TRX:
TRX burned from caller = 70 × 100 sun = 7,000 sunCaller's fee_limit = 1,000,000 sun is well above 7,000 sun, so the transaction succeeds. The 7,000 sun are deducted from the caller's TRX balance; the remaining 993,000 sun of fee_limit are not charged — fee_limit is a cap, not a payment.
Resource settlement for failed transactionsEnergy charges are not refunded when transaction execution fails. TRX burned to pay for Energy is not returned. Energy supplied by staking or delegation counts toward resource usage, and the available quota recovers gradually over time. Before sending a transaction with high Energy requirements, estimate its Energy consumption and allow a margin for changes in the execution path.
How fee_limit affects available Energy
fee_limit affects available EnergyBefore executing a contract, the network calculates the available Energy allowance from fee_limit, account resources, and the contract's resource-sharing settings.
- Check the parameter range.
fee_limitmust be at least 0 and must not exceed the limit set by thegetMaxFeeLimitchain parameter. Transactions outside this range are rejected during validation, before contract execution. - Convert the limit to Energy. Dividing
fee_limitby the current Energy price gives the maximum Energy the caller can cover for this execution. This cap applies to both Energy obtained through staking or delegation and Energy paid for by burning TRX. - Determine the caller's budget. The Energy the caller can actually cover also depends on their available resources and TRX balance. TRX transferred to the contract in this call is excluded from the balance available to pay for Energy. A high
fee_limitcannot compensate for insufficient resources or balance. - Calculate the deployer's contribution. The deployer's contribution is limited by the sharing percentage,
origin_energy_limit, and their available Energy. When both parties share costs proportionally, the caller's Energy budget also limits how much the deployer can contribute. The caller therefore needs a sufficientfee_limiteven when the deployer has ample resources. When the deployer calls their own contract, all Energy is covered by the caller's budget; no separate deployer allowance is added. - Execute the contract. The Energy available for execution is the sum of both budgets. If the remaining Energy is insufficient for the next operation, execution fails with
OUT_OF_ENERGY. - Settle the charges. After execution, Energy is charged according to the resource-sharing rules. The caller's share is covered first by Energy obtained through staking or delegation, then by burning TRX for any shortfall. See below for how failed executions are charged.
The TRX burned to pay for the caller's Energy cannot exceed fee_limit, because the caller's Energy budget is capped at fee_limit / sunPerEnergy. Any deployer contribution is additional to that caller-side budget.
Constant calls and execution failures
- Constant calls do not require a transaction-level
fee_limit.triggerconstantcontractexecutes locally, creates no on-chain transaction, and consumes no actual account resources. The simulation is still subject to node configuration and protective TVM execution limits; inspect the returnedresultand error message when it fails. OUT_OF_TIMEexhausts the Energy budget for the execution. Whether actual execution exceeds the per-transaction CPU time limit or a specific protocol check triggersOUT_OF_TIMEdirectly, the Energy allowance available to the contract execution is exhausted, including the unused remainder.OUT_OF_ENERGYalso exhausts this allowance, but its trigger is insufficient remaining Energy for the next operation. Inspect the exact message when diagnosingOUT_OF_TIME; expensive logic such as an unbounded loop over a large array increases actual timeout risk. See Smart contract errors for message-specific diagnosis and VM exception handling for Energy accounting.
For the detailed calculation, see the Energy budget implementation.
How to size fee_limit: three strategies
fee_limit: three strategiesThere is no universal "right" fee_limit. The choice trades off precision against complexity. Below are the three strategies developers use in practice, ordered from simplest to most precise.
Strategy 1 — Use max_factor (recommended default)
max_factor (recommended default)max_factor is the upper bound of the Dynamic Energy Model (DEM) penalty factor and is controlled by chain parameter #75 getDynamicEnergyMaxFactor. The API returns the actual penalty factor multiplied by 10,000 as an integer. Mainnet currently returns 34,000; dividing it by 10,000 gives max_factor = 3.4. This means the dynamic penalty can add up to 3.4 times the base Energy, producing a maximum total Energy multiplier of 4.4. Estimate fee_limit from max_factor as follows:
fee_limit = floor(base_energy_estimate × (1 + max_factor)) × EnergyPriceEnergyPrice is the price in sun per unit of Energy, so the resulting fee_limit is also denominated in sun.
Pros: simple and does not require querying each contract's current energy_factor; when the base estimate and chain parameters remain valid, it reduces failures caused by Dynamic Energy penalties.
Cons: typically over-budgets, and the account must be able to cover the higher cap. Normal execution and revert settle according to protocol-defined Energy consumption, but exceptional failures such as OUT_OF_TIME or illegal instructions may charge the maximum Energy allowed for the transaction.
This formula covers only the Dynamic Energy factor upper bound. It does not account for execution branches, state changes, call parameters, account balances, or later chain-parameter changes, so it is a conservative budget rather than a success guarantee.
Strategy 2 — Track each contract's energy_factor per Maintenance Period
energy_factor per Maintenance PeriodIf you call the same contract repeatedly and want a tighter fee_limit, query the contract's current energy_factor once per Maintenance Period (currently every 6 hours on Mainnet). The API also returns this value as an integer scaled by 10,000; divide it by 10,000 to obtain contract_energy_factor before using the formula:
fee_limit = floor(base_energy_estimate × (1 + contract_energy_factor)) × EnergyPriceThe normalized contract_energy_factor is specific to each contract and reflects how heavily that contract is used. It is always between 0 and max_factor. Read the raw energy_factor from wallet/getcontractinfo:
# Query the example contract on the Shasta testnet
BASE_URL=https://api.shasta.trongrid.io
curl -X POST "${BASE_URL}/wallet/getcontractinfo" \
-H 'Content-Type: application/json' \
-d '{"value":"TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs","visible":true}'When switching networks, change both the node endpoint and the contract address. Check that the response contains smart_contract and contract_state before reading contract_state.energy_factor; this field may be omitted when it is zero. An empty object {} is not a zero factor: check the network and contract address.
Pros: usually tighter than Strategy 1 and reflects the contract's Dynamic Energy factor at query time.
Cons: requires periodic refreshes. Even within the same Maintenance Period, contract state, call parameters, and account resources can make an earlier estimate unsuitable.
Strategy 3 — Estimate Energy before every call
A more timely — and more complex — strategy is to call wallet/estimateenergy (or triggerconstantcontract as fallback) before broadcasting and set:
fee_limit = estimated_total_energy × EnergyPricePros: reflects the contract state and Dynamic Energy factor observed by the estimation node at request time, and is usually closer to the eventual execution cost than a cached value.
Cons: adds a node round-trip before every transaction. State changes, factor changes after a new Maintenance Period begins, node-state differences, or a different execution branch can still create estimation error, so keep a reasonable buffer and handle retries.
Picking a strategy
| Your situation | Use |
|---|---|
| Most use cases — wallets, occasional calls, deploys | Strategy 1 (max_factor) |
| High-volume calls to a known, popular contract | Strategy 2 (energy_factor) |
| Maximum precision required (cost-sensitive workloads, exchanges) | Strategy 3 (estimate before every call) |
Estimating Energy before broadcasting
Both Strategies 2 and 3 require a base Energy estimate. There are two APIs.
wallet/triggerconstantcontract — works everywhere
wallet/triggerconstantcontract — works everywhereThis is the universal estimation API. It simulates the transaction on the local node without touching the chain, and returns the Energy that would have been consumed in the energy_used field. It works for both contract calls and contract deployments.
For a contract call:
BASE_URL=https://api.shasta.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl -X POST ${BASE_URL}/wallet/triggerconstantcontract \
-d '{
"owner_address": "TPnBjYQEMo4Yd4866KCzXdi4a169KGd63n",
"contract_address": "TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs",
"function_selector": "balanceOf(address)",
"parameter": "00000000000000000000000015208ef33a926919ed270e2fa61367b2da3753da",
"visible": true
}'For a contract deployment, pass the contract bytecode(the output of contract compiling) in the data field. See HTTP API — triggerconstantcontract.
BASE_URL=https://api.shasta.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl --request POST \
--url ${BASE_URL}/wallet/triggerconstantcontract \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"owner_address": "TZ4UXDV5ZhNW7fb2AMSbgfAEZ7hWsnYS2g",
"data":"608060405234801561000f575f80fd5b50d3801561001b575f80fd5b50d28015610027575f80fd5b5061015b806100355f395ff3fe608060405234801561000f575f80fd5b50d3801561001b575f80fd5b50d28015610027575f80fd5b506004361061004c575f3560e01c806360fe47b1146100505780636d4ce63c1461006c575b5f80fd5b61006a600480360381019061006591906100d2565b61008a565b005b610074610093565b604051610081919061010c565b60405180910390f35b805f8190555050565b5f8054905090565b5f80fd5b5f819050919050565b6100b18161009f565b81146100bb575f80fd5b50565b5f813590506100cc816100a8565b92915050565b5f602082840312156100e7576100e661009b565b5b5f6100f4848285016100be565b91505092915050565b6101068161009f565b82525050565b5f60208201905061011f5f8301846100fd565b9291505056fea26474726f6e58221220ca11b5749b47f126a08ed4dd6de453cf3e3e1d68c1105af0acdd8a38c18b37ac64736f6c63430008140033",
"visible": true
}'The response includes energy_used (total Energy required) and energy_penalty (the DEM penalty portion). Subtract energy_penalty from energy_used if you want only the base Energy.
wallet/estimateenergy — more accurate but optional
wallet/estimateenergy — more accurate but optionalwallet/estimateenergy was introduced in java-tron 4.7.0.1 to give better estimates for a small number of edge-case contracts. It has the same interface as triggerconstantcontract but the response field is energy_required instead of energy_used.
BASE_URL=https://api.shasta.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl -X POST ${BASE_URL}/wallet/estimateenergy \
-d '{
"owner_address": "TPnBjYQEMo4Yd4866KCzXdi4a169KGd63n",
"contract_address": "TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs",
"function_selector": "balanceOf(address)",
"parameter": "00000000000000000000000015208ef33a926919ed270e2fa61367b2da3753da",
"visible": true
}'This API is optional on FullNodes — node operators must enable both vm.estimateEnergy and vm.supportConstant in node config. Support on a public RPC depends on the operator's current configuration. Clients should handle this node does not support estimate energy and fall back to triggerconstantcontract.
Which to use
triggerconstantcontractis the commonly used local simulation endpoint and returnsenergy_used; the node must still enablevm.supportConstant.
estimateenergymay provide a closer estimate for a small set of unusual contracts, but it may be disabled on some nodes.
Usetriggerconstantcontractby default; only switch when you have evidence the estimates differ for your specific contract.
The Dynamic Energy Model — why estimates can drift
If you tested a transaction on Shasta and saw 31,000 Energy, then deployed to Mainnet and saw 90,000 Energy charged for the same call — you encountered the Dynamic Energy Model (DEM).
DEM adjusts a contract's penalty factor based on its Energy usage during the previous Maintenance Period. More frequent calls can produce a higher penalty factor and therefore greater actual Energy consumption. Mainnet's Maintenance Period is currently 6 hours, and the factor is updated once per period. The actual Energy charged for a call is:
actual_energy = floor(base_energy × (1 + contract_energy_factor))Where:
base_energyis the deterministic Energy cost of executing the bytecodecontract_energy_factoris the contract penalty factor obtained by dividing the API'senergy_factorby10,000; it is between 0 andmax_factor
For an infrequently called contract, contract_energy_factor is usually 0 and actual Energy equals base Energy. If the API returns energy_factor = 5,000, then contract_energy_factor = 0.5, adding 0.5 times the base Energy and producing a total of 1.5 times the base amount. Frequently called contracts can have a higher factor.
Energy estimation uses the contract state and energy_factor currently visible to the node. The energy_factor may change when a new Maintenance Period begins, while contract state or call parameters may change within the same period. Do not reuse an estimate for too long, and re-estimate when crossing into a new period.
For full reference, see Paying for resources — Dynamic Energy Model.
Setting fee_limit and origin_energy_limit in different tools
fee_limit and origin_energy_limit in different toolsThese parameters have different scopes and storage locations. Each smart-contract deployment or invocation transaction sets its own fee_limit, while origin_energy_limit and consume_user_resource_percent are contract properties written on-chain at deployment. After deployment, the contract owner can update the latter two through /wallet/updateenergylimit and /wallet/updatesetting. fee_limit is denominated in sun, origin_energy_limit in Energy, and consume_user_resource_percent as an integer from 0 to 100.
HTTP API
For deployment, all three fields go in the wallet/deploycontract body:
BASE_URL=https://api.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl -X POST ${BASE_URL}/wallet/deploycontract \
-d '{
"abi": "...",
"bytecode": "...",
"fee_limit": 1000000000,
"consume_user_resource_percent": 100,
"origin_energy_limit": 10000000,
"owner_address": "TTGhREx2pDSxFX555NWz1YwGpiBVPvQA7e",
"visible": true
}'For a regular call (wallet/triggersmartcontract), only fee_limit is needed — the other two are read from the contract's stored settings.
TronWeb
When deploying:
const tx = await tronWeb.transactionBuilder.createSmartContract(
{
abi: contractAbi,
bytecode: contractBytecode,
feeLimit: 1000e6, // 1,000 TRX, in sun
userFeePercentage: 100, // = consume_user_resource_percent
originEnergyLimit: 10_000_000 // = origin_energy_limit
},
ownerAddress
);When calling, only feeLimit is needed:
const result = await contract
.transfer(toAddress, amount)
.send({ feeLimit: 150e6 });Trident (Java)
// Deploy
Response.TransactionExtention deployTx = wrapper.deployContract(
"TokenContract",
abiJson,
bytecode,
parameters,
150_000_000L, // feeLimit, in sun
100, // consumeUserResourcePercent
10_000_000L, // originEnergyLimit
0L, // callValue
"", // tokenName
0L // tokenValue
);
// Call: callData is the 4-byte function selector followed by ABI-encoded arguments
String callData = "a9059cbb" + parameter;
Response.TransactionExtention callTx = wrapper.triggerContract(
ownerAddress,
contractAddress,
callData,
0L, // callValue
0L, // tokenValue
null, // tokenId
150_000_000L // feeLimit, in sun
);TronBox
Set globally in tronbox-config.js per network:
networks: {
shasta: {
privateKey: process.env.PRIVATE_KEY,
feeLimit: 1000 * 1e6, // 1,000 TRX, in sun
userFeePercentage: 100, // = consume_user_resource_percent
originEnergyLimit: 10_000_000, // = origin_energy_limit
fullHost: 'https://api.shasta.trongrid.io',
network_id: '2'
}
}The userFeePercentage and originEnergyLimit apply only to deployments. For calls, only feeLimit is consulted.
TronIDE
In the Deploy & Run panel, three fields are exposed: feeLimit (sun), userFeePercentage (0–100), and originEnergyLimit (Energy). Defaults are conservative — raise them for large contracts.
Updating after deployNeed to change
consume_user_resource_percentororigin_energy_limiton a contract that's already deployed? Usewallet/updatesetting(the percent) orwallet/updateenergylimit(the limit). Only the deployer can call these.
Common pitfalls
- Setting
fee_limitin TRX instead of sun. Afee_limit = 100(intending 100 TRX) actually authorizes 0.0001 TRX. The transaction fails immediately withOUT_OF_ENERGY. - Assuming
fee_limitis always burned in full. It is a caller-side cost cap, not a fixed fee. Normal execution andREVERTsettle the Energy actually used, while failures such asOUT_OF_TIMEand illegal instructions exhaust the Energy allowance for the execution. Settlement consumes staked Energy first and burns TRX only for the remainder, so the final burn does not necessarily equalfee_limit. - Treating TRX burn as the first step. For an on-chain contract transaction, the VM first converts
fee_limitinto the maximum Energy the caller can cover, then executes and settles resources. This explains why staked Energy and Energy paid for by burning TRX share the same caller-side budget, and why some failed transactions still consume resources. - Hard-coding 15,000 TRX or 100 sun in your code. Both are chain parameters that can be changed by SR vote (
getMaxFeeLimitfor the upper bound,getEnergyFeefor the conversion rate). Production code that sets the maximum or estimates costs should querywallet/getchainparametersrather than embedding the numeric values. - Reusing an estimate for too long. The
energy_factormay change when a new Maintenance Period begins, while contract state and call parameters can change at any time. Re-estimate before sending high-volume transactions, or leave headroom for the Dynamic Energy Model (DEM) upper bound. - Forgetting to estimate for deploys. Deployments are often the highest-Energy operation against a contract. A typical TRC-20 deploy consumes 200,000–500,000 Energy (20–50 TRX at the default
EnergyPrice); a complex contract with libraries can exceed 1,000,000. - Confusing
OUT_OF_TIMEwithOUT_OF_ENERGY.OUT_OF_ENERGYmeans the remaining Energy is insufficient for the next operation; check the Energy estimate, account resources, andfee_limit.OUT_OF_TIMEcan mean that execution exceeded the per-transaction CPU time limit or that a specific protocol check triggered the result directly; inspect the exact error message first. See VM exception handling.
Related resources
- Obtaining Energy — three ways to acquire Energy before deploying or calling
- Resource model — Energy and the Dynamic Energy Model in full
- Paying for resources & Energy sharing — full reference for the deployer/caller Energy split formula
- Smart contract deployment and invocation —
fee_limit,origin_energy_limit, andconsume_user_resource_percentin the deployment HTTP API - Smart contract errors — use the exact error message to determine whether
OUT_OF_TIMEwas triggered by an execution timeout or a protocol check - VM exception handling — trigger conditions and Energy accounting for
OUT_OF_ENERGYandOUT_OF_TIME - Querying chain parameters — read current
EnergyPrice,max_factor, etc. - HTTP API — triggerconstantcontract — full reference
- HTTP API — estimateenergy — full reference
- HTTP API — updatesetting — update
consume_user_resource_percentafter deploy - HTTP API — updateenergylimit — update
origin_energy_limitafter deploy
Updated 13 days ago