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. Themin()means that even with ample staked Energy, a lowfee_limitcan still cap the total and triggerOUT_OF_ENERGY. This dual-bound protects against runaway-Energy consumption (a buggy loop or attack), not just TRX-burn exposure. See the full execution chain under "Howfee_limitis enforced under the hood" 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)TRON's contract Energy model has two independent ceilings on how much Energy a single call can consume. They look similar at first glance, but they live at completely different layers of the system — one is a property of the contract, the other is a property of each individual transaction. Understanding this scope difference is the fastest way to stop confusing them.
| 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) | No hard cap in the actuator — only > 0 is enforced (UpdateEnergyLimitContractActuator.java). 10,000,000 is the default, not a ceiling |
| Default if not set | 0 (the caller can cover 0 Energy; the transaction fails if the deployer cannot cover the full execution) | 10,000,000 Energy |
| How to update | Just set a new value on the next transaction | Submit an UpdateEnergyLimitContract system transaction; once mined, every subsequent call to that contract reads the new value |
| 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" |
The two parameters are independent, but both participate in the Energy-limit calculation for every call. An insufficient origin_energy_limit only reduces the deployer's available subsidy; the caller may cover the remainder. The transaction fails with OUT_OF_ENERGY only when the combined Energy that the caller and deployer can cover is still insufficient.
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 metadata. It is set once when the deployer publishes the contract, sits in the on-chain SmartContract record, and is read by every node executing any call to that contract. When the deployer wants to change it, they broadcast an UpdateEnergyLimitContract system transaction; from the next block onward, every caller's transaction loads the new value automatically. Callers do not see this happening — the limit just changes underneath them.
fee_limit is a per-transaction instruction. It travels in the raw_data of each Transaction message and exists only while that specific transaction is being executed. The VM reads it once at the start of execution, converts it to an Energy ceiling (fee_limit / EnergyPrice), and uses that ceiling to cap how much Energy this call can consume. When the call completes, the value is discarded. The contract never records it; the next caller starts with their own fresh fee_limit.
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 are not substitutes — both apply to every call.
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.
The TRX burn is unrefundableEnergy consumed (whether from stake or burn) is never refunded, even if the transaction reverts later or fails on a different check. Always estimate before broadcasting on Mainnet.
How fee_limit is enforced under the hood
fee_limit is enforced under the hoodMost developers don't need to read this section — it is enough to know that fee_limit caps the maximum Energy cost the caller is willing to cover for this transaction. Understanding the enforcement chain also helps explain transaction timeouts and creator/caller settlements.
The full chain in java-tron's VMActuator:
-
Range check. Before anything else, the node validates
0 ≤ fee_limit ≤ MaxFeeLimit(chain parametergetMaxFeeLimit). If yourfee_limitexceeds the current chain limit, you get aContractValidateExceptionimmediately — no Energy is consumed because the transaction never reaches the VM. -
Convert
fee_limitto an Energy ceiling.energyFromFeeLimit = fee_limit / sunPerEnergy, wheresunPerEnergy = DynamicPropertiesStore.getEnergyFee(). This is the maximum Energy cost the caller is willing to cover, and it participates in the budget calculation for both staked Energy and Energy paid for by burning TRX. -
Compute the caller's total Energy budget.
callerEnergyLimit = min(callerStakedEnergy + (balance - callValue) / sunPerEnergy, energyFromFeeLimit). The caller can spend up to this much Energy on their share of the call. -
Add the deployer's contribution (if any). If
consume_user_resource_percent < 100, the protocol then addsdeployerEnergyLimit = min(theoretical share, origin_energy_limit, deployer's available Energy). The deployer's part is not bounded by the caller'sfee_limit— that's aconsume_user_resource_percent+origin_energy_limitdecision, not a caller decision. -
Inject the total into the VM. The VM starts execution with
totalEnergyLimit = callerEnergyLimit + deployerEnergyLimit. Each opcode deducts its Energy cost. When the counter hits zero, the VM throwsOutOfEnergyExceptionand execution halts. -
Settle in TRX. After execution,
payEnergyBilldeducts the actually-consumed Energy: from staked Energy first (no TRX burned), then from the TRX balance atsunPerEnergyper Energy unit (capped by whatfee_limitallows).
The math always works out to actualTRXBurned ≤ fee_limit, because step 2 made it impossible to consume more Energy than fee_limit / sunPerEnergy in the first place.
Side effects worth knowing
- 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. When a contract exceeds the per-transaction CPU time limit, the TVM accounts for Energy up to the limit calculated before execution: both the Energy actually used before the timeout and the unused remainder are recorded as consumed.OUT_OF_ENERGYalso exhausts this Energy allowance after failure, but it has a different trigger: the remaining Energy is insufficient for the next operation, whereasOUT_OF_TIMEmeans execution exceeded the CPU time limit. Expensive logic such as an unbounded loop over a large array increases the timeout risk. See VM exception handling.
The relevant source file is actuator/VMActuator.java, specifically getAccountEnergyLimitWithFixRatio (caller side) and getTotalEnergyLimitWithFixRatio (creator + caller combined).
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 cycle
energy_factor per maintenance cycleIf you call the same contract repeatedly and want a tighter fee_limit, query the contract's current energy_factor once per maintenance cycle (every 6 hours). 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:
BASE_URL=https://api.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl -X POST ${BASE_URL}/wallet/getcontractinfo \
-d '{"value":"TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs","visible":true}'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 cycle, 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, maintenance-cycle transitions, 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.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl -X POST ${BASE_URL}/wallet/triggerconstantcontract \
-d '{
"owner_address": "TTGhREx2pDSxFX555NWz1YwGpiBVPvQA7e",
"contract_address": "TVSvjZdyDSNocHm7dP3jvCmMNsCnMTPa5W",
"function_selector": "transfer(address,uint256)",
"parameter": "0000000000000000000000002ce5...0000038d7ea4c68000",
"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.trongrid.io # example — replace with any TRON node (TronGrid, third-party, or self-hosted)
curl -X POST ${BASE_URL}/wallet/estimateenergy \
-d '{
"owner_address": "TTGhREx2pDSxFX555NWz1YwGpiBVPvQA7e",
"contract_address": "TVSvjZdyDSNocHm7dP3jvCmMNsCnMTPa5W",
"function_selector": "transfer(address,uint256)",
"parameter": "0000000000000000000000002ce5...0000038d7ea4c68000",
"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 applies a per-contract penalty multiplier that grows when a contract is called frequently. It is recalculated every maintenance cycle (every 6 hours). 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.
The estimation APIs use the contract state and energy_factor visible to the estimation node. The factor may change after a maintenance-cycle transition, so cross-cycle caches must be revalidated. Contract state or call-parameter changes can also make a cached estimate unsuitable before the cycle ends.
For full reference, see Resource model — Dynamic Energy Model.
Setting fee_limit and origin_energy_limit in different tools
fee_limit and origin_energy_limit in different toolsThe two parameters travel in different places. fee_limit goes on every transaction, while origin_energy_limit and consume_user_resource_percent only go on the deploy transaction — to change them later, the deployer broadcasts a separate update transaction (wallet/updateenergylimit for the limit, wallet/updatesetting for the percent). All values are in their natural units — sun for fee_limit, Energy (unitless) for origin_energy_limit, percent for consume_user_resource_percent.
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 Dynamic Energy factor may change at a maintenance-cycle transition, while contract state and call parameters can change sooner. Re-estimate before sending or use a conservative budget with a DEM upper-bound buffer.
- 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_TIMEmeans execution exceeded the per-transaction CPU time limit; check for unbounded loops, large-array traversal, and other expensive logic. 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 - VM exception handling —
OUT_OF_ENERGYvsOUT_OF_TIMEand why each one consumes Energy differently - 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 about 24 hours ago