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

Hedera测试网合约部署成功但无代码,Anvil环境运行正常

智能合约部署问题:Hedera测试网部署后合约地址无代码

部署脚本

require('dotenv').config();
const { ethers } = require("ethers");
const fs = require("fs");
const path = require("path");

const RPC_URL = process.env.RPC_URL.replace(/"/g, "");
const PRIVATE_KEY = process.env.PRIVATE_KEY.replace(/"/g, "");
const ADMIN_ADDRESS = process.env.ADMIN_ADDRESS.replace(/"/g, "");

console.log(`=== Using RPC_URL ${RPC_URL} ===`);
console.log(`=== Using PRIVATE_KEY ${PRIVATE_KEY} ===`);
console.log(`=== Using ADMIN_ADDRESS ${ADMIN_ADDRESS} ===`);

const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

const shipmentManagerJson = JSON.parse(fs.readFileSync("out/ShipmentManager.sol/ShipmentManager.json"));
const shipmentTokenJson = JSON.parse(fs.readFileSync("out/ShipmentToken.sol/ShipmentToken.json"));

const shipmentManagerBytecode = shipmentManagerJson.bytecode.object || shipmentManagerJson.bytecode;
const shipmentManagerABI = shipmentManagerJson.abi;
const shipmentTokenBytecode = shipmentTokenJson.bytecode.object || shipmentTokenJson.bytecode;
const shipmentTokenABI = shipmentTokenJson.abi;

async function main() {
  let currentNonce = await wallet.getNonce();

  // deploy ShipmentToken
  console.log("=== Deploying ShipmentToken ===");
  const ShipmentTokenFactory = new ethers.ContractFactory(shipmentTokenABI, shipmentTokenBytecode, wallet);
  const shipmentToken = await ShipmentTokenFactory.deploy({
    nonce: currentNonce
  });
  await shipmentToken.waitForDeployment();
  const tokenAddress = await shipmentToken.getAddress();
  currentNonce++;
  const tokenCode = await provider.getCode(tokenAddress);
  if(tokenCode.length <= 2) {
    console.error("Error: ShipmentToken deployment failed, no code at address.");
    process.exit(1);
  }

  // deploy ShipmentManager
  console.log("=== Deploying ShipmentManager ===");
  const ShipmentManagerFactory = new ethers.ContractFactory(shipmentManagerABI, shipmentManagerBytecode, wallet);
  const shipmentManager = await ShipmentManagerFactory.deploy({
    nonce: currentNonce
  });
  await shipmentManager.waitForDeployment();
  const managerAddress = await shipmentManager.getAddress();
  currentNonce++;
  const managerCode = await provider.getCode(managerAddress);
  if(managerCode.length <= 2) {
    console.error("Error: ShipmentManager deployment failed, no code at address.");
    process.exit(1);
  }

  console.log("=== Initializing ShipmentToken ===");
  const tx1 = await shipmentToken.initialize(managerAddress, {
    nonce: currentNonce
  });
  const receipt1 = await tx1.wait();
  if (receipt1.status !== 1) {
    console.error("Error: ShipmentToken initialization transaction failed.");
    process.exit(1);
  }
  currentNonce++;
  
  // initialize ShipmentManager
  console.log("=== Initializing ShipmentManager ===");
  const tx2 = await shipmentManager.initialize(ADMIN_ADDRESS, tokenAddress, ADMIN_ADDRESS, {
    nonce: currentNonce
  });
  const receipt2 = await tx2.wait();
  if (receipt2.status !== 1) {
    console.error("Error: ShipmentManager initialization transaction failed.");
    process.exit(1);
  }

  // update process.env with contract addresses
  console.log("=== Updating environment variables ===");
  LOCAL_ENV_PATH = process.env.LOCAL_ENV_PATH || ".env";
  updateEnv(LOCAL_ENV_PATH, "SHIPMENT_MANAGER_CONTRACT_ADDR", managerAddress);
  updateEnv(LOCAL_ENV_PATH, "SHIPMENT_TOKEN_CONTRACT_ADDR", tokenAddress);

  // update backend and frontend envs with contract addresses
  const BACKEND_ENV_PATH = process.env.BACKEND_ENV_PATH;
  const FRONTEND_ENV_PATH = process.env.FRONTEND_ENV_PATH;

  if (BACKEND_ENV_PATH) {
    updateEnv(BACKEND_ENV_PATH, "ADMIN_PRIVATE_KEY", PRIVATE_KEY);
    updateEnv(BACKEND_ENV_PATH, "SHIPMENT_MANAGER_CONTRACT_ADDR", managerAddress);
    updateEnv(BACKEND_ENV_PATH, "SHIPMENT_TOKEN_CONTRACT_ADDR", tokenAddress);
  }
  
  if (FRONTEND_ENV_PATH) {
    updateEnv(FRONTEND_ENV_PATH, "VITE_SHIPMENT_MANAGER_CONTRACT_ADDR", managerAddress);
    updateEnv(FRONTEND_ENV_PATH, "VITE_SHIPMENT_TOKEN_CONTRACT_ADDR", tokenAddress);
  }

  // write ABIs
  console.log("=== Updating ABIs ===");
  const ABI_BACKEND_OUTPUT_PATH = process.env.BACKEND_ABI_PATH;
  const ABI_FRONTEND_OUTPUT_PATH = process.env.FRONTEND_ABI_PATH;

  if (ABI_BACKEND_OUTPUT_PATH) {
    fs.mkdirSync(ABI_BACKEND_OUTPUT_PATH, { recursive: true });
    fs.writeFileSync(path.join(ABI_BACKEND_OUTPUT_PATH, "ShipmentManager.json"), JSON.stringify(shipmentManagerABI, null, 2));
    fs.writeFileSync(path.join(ABI_BACKEND_OUTPUT_PATH, "ShipmentToken.json"), JSON.stringify(shipmentTokenABI, null, 2));
  }

  if (ABI_FRONTEND_OUTPUT_PATH) {
    fs.mkdirSync(ABI_FRONTEND_OUTPUT_PATH, { recursive: true });
    fs.writeFileSync(path.join(ABI_FRONTEND_OUTPUT_PATH, "ShipmentManager.json"), JSON.stringify(shipmentManagerABI, null, 2));
    fs.writeFileSync(path.join(ABI_FRONTEND_OUTPUT_PATH, "ShipmentToken.json"), JSON.stringify(shipmentTokenABI, null, 2));
  }
  
  console.log("");
  console.log("SHIPMENT_TOKEN_CONTRACT_ADDR=" + tokenAddress);
  console.log("SHIPMENT_MANAGER_CONTRACT_ADDR=" + managerAddress);
  console.log("");
  console.log("=== Contracts deployed and ABIs extracted to ===");
  console.log(ABI_BACKEND_OUTPUT_PATH);
  console.log(ABI_FRONTEND_OUTPUT_PATH);
}

function updateEnv(envPath, key, value) {
  let env = fs.readFileSync(envPath, "utf-8").split("\n");
  let found = false;
  env = env.map(line => {
    if (line.startsWith(key + "=")) {
      found = true;
      return `${key}=${value}`;
    }
    return line;
  });
  if (!found) env.push(`${key}=${value}`);
  fs.writeFileSync(envPath, env.join("\n"));
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});

ShipmentToken合约骨架

contract ShipmentToken is Initializable, ERC20PermitUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable {
  // some code here
}

问题现象

  • 在Anvil测试网(RPC地址:http://localhost:8545)使用对应账户地址和私钥时,脚本执行完全成功
  • 切换到Hedera测试网(RPC地址:https://testnet.hashio.io/api)并使用Hedera测试网账户的地址和私钥时,ShipmentManager与ShipmentToken的部署交易回执状态为1(交易成功),且返回了合约地址,但查询这些地址的代码时结果为0x
  • 完全相同的脚本和环境变量两周前可在Hedera测试网正常运行

注:已知当前部署方式不符合升级型智能合约的规范(应使用代理),核心疑问是原本正常的脚本为何现在失效

补充验证信息

  • 执行forge inspect ShipmentToken bytecode | wc -c得到结果17251,字节码长度合理
  • 等待超过15秒后,合约地址的代码仍未更新
  • 手动设置gas limit为10000000,问题未得到解决
  • 部署交易回执状态明确为1,确认交易已成功上链

内容的提问来源于stack exchange,提问作者Kotaka Danski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:44:57