如何将NFT合约的铸造买家地址数组传递至其他合约?
解决方案
1. 修改NFT合约,收集铸造地址
首先在你的NFT合约中添加存储铸造者地址的数组,并在铸造逻辑里记录地址:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract Nft is ERC721 { string public constant TOKEN_URI = "ipfs://..."; uint256 private s_tokenCounter; // 存储所有铸造过NFT的地址数组 address[] public s_minters; // 可选:用于去重的mapping,避免同一地址重复存入数组 mapping(address => bool) public hasMinted; constructor() ERC721("NFT", "NFT") { s_tokenCounter = 0; } function mintNft() public { s_tokenCounter += 1; _safeMint(msg.sender, s_tokenCounter); // 若不需要去重,直接push即可;需要去重则加判断 if (!hasMinted[msg.sender]) { hasMinted[msg.sender] = true; s_minters.push(msg.sender); } } function tokenURI(uint256 tokenId) public view override returns (string memory) { return TOKEN_URI; } function getTokenCounter() public view returns (uint256) { return s_tokenCounter; } // 获取完整的铸造者地址数组 function getAllMinters() public view returns (address[] memory) { return s_minters; } // 获取数组长度,方便分批读取(避免大数组一次性读取消耗过多gas) function getMintersCount() public view returns (uint256) { return s_minters.length; } }
2. 编写目标合约,读取NFT合约的地址列表
目标合约通过导入NFT合约的定义,传入已部署的NFT合约地址后,就能调用其getter函数获取地址数组:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; // 导入同目录下的NFT合约文件 import "./Nft.sol"; contract TargetContract { Nft public nftContract; // 构造函数传入已部署的NFT合约地址 constructor(address _nftContractAddress) { nftContract = Nft(_nftContractAddress); } // 示例:读取所有铸造者地址并执行自定义逻辑 function processMinterAddresses() public { address[] memory minters = nftContract.getAllMinters(); // 遍历地址执行操作,这里替换为你的业务逻辑 for (uint256 i = 0; i < minters.length; i++) { address minter = minters[i]; // 示例逻辑:比如给地址发代币、记录到合约存储等 // do something with minter... } } // 可选:按索引单独获取铸造者地址(适合分批处理大数组) function getMinterAtIndex(uint256 index) public view returns (address) { require(index < nftContract.getMintersCount(), "Index out of bounds"); return nftContract.s_minters(index); } }
3. 部署与调用步骤
- 先部署修改后的
Nft合约,记录其部署地址。 - 部署
TargetContract合约,构造函数传入刚才的NFT合约地址。 - 调用
Nft合约的mintNft函数进行铸造,地址会自动被记录。 - 调用
TargetContract的processMinterAddresses函数,即可读取并处理所有铸造者地址。
额外方案:NFT主动推送地址到目标合约
如果需要NFT合约在铸造时直接把地址推送给目标合约,可以修改NFT合约添加主动调用逻辑:
// 在Nft合约中新增 TargetContract public targetContract; // 设置目标合约地址(仅合约所有者可调用,建议添加权限控制) function setTargetContract(address _target) public { targetContract = TargetContract(_target); } // 修改mintNft函数 function mintNft() public { s_tokenCounter += 1; _safeMint(msg.sender, s_tokenCounter); if (!hasMinted[msg.sender]) { hasMinted[msg.sender] = true; s_minters.push(msg.sender); // 主动调用目标合约的接收方法 targetContract.receiveMinter(msg.sender); } }
同时在目标合约中添加接收方法:
// 在TargetContract中新增 address[] public storedMinters; function receiveMinter(address minter) external { // 验证调用者是NFT合约,防止恶意调用 require(msg.sender == address(nftContract), "Only NFT contract can call"); storedMinters.push(minter); }
内容的提问来源于stack exchange,提问作者Andrew Novikoff
相关产品推荐
相关产品推荐

