tronprotocol / tronweb

Javascript API Library for interacting with the TRON Network
MIT License
388 stars 259 forks source link

`triggerConstantContract` and `estimateenergy` do not return the correct energy amounts #487

Closed mattiaferrari02 closed 4 months ago

mattiaferrari02 commented 4 months ago

I'm using this snippet of code to get the current energy consumed by a TRC20 transfer

const res = await tron.current.transactionBuilder.estimateEnergy(
      "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "transfer(address,uint256)",
      { feeLimit: 10000000, callValue: 0 },
      [
        { type: "address", value: address,
        { type: "uint256", value: tokenAmount }
      ]
    )

I'm getting always a value like 33889 but when I broadcast the transaction I see in tronscan that the energy consumed sometimes doubles and if I use a fee limit too low the transaction goes out-of-gas For example this The transaction burned 27 TRX for energy but when I try calling triggerConstantContract I get the wrong values:

energy_used: 31895, energy_penalty 17245 (= 14 TRX)

how can I get the correct energy values?

start940315 commented 4 months ago
Screenshot 2024-02-28 at 2 18 52 PM

Because you triggered a frequently used contract and caused 35,245 extra Energy consumption.

mattiaferrari02 commented 4 months ago

Yes but the value that i get from triggerConstantContract is not up to date with the extra energy consumption. When I call triggerConstantContract I always get something like this energy_used: 31895, energy_penalty 17245 (= 14 TRX), but in reality in case of the first transaction i pasted I should have got 64K energy_used with 32K energy penalty. I also opened a post on stackOverflow to describe the problem https://stackoverflow.com/questions/78073497/how-to-accurately-calculate-trc20-transfer-fees

ferdinand026 commented 4 months ago

@mattiaferrari02 That is because a transfer to an address with a USDT balance of 0 will require 15,000 more basic energy than a transfer to an address with some USDT.

You passed an account addrsss whoes USDT balance is not zero when invoking the triggerConstantContract API, then the returned energy_used will be 30k+, but when you transafer USDT acturally, you pass an account address whoes USDT balance is zero, at this situation, the energy_used will be 60k+.

If you passed an account addrsss whoes USDT balance is zero when invoking the triggerConstantContract API, then the returned energy_used will be 60k+.

mattiaferrari02 commented 4 months ago

@ferdinand026 Is there some documentation about this? Does this vary from token to token?

ferdinand026 commented 4 months ago

@mattiaferrari02 When the SSTORE storage instruction in TVM assigns a value to a variable, if the variable value is empty, it will consume 20,000 energy, otherwise, it will only consume 5,000 energy. Therefore, for a certain TRC20 Token transfer, if the balance of the TRC20 token of the receiving account is 0, the energy consumed by the transfer will consume 15,000 more energy than when the balance is not 0. Please refer to this document: https://developers.tron.network/docs/faq#16-why-do-two-transfer-transactions-of-the-same-trc20-token-consume-different-energy .

mattiaferrari02 commented 4 months ago

Ok thank you for the kind explanation about this

PVZMF commented 4 months ago

@mattiaferrari02 I also faced the problem, could you solve the problem? When I enter different amounts of tokens, the energy does not change

mattiaferrari02 commented 4 months ago

The issue that I had was due to the fact that I was using an hardcoded address to make a "dummy" transaction to display the energy fees in my UI in advance. But this snippet of code works correctly

const res = await tron.transactionBuilder.estimateEnergy(
      "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "transfer(address,uint256)",
      { feeLimit: 10000000, callValue: 0 },
      [
        { type: "address", value: address,
        { type: "uint256", value: tokenAmount }
      ]
    )

You just need to make sure that address is the real address to which you want to send token to. Due to the rules of the tron virtual machine, when you try to send some token to an address that had 0 balance of that token the energy required increses as stated here https://developers.tron.network/docs/faq#16-why-do-two-transfer-transactions-of-the-same-trc20-token-consume-different-energy You can also try to use the estimateEnergy rpc, the results and the behaviours are similar.