使用@mysten/sui TypeScript SDK发布SUI合约遇PublishErrorNonZeroAddress错误
问题:使用@mysten/sui TypeScript SDK发布合约时出现PublishErrorNonZeroAddress错误
我尝试用@mysten/sui TypeScript SDK构建并发布新的SUI智能合约包,但执行交易模拟时失败,模拟结果显示错误:PublishErrorNonZeroAddress in command 0。
相关配置信息:
- Move.toml中edition设置为2024.beta
- SUI依赖先后试过framework/testnet和framework/devnet两种配置
- @mysten/sui SDK版本为1.12.0
- 在devnet和testnet网络均尝试过,结果一致失败,但使用CLI可正常构建并部署该合约
以下是我的代码示例:
import path from 'path'; import { execSync } from 'child_process'; import { getFullnodeUrl, SuiClient, } from '@mysten/sui/client'; import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"; import { Transaction } from '@mysten/sui/transactions'; const client = new SuiClient({ url: getFullnodeUrl('testnet') }); const signer = Ed25519Keypair.deriveKeypair("my seed phrase"); const contractURI = path.resolve(__dirname, "../", "./contract"); const { modules, dependencies } = JSON.parse( execSync(`sui move build --dump-bytecode-as-base64 --path ${contractURI}`, { encoding: 'utf-8', }) ); const tx = new Transaction(); tx.setSender(signer.getPublicKey().toSuiAddress()); tx.setGasBudget(1000000000); const upgradeCap = tx.publish({ modules, dependencies }); tx.transferObjects([upgradeCap], signer.getPublicKey().toSuiAddress()); const txBytes = await tx.build({ client }); const signature = (await signer.signTransaction(txBytes)).signature; const simulationResult = await client.dryRunTransactionBlock({ transactionBlock: txBytes }); if (simulationResult.effects.status.status === "success") { const result = await client.executeTransactionBlock({ transactionBlock: txBytes, signature, options: { showEffects: true, } }); console.log("Result: ", result); } else { console.log("Simulation failed: ", simulationResult); }
解决方案
这个错误的核心原因是2024.beta版本的Move合约在发布时,SDK需要显式指定发布者地址作为包的地址生成器,CLI会自动处理该逻辑,但SDK需手动配置。
修改步骤:
- 在创建
Transaction实例后,添加setPackageAddressGenerator方法指定发布者地址:
const tx = new Transaction(); // 新增此行配置地址生成器 tx.setPackageAddressGenerator(signer.getPublicKey().toSuiAddress()); tx.setSender(signer.getPublicKey().toSuiAddress()); tx.setGasBudget(1000000000);
- 确保
sui move build命令使用与SDK连接一致的网络,避免依赖不匹配:
execSync(`sui move build --dump-bytecode-as-base64 --path ${contractURI} --network testnet`, { encoding: 'utf-8', })
完整修改后的核心代码片段:
const tx = new Transaction(); tx.setPackageAddressGenerator(signer.getPublicKey().toSuiAddress()); tx.setSender(signer.getPublicKey().toSuiAddress()); tx.setGasBudget(1000000000); const upgradeCap = tx.publish({ modules, dependencies }); tx.transferObjects([upgradeCap], signer.getPublicKey().toSuiAddress()); // 构建交易时指定网络,确保一致性 const txBytes = await tx.build({ client, network: 'testnet' });
说明:
- 2024.beta版本的Move引入了包地址生成器机制,要求发布者必须显式指定地址生成规则,否则会触发
PublishErrorNonZeroAddress错误。 - CLI发布时默认使用发送者地址作为生成器,而SDK需要手动调用
setPackageAddressGenerator完成配置。
内容的提问来源于stack exchange,提问作者Dejan Ignjatovic
相关产品推荐
相关产品推荐

