2

I used PolkadotJS to call a contract, when i did, it logged the status "in block", Turns out it never makes any state change. I used contracts-ui it worked, but with JS? Never. What can be the reason: This is my JS snippet:

 const value = 10000;
    const gasLimit = 3000n * 1000000n;
    const storageDepositLimit = null;

 // Send the transaction, like elsewhere this is a normal extrinsic
    await contract.tx
        .commence({ storageDepositLimit, gasLimit }, hash, names, parties, ipfs_str, getFutureUnixTime(hours))
        .signAndSend(alice, result => {
            if (result.status.isInBlock) {
                console.log('in a block');
            } else if (result.status.isFinalized) {
                console.log('finalized');
            }
        }).then(() => res.status(200).send({ data: `#elect-0-rate-${hash}` }));

Am i not calling it right? I took it off the PolkadotJS website

1 Answer 1

2

The best practice is to first dry-run to check for errors and then process the tx:

// Get the initial gas WeightV2 using api.consts.system.blockWeights['maxBlock']
const gasLimit = api.registry.createType(
  'WeightV2',
  api.consts.system.blockWeights['maxBlock']
)

// Query the contract message
// This will return the gas required and storageDeposit to execute the message
// and the result of the message
const { gasRequired, storageDeposit, result } = await contract.query.enter(
  account.address,
  {
    gasLimit: gasLimit,
    storageDepositLimit: null,
    value: new BN('1000000000000000000')
  }
)

// Check for errors
if (result.isErr) {
  let error = ''
  if (result.asErr.isModule) {
    const dispatchError = api.registry.findMetaError(result.asErr.asModule)
    error = dispatchError.docs.length ? dispatchError.docs.concat().toString() : dispatchError.name
  } else {
    error = result.asErr.toString()
  }

  console.error(error)
  return
}

// Even if the result is Ok, it could be a revert in the contract execution
if (result.isOk) {
  const flags = result.asOk.flags.toHuman()
  // Check if the result is a revert via flags
  if (flags.includes('Revert')) {
    const type = contract.abi.messages[5].returnType // here 5 is the index of the message in the ABI
    const typeName = type?.lookupName || type?.type || ''
    const error = contract.abi.registry.createTypeUnsafe(typeName, [result.asOk.data]).toHuman()

    console.error(error ? (error as any).Err : 'Revert')
    return
  }
}

// Gas require is more than gas returned in the query
// To be safe, we double the gasLimit.
// Note, doubling gasLimit will not cause spending more gas for the Tx
const estimatedGas = api.registry.createType(
  'WeightV2',
  {
    refTime: gasRequired.refTime.toBn().mul(BN_TWO),
    proofSize: gasRequired.proofSize.toBn().mul(BN_TWO),
  }
) as WeightV2

setLoading(true)

const unsub = await contract.tx
  .enter({
    gasLimit: estimatedGas,
    storageDepositLimit: null,
    value: new BN('1000000000000000000') // 1 TOKEN or it could be value you want to send to the contract in title
  })
  .signAndSend(account.address, (res) => {
    // Send the transaction, like elsewhere this is a normal extrinsic
    // with the same rules as applied in the API (As with the read example,
    // additional params, if required can follow)
    if (res.status.isInBlock) {
      console.log('in a block')
    }
    if (res.status.isFinalized) {
      console.log('Successfully sent the txn')
      unsub()
    }
  })

Code snippet from Astar doc

2
  • The setLoading() function is not defined
    – Woodfish
    May 5 at 12:56
  • I am getting this error -> Contract trapped during execution.. But when i use the UI it doesn't give any errors, it just works.
    – Woodfish
    May 5 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.