Energy Delegation
Delegate generated ENERGY to another TRON account without transferring ownership of the frozen TRX.
Energy Delegation
Delegate generated ENERGY to another TRON account without transferring ownership of the underlying frozen TRX.
What is Energy delegation?
On TRON, every action that touches a smart contract (including TRC-20 transfers, e.g. USDT) consumes ENERGY. ENERGY is generated by freezing TRX via /staking/delegate, the same mechanism used for BANDWIDTH and voting power.
Energy delegation lets the account that froze the TRX (the owner) share the ENERGY it generates with a different account (the receiver), without moving the frozen TRX itself and without giving up ownership of it. The owner keeps the frozen balance, its voting rights, and can reclaim the delegated resource at any time after the lock period expires.
This is the pattern used to cover gas costs for a large number of wallets from a single pool of frozen TRX — for example, an exchange or a custodian freezing TRX once and delegating ENERGY to hundreds of hot wallets so that each of them can pay for TRC-20 transfers without holding TRX of its own.
The full flow
Energy delegation sits between the freeze and unfreeze steps of the regular TRON staking flow:
freeze → delegate-resource → undelegate-resource → unfreeze → withdraw
| Step | Endpoint | Description |
|---|---|---|
| /staking/delegate | Freeze TRX and generate ENERGY on the owner account |
| /staking/delegate-resource | Delegate generated ENERGY from the owner to a receiver account. |
| /staking/undelegate-resource | Reclaim previously delegated ENERGY back to the owner, once the delegation lock period has passed. |
| /staking/undelegate | Unfreeze the owner's TRX |
| /staking/withdraw | Claim the unfrozen TRX back to the available balance |
Steps 1, 4, and 5 are the standard freeze/unfreeze/withdraw operations already described in Getting Started and Withdrawal. This guide focuses on steps 2 and 3, which sit in between.
Note that the owner does not have to unfreeze immediately after undelegating. ENERGY can be delegated and reclaimed many times over the lifetime of a single frozen balance — unfreezing is only required once the owner wants the underlying TRX back.
Signing model
As with any other operation on TRON, /staking/delegate-resource and /staking/undelegate-resource only build and return an unsigned transaction — the API never holds or uses your private key. The client is responsible for signing every transaction in the flow (freeze, delegate-resource, undelegate-resource, unfreeze, withdraw) individually with the P2P Signer SDK and broadcasting it via /transaction/send, following the steps described in Sign and Broadcast Transaction.
The owner address that signs the delegate/undelegate-resource transaction must be the same address that froze the TRX (delegatorAddress) — the receiver never signs anything as part of this flow.
1. Create delegate-resource request
To delegate generated ENERGY to a receiver account, send a POST request to /api/v1/tron/{network}/staking/delegate-resource.
Example request (for testnet-nile network):
curl --request POST \
--url 'https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/delegate-resource' \
--header 'accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"delegatorAddress": "TVscj8F6wPZ92d1smGYjH9heZR1MaEcE9u",
"amount": 1000000,
"resource": "ENERGY"
}'delegatorAddress— owner account address, i.e. the account that froze the TRX and generated theENERGY.amount— amount of resource to delegate, in SUN (1 TRX = 10⁶ SUN).resource— resource type to delegate. OnlyENERGYis supported in the current version, defaults toENERGY.
Example response:
{
"error": {},
"result": {
"delegatorAddress": "TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg3r",
"receiverAddress": "TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg3r",
"amount": 10000000,
"resource": "ENERGY",
"lockPeriod": 28800,
"unsignedTransaction": {},
"unsignedTransactionSerialized": "eyJ0eElEIjoidHJ4SWQifQ==",
"createdAt": "2025-06-03T12:00:00.000Z"
}
}delegatorAddress— owner account address.receiverAddress— account address receiving the delegated resource.amount— amount of resource delegated, in SUN.resource— resource type delegated:ENERGY.unsignedTransaction— original unsigned transaction object returned by tronWeb.unsignedTransactionSerialized— unsigned serialized transaction in Base64 format, ready for signing.createdAt— timestamp of the transaction in the ISO 8601 format.
Delegation lock
TRON enforces a protocol-level lock on delegated resources: once ENERGY has been delegated to a receiver, it cannot be undelegated for approximately 24 hours from the moment the delegation transaction is confirmed. This is a network rule, and it applies per delegation — each new /staking/delegate-resource call starts its own 24-hour lock for the amount it delegates.
Calling /staking/undelegate-resource before the lock period has elapsed will cause the transaction to fail on-chain. Plan any automated re-delegation or rebalancing logic around this window, and track the delegation's confirmation time so you know when it becomes eligible for undelegation.
2. Create undelegate-resource request
Once the lock period has passed, reclaim the delegated ENERGY back to the owner account by sending a POST request to /api/v1/tron/{network}/staking/undelegate-resource.
Example request (for testnet-nile network):
curl --request POST \
--url 'https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/undelegate-resource' \
--header 'accept: application/json' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"delegatorAddress": "TVscj8F6wPZ92d1smGYjH9heZR1MaEcE9u",
"amount": 1000000,
"resource": "ENERGY"
}'delegatorAddress— owner account address that originally delegated the resource.amount— amount of resource to reclaim, in SUN.resource— resource type to reclaim. OnlyENERGYis supported, defaults toENERGY.
Example response:
{
"error": {},
"result": {
"delegatorAddress": "TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg3r",
"receiverAddress": "TNDzfERDpxLDS2w1q6yaFC7pzqaSQ3Bg3r",
"amount": 10000000,
"resource": "ENERGY",
"unsignedTransaction": {},
"unsignedTransactionSerialized": "eyJ0eElEIjoidHJ4SWQifQ==",
"createdAt": "2025-06-03T12:00:00.000Z"
}
}Field descriptions mirror the delegate-resource response above; the only difference is the underlying UnDelegateResourceContract type.
Error codes
/staking/delegate-resource and /staking/undelegate-resource can return the following 400 Bad request errors in addition to the standard 401 and 429 responses:
| Code | Description |
|---|---|
ExceedsDelegatableMaxExeption | The requested amount exceeds the amount of ENERGY |
InvalidReceiverExeption | receiverAddress is malformed or is not a valid |
ReceiverEqualsOwnerExeption | receiverAddress is the same as delegatorAddress |
ResourceNotSupportedExeption | resource is set to a value other than ENERGY |
InvalidDelegatorAddressExeption | delegatorAddress is malformed or does not match the address used to freeze the TRX |
FreezeAmountTooLowExeption | The requested amount is below the minimum amount that can be delegated. |
Testing on the Nile testnet
Before delegating on mainnet, validate the full flow on TRON's Nile testnet using the testnet-nile network identifier.
-
Fund a Nile testnet account. Use the Nile faucet to receive test TRX on your account.
-
Freeze TRX for
ENERGY. Send a POST request to/api/v1/tron/testnet-nile/staking/delegatewithresource: "ENERGY", sign, and broadcast the transaction, as described in Getting Started. -
Delegate the resource. Send a POST request to:
https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/delegate-resourcewith your
delegatorAddress, areceiverAddressyou control (a second Nile testnet account), and theamountto delegate. Sign and broadcast the returned transaction. -
Broadcast via POST
/tron/testnet-nile/transaction/send -
Verify the delegation. The transaction confirms as DelegateResourceContract; getDelegatedResourceV2(owner, pool) shows the delegation with an expire_time.
-
Undelegate the resource. Before the lock has expired, send a POST request to:
https://api-test.p2p.org/api/v1/tron/testnet-nile/staking/undelegate-resourcewith the same
delegatorAddress/receiverAddresspair andamount, then sign and broadcast.
Testnet transactions use the same request/response shapes as mainnet. Only the network path parameter and the api-test.p2p.org host differ, so code validated on Nile carries over to production without changes.
What's next?
Updated 1 day ago