使用Polkadot-JS在Substrate链部署智能合约时返回CodeSubmittableResult无有效信息的问题排查
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 yetstatus: Type { ... }: This is the transaction's current state, with getters likeisFuture,isReady,isInBlockto track its progress through the network. The empty events andblueprint: undefinedmean 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:
- You're relying on
result.blueprint, which may have been deprecated or moved in newer Polkadot-JS versions (since you mentioned docs are outdated) - You call
unsub()as soon asisInBlocktriggers, 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
- 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.
- Event-Based Blueprint Extraction: The
contracts.CodeStoredevent is a reliable, version-agnostic way to get the blueprint address—no more relying on outdatedresult.blueprintfields. - Safe Listener Cleanup: We only call
unsub()when the transaction is finalized, ensuring we don't miss critical state updates or event data. - Error Checking: We explicitly check for
dispatchErrorto 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

