如何预部署LensHub依赖的带构造参数的合约并保持原合约完整性?
部署LensHub合约的解决方案(保留原合约完整性)
问题背景
我需要部署LensHub智能合约,但它依赖的ERC721Enumerable相关合约需要构造函数参数初始化。LensHub只能在部署后调用initialize完成初始化,不预部署依赖合约的话部署会失败。我不想通过继承IERC721Enumerable并在构造函数初始化的方式解决,希望完全保留原合约结构用于测试。
可行解决方案
方案1:预部署最小化Mock合约(推荐)
直接预部署一个符合IERC721Enumerable接口的Mock合约,不需要完整功能,只要满足构造函数参数要求且接口匹配即可。这样既满足LensHub构造函数的参数校验,又不会改动原合约逻辑。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol"; contract MockERC721Enumerable is IERC721Enumerable { string public name; string public symbol; constructor(string memory name_, string memory symbol_) { name = name_; symbol = symbol_; } // 空实现满足接口要求,测试时按需扩展 function totalSupply() external pure returns (uint256) { return 0; } function tokenOfOwnerByIndex(address, uint256) external pure returns (uint256) { revert("Mock: Not implemented"); } function tokenByIndex(uint256) external pure returns (uint256) { revert("Mock: Not implemented"); } // 实现IERC721基础接口(因IERC721Enumerable继承自它) function balanceOf(address) external pure returns (uint256) { return 0; } function ownerOf(uint256) external pure returns (address) { revert("Mock: Not implemented"); } function safeTransferFrom(address, address, uint256) external pure { revert("Mock: Not implemented"); } function transferFrom(address, address, uint256) external pure { revert("Mock: Not implemented"); } function approve(address, uint256) external pure { revert("Mock: Not implemented"); } function getApproved(uint256) external pure returns (address) { revert("Mock: Not implemented"); } function setApprovalForAll(address, bool) external pure { revert("Mock: Not implemented"); } function isApprovedForAll(address, address) external pure returns (bool) { return false; } function safeTransferFrom(address, address, uint256, bytes calldata) external pure { revert("Mock: Not implemented"); } function name() external view returns (string memory) { return name; } function symbol() external view returns (string memory) { return symbol; } function tokenURI(uint256) external pure returns (string memory) { revert("Mock: Not implemented"); } }
部署Mock合约时传入任意合法的name和symbol参数,将返回的地址作为LensHub构造函数的followNFTImpl和collectNFTImpl参数传入,即可完成LensHub部署。测试时若需要真实功能,可重新部署替换地址。
方案2:工厂合约一键部署依赖+LensHub
编写工厂合约,在同一个交易内先部署所需的ERC721Enumerable合约,再用返回地址部署LensHub并完成初始化,全程无需修改原LensHub合约。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./LensHub.sol"; import "./YourERC721Enumerable.sol"; // 导入你的目标ERC721合约 contract LensHubFactory { event LensHubDeployed(address indexed lensHub, address followNFT, address collectNFT); function deployLensHub( string calldata followNFTName, string calldata followNFTSymbol, string calldata collectNFTName, string calldata collectNFTSymbol, string calldata lensHubName, string calldata lensHubSymbol, address governance ) external returns (address) { // 1. 部署Follow NFT合约 YourERC721Enumerable followNFT = new YourERC721Enumerable(followNFTName, followNFTSymbol); // 2. 部署Collect NFT合约 YourERC721Enumerable collectNFT = new YourERC721Enumerable(collectNFTName, collectNFTSymbol); // 3. 部署LensHub LensHub lensHub = new LensHub(address(followNFT), address(collectNFT)); // 4. 初始化LensHub lensHub.initialize(lensHubName, lensHubSymbol, governance); emit LensHubDeployed(address(lensHub), address(followNFT), address(collectNFT)); return address(lensHub); } }
调用工厂合约的deployLensHub函数,传入所有必要参数即可一次性完成所有部署流程。
方案3:测试框架脚本自动处理(针对测试场景)
如果是在Hardhat/Truffle等测试环境中,可通过部署脚本按顺序自动部署依赖合约,再传入地址部署LensHub。以Hardhat为例:
const hre = require("hardhat"); async function main() { // 部署Follow NFT合约 const FollowNFT = await hre.ethers.getContractFactory("YourERC721Enumerable"); const followNFT = await FollowNFT.deploy("FollowNFT", "FOLLOW"); await followNFT.deployed(); // 部署Collect NFT合约 const CollectNFT = await hre.ethers.getContractFactory("YourERC721Enumerable"); const collectNFT = await CollectNFT.deploy("CollectNFT", "COLLECT"); await collectNFT.deployed(); // 部署LensHub const LensHub = await hre.ethers.getContractFactory("LensHub"); const lensHub = await LensHub.deploy(followNFT.address, collectNFT.address); await lensHub.deployed(); // 初始化LensHub await lensHub.initialize("LensHub", "LENS", "0xYourGovernanceAddress"); console.log(`LensHub deployed to ${lensHub.address}`); } main().catch((error) => { console.error(error); process.exitCode = 1; });
这种方式完全不需要修改合约,仅通过脚本控制部署顺序,适配测试场景的快速迭代需求。
内容的提问来源于stack exchange,提问作者havendewart.eth
相关产品推荐
相关产品推荐

