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
相关产品推荐
相关产品推荐

