如何部署Polygon智能合约并由他人签署部署交易?
Polygon主网离线签署部署合约方案
核心思路是离线生成部署交易数据,由目标所有者钱包签署后,再广播到主网,完全不需要多签或复杂配置,匹配你要的两步流程。
步骤1:生成未签名的部署交易
用Hardhat+ethers.js编写脚本,生成包含合约部署数据的未签名交易,保存为文件发送给签署人。
示例脚本(generate-unsigned-tx.js)
const { ethers, network } = require("hardhat"); const fs = require("fs"); async function main() { // Polygon主网链ID const CHAIN_ID = 137; // 签署人的钱包地址(用来获取交易nonce) const DEPLOYER_ADDRESS = "0x替换为上司的钱包地址"; // 加载你的合约工厂 const TargetContract = await ethers.getContractFactory("你的合约名称"); // 合约构造函数参数(无参数则留空数组) const constructorArgs = []; // 生成部署合约的交易数据 const deployTxData = TargetContract.getDeployTransaction(...constructorArgs).data; // 连接Polygon主网RPC节点(需提前在hardhat.config.js配置) const provider = new ethers.providers.JsonRpcProvider(network.config.url); // 获取签署人地址的当前nonce(pending状态避免重复) const nonce = await provider.getTransactionCount(DEPLOYER_ADDRESS, "pending"); // 估算gas上限 const gasLimit = await provider.estimateGas({ from: DEPLOYER_ADDRESS, data: deployTxData }); // 获取当前主网gas价格 const gasPrice = await provider.getGasPrice(); // 构建未签名交易对象 const unsignedTx = { chainId: CHAIN_ID, nonce: nonce, gasLimit: gasLimit.toHexString(), gasPrice: gasPrice.toHexString(), data: deployTxData, to: null, // 部署合约时to字段为空 value: ethers.utils.parseEther("0"), // 无需转账ETH则设为0 }; // 保存未签名交易到本地文件 fs.writeFileSync("unsigned-deploy-tx.json", JSON.stringify(unsignedTx, null, 2)); console.log("未签名交易已生成:unsigned-deploy-tx.json"); } main().catch(err => { console.error(err); process.exit(1); });
运行脚本前,确保hardhat.config.js中配置了Polygon主网的RPC节点(比如Alchemy/Infura的节点地址)。
步骤2:由目标所有者签署交易
将生成的unsigned-deploy-tx.json发送给签署人,对方可以通过两种方式签署:
方式1:MetaMask可视化签署(推荐,无需暴露私钥)
签署人可以用一个简单的前端页面完成签名:
- 创建HTML文件,引入ethers.js
- 读取
unsigned-deploy-tx.json内容 - 调用MetaMask的签名接口:
// 示例前端代码片段 const unsignedTx = JSON.parse(读取的文件内容); const provider = new ethers.providers.Web3Provider(window.ethereum); await provider.send("eth_requestAccounts", []); const signer = provider.getSigner(); const signedTx = await signer.signTransaction(unsignedTx); // 复制signedTx字符串发给你
方式2:离线私钥签署(签署人自行操作)
如果签署人愿意使用私钥,可以用以下脚本完成签名:
const { ethers } = require("ethers"); const fs = require("fs"); async function signTx() { const unsignedTx = JSON.parse(fs.readFileSync("unsigned-deploy-tx.json")); // 签署人的私钥(仅本人使用,绝对不能泄露) const privateKey = "0x签署人的私钥"; const wallet = new ethers.Wallet(privateKey); const signedTx = await wallet.signTransaction(unsignedTx); fs.writeFileSync("signed-deploy-tx.json", JSON.stringify({ signedTx }, null, 2)); console.log("已签名交易生成:signed-deploy-tx.json"); } signTx().catch(err => { console.error(err); process.exit(1); });
步骤3:广播已签名交易到Polygon主网
拿到签署后的交易字符串,用脚本广播到主网:
广播脚本(broadcast-signed-tx.js)
const { ethers, network } = require("hardhat"); const fs = require("fs"); async function main() { const { signedTx } = JSON.parse(fs.readFileSync("signed-deploy-tx.json")); const provider = new ethers.providers.JsonRpcProvider(network.config.url); // 广播交易 const txResponse = await provider.sendTransaction(signedTx); console.log(`交易已广播,哈希:${txResponse.hash}`); // 等待交易确认 await txResponse.wait(); console.log(`交易确认完成,合约地址:${txResponse.contractAddress}`); } main().catch(err => { console.error(err); process.exit(1); });
关键注意事项
- 签署人的钱包必须有足够的MATIC支付gas费
- 确保合约的
Ownable逻辑默认将部署者(签署人地址)设为初始所有者(比如OpenZeppelin的Ownable合约默认如此) - 生成未签名交易时,nonce必须准确,若期间签署人有其他交易,需要重新生成nonce
内容的提问来源于stack exchange,提问作者user2701487
相关产品推荐
相关产品推荐

