tronprotocol / tronweb

Javascript API Library for interacting with the TRON Network
MIT License
413 stars 271 forks source link

`Assertion failed` during sign #446

Closed mattiaferrari02 closed 9 months ago

mattiaferrari02 commented 9 months ago

I'm creating a transaction using triggerSmartContract to send some USDT tokens

const tronInstance = new TronWeb({ fullHost: "https://api.trongrid.io" })
tronInstance.setAddress(myAddress)
const { transaction } = await tronInstance.transactionBuilder.triggerSmartContract(
      contractAddress,
      "transfer(address,uint256)",
      { feeLimit: 10000000000, callValue: 0 },
      [
        { type: "address", value: to },
        { type: "uint256", value: 1000000 }
      ]
    )

const signedTx = await tronInstance.trx.sign(
      transaction, 
      hex.encode(privateKey)
    )

When i try to sign the transaction i get this error: Screenshot 2023-11-15 at 15 52 32

I'm using version 5.3.1 running in browser environment. I tested the same flow in node environment and it works. I also tried creating the transaction from the browser environment and passing the obtained transaction to the sign function in node env and it gave out the same assertion failed. So it seems to be a problem related to the triggerSmartContract function in browser environment

svein1010 commented 9 months ago

Could you please console.log the transaction object? Then we can figure out the problem.

mattiaferrari02 commented 9 months ago
{"visible":false,"txID":"d6b8bbd289988cf1fa9f5ad334ac41ac35578121970a5f799f043d2f412a4f3a","raw_data":{"contract":[{"parameter":{"value":{"data":"a9059cbb000000000000000000000000f09a649caaace21b043604ca26754757c6f7232300000000000000000000000000000000000000000000000000000000000f4240","owner_address":"4115bbc9f9ddc37976a45436c3ef7ba4f913c3b317","contract_address":"41a614f803b6fd780986a42c78ec9c7f77e6ded13c"},"type_url":"type.googleapis.com/protocol.TriggerSmartContract"},"type":"TriggerSmartContract"}],"ref_block_bytes":"11ec","ref_block_hash":"bcfbce67ae325b35","expiration":1700122296000,"fee_limit":10000000000,"timestamp":1700122237207},"raw_data_hex":"0a0211ec2208bcfbce67ae325b3540c0fdbdb9bd315aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a154115bbc9f9ddc37976a45436c3ef7ba4f913c3b317121541a614f803b6fd780986a42c78ec9c7f77e6ded13c2244a9059cbb000000000000000000000000f09a649caaace21b043604ca26754757c6f7232300000000000000000000000000000000000000000000000000000000000f42407097b2bab9bd31900180c8afa025"}
svein1010 commented 9 months ago

I have tried this method with my own address and it works fine. Please check the address and your privateKey is correct. And do you mind providing a demo repo that can reproduct this issue?

mattiaferrari02 commented 9 months ago

I tried but I can't reproduce it outside my repo... I don't know the reason at this point. Is there another way to send some tokens?, maybe let's try another way

mattiaferrari02 commented 9 months ago

@svein1010 I just tried using the sendToken function from transactionBuilder

const tronInstance = new TronWeb({ fullHost: "https://api.trongrid.io" })
tronInstance.setAddress(address)

const transaction = await tronInstance.transactionBuilder.sendToken("TXuQ8WiGa4LWUDf48UatkUfD3tK9gRyrZd", 1000000, TronWeb.address.toHex("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"))

sendToken causes an error:

class org.tron.core.exception.ContractValidateException : No asset!

Any idea about this? In the same way as before, I can't replicate the error outside my project

svein1010 commented 9 months ago

sendToken is used to transfer TRC10 token but not USDT. It seems it's not a problem of triggerSmartContract. Please check if the address passed to tronWeb.setAddress() is matched the privateKey passed to sign() with the following code:

const address = tronWeb.address.fromPrivateKey(hex.encode(privateKey));
console.log(address === myAddress)
mattiaferrari02 commented 9 months ago

Yes they are the same

mattiaferrari02 commented 9 months ago

I tried this exact snippet of code in my repo and in a new test repo

    const t = new TronWeb({ fullHost: "https://api.trongrid.io" })
    t.setAddress("TBx89tnoJaZrQRdPJAkqrrCJfaEzd6pFgt")
    const seed2 = bip39.mnemonicToSeedSync(mnemonic)
    const { privateKey } = HDKey.fromMasterSeed(seed2).derive(CUSTOM_DERIVATION_PATH)

    const transaction = await t.transactionBuilder.sendToken("TXuQ8WiGa4LWUDf48UatkUfD3tK9gRyrZd", 1000000, TronWeb.address.toHex("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"))

    console.log(transaction)

    const signedTx = await t.trx.sign(
      transaction,
      hex.encode(privateKey as Uint8Array)
    )

    console.log("result", JSON.stringify(signedTx))

In my repo does not work and in the other test repo it does

svein1010 commented 9 months ago

It's a bit hard to location the problem. Perhaps you can check the TronWeb version or others libraries version. Maybe there is something else effect the function.

mattiaferrari02 commented 9 months ago

Yeah I also think that something a bit stange is happening. I took a look in your code but It's a bit difficult for me to understand what part of your code causes that Asserion failed error when I call triggerSmartContract function. Can you give me more information about the flow that the triggerSmartContract function takes so that I can dig into the problem on my own?

svein1010 commented 9 months ago

triggerSmartContract logic:

  1. encode the parameter according to the functionSelector and parameters.
  2. send the following object to https://api.trongrid.io/wallet/triggersmartcontract:
    {
    "contract_address": "41a614f803b6fd780986a42c78ec9c7f77e6ded13c",
    "owner_address": "4166199dd3ae29b71cc71253b21d19bc80bc8f4890",
    "function_selector": "transfer(address,uint256)",
    "parameter": "0000000000000000000000000199f9fe51ec358692f84510a003037710cae3e000000000000000000000000000000000000000000000000000000000000f4240",
    "call_value": 0,
    "fee_limit": 10000000000
    }

    Then you will get the unsigned transaction. According to you error screenshot , the problem occurs when encoding the transaction json object to protobuf.

Maybe the following steps can help:

  1. Compare the returned transaction in node and browser to find the difference between them.
  2. Run tronWeb.utils.transaction.txCheck(unsignedTransaction) and check the result.
mattiaferrari02 commented 9 months ago

I checked the unsigned transaction using txCheck and it gives out true. I also checked the parameter serialization in both my environments and they are exactly the same...

Can you briefly explain to me also the flow of sign function?

svein1010 commented 9 months ago

The sign logic is simple:

  1. check the transaction: tronWeb.utils.transaction.txCheck(unsignedTransaction)
  2. sign the transaction: tronWeb.utils.crypto.signTransaction(privateKey, unsignedTransaction).

And your error is occurs in google-protobuf.js. It seems that it occurs in txCheck function.

mattiaferrari02 commented 9 months ago

I understood what was the probler: after I created the unsigned transaction I was manually updating the feeLimit of the transaction. By accident we were updating that value using a number with floating point and that caused that assertion failed error. Thanks for the help