You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Polkadot-JS在Substrate链部署智能合约时返回CodeSubmittableResult无有效信息的问题排查

Troubleshooting Contract Deployment with Polkadot-JS on a Substrate Chain

Let's break down your issue and walk through how to fix it, since outdated docs can make this tricky.

First, Understanding the CodeSubmittableResult You Received

The result you're seeing tells us a few key things right off the bat:

  • dispatchError: undefined: Your transaction didn't hit an execution error (good sign, since your UI confirms deployment works)
  • events: []: At the time this result was logged, no on-chain events had been emitted for the transaction yet
  • status: Type { ... }: This is the transaction's current state, with getters like isFuture, isReady, isInBlock to track its progress through the network. The empty events and blueprint: undefined mean the transaction hadn't reached a state where contract metadata was available yet.

What's Wrong With Your Current Code?

Your callback only checks for isInBlock or isFinalized, but there are two key issues:

  1. You're relying on result.blueprint, which may have been deprecated or moved in newer Polkadot-JS versions (since you mentioned docs are outdated)
  2. You call unsub() as soon as isInBlock triggers, which might cancel the listener before the transaction reaches finalization (or before events are populated)

Fixed Code to Track Progress & Extract Blueprint Data

Instead of relying on the potentially outdated result.blueprint, we'll pull the blueprint address directly from the on-chain contracts.CodeStored event, which is emitted when contract code is successfully uploaded. We'll also track all transaction states to see exactly what's happening:

const unsub = await code.tx.new(
  { gasLimit: 200000, value: 5000 },
  true
).signAndSend(alicePair, (result) => {
  // Track all transaction states to debug progress
  if (result.status.isFuture) {
    console.log("Transaction is queued for future processing");
  } else if (result.status.isReady) {
    console.log("Transaction has entered the node's transaction pool");
  } else if (result.status.isBroadcast) {
    console.log(`Transaction broadcast to nodes: ${result.status.asBroadcast}`);
  } else if (result.status.isInBlock) {
    const blockHash = result.status.asInBlock.toHex();
    console.log(`Transaction included in block: ${blockHash}`);

    // Check for execution errors
    if (result.dispatchError) {
      console.error("Transaction failed to execute:", result.dispatchError.toString());
    } else {
      // Extract blueprint address from the CodeStored event
      result.events.forEach(({ event }) => {
        if (event.section === "contracts" && event.method === "CodeStored") {
          const blueprintAddress = event.data[0];
          console.log("Contract blueprint address:", blueprintAddress.toHex());
          blueprint = blueprintAddress; // Assign your blueprint variable here
        }
      });
    }
  } else if (result.status.isFinalized) {
    const finalizedBlockHash = result.status.asFinalized.toHex();
    console.log(`Transaction finalized in block: ${finalizedBlockHash}`);

    // Re-extract blueprint for confirmation (optional but safe)
    result.events.forEach(({ event }) => {
      if (event.section === "contracts" && event.method === "CodeStored") {
        const blueprintAddress = event.data[0];
        console.log("Finalized contract blueprint address:", blueprintAddress.toHex());
        blueprint = blueprintAddress;
      }
    });

    unsub(); // Only cancel the listener once the transaction is finalized
  } else if (result.status.isDropped || result.status.isInvalid) {
    console.error("Transaction was dropped or marked invalid");
    unsub();
  }
});

Key Improvements Explained

  1. Full State Tracking: You'll now see exactly where your transaction is in the pipeline (queued, in pool, broadcast, etc.), which helps confirm it's moving toward finalization.
  2. Event-Based Blueprint Extraction: The contracts.CodeStored event is a reliable, version-agnostic way to get the blueprint address—no more relying on outdated result.blueprint fields.
  3. Safe Listener Cleanup: We only call unsub() when the transaction is finalized, ensuring we don't miss critical state updates or event data.
  4. Error Checking: We explicitly check for dispatchError to catch any execution issues that might not show up in the UI.

Why Your Original Code's if Didn't Trigger

It's likely that when you ran your code, the callback was firing for intermediate states (like isReady or isBroadcast) but hadn't reached isInBlock or isFinalized yet when you checked the result. By expanding the state checks, you'll see the transaction progress through all stages until it finalizes.

内容的提问来源于stack exchange,提问作者Manolo Viso Romero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 12:42:48