Solidity NFT合约如何实现指定ID作品预约铸造及权限管控
该需求完全可以实现,两种常用实现方案如下
方案1:预约预留模式(匹配你提出的地址绑定固定作品编号的需求)
你描述的钱包地址对应预留作品编号的逻辑,直接通过Solidity的映射类型就能实现:
- 首先在合约中定义两个映射变量:
- 地址到预留ID的映射:
mapping(address => uint256) public userReservedId,用于存储每个地址被分配的可铸造编号 - 编号预留状态映射:
mapping(uint256 => bool) public idIsReserved,用于避免同一个编号被分配给多个地址
- 地址到预留ID的映射:
- 管理员可以通过专属的权限控制方法,提前给指定地址绑定预留编号,绑定前校验该编号未被预留、未被铸造即可
- 改写mint方法,要求用户调用时传入想要铸造的作品编号,合约执行以下校验逻辑:
- 校验当前调用者的预留编号是否和传入的编号一致,不一致直接抛出错误
- 校验该编号未被铸造
- 校验其他通用铸造条件(如支付金额、铸造时间等)
- 校验通过后执行铸造,同时清空该用户的预留记录,避免重复铸造
简化版mint方法示例:
function mint(uint256 targetTokenId) external payable { require(userReservedId[msg.sender] == targetTokenId, "No permission to mint this token"); require(_exists(targetTokenId) == false, "Token has been minted"); require(msg.value >= publicMintPrice, "Insufficient payment"); _safeMint(msg.sender, targetTokenId); delete userReservedId[msg.sender]; idIsReserved[targetTokenId] = false; }
方案2:无预约直接指定ID铸造
如果不需要提前做地址和编号的绑定,仅支持用户自选未被铸造的编号铸造,逻辑更简单:
- 直接在mint方法中增加入参
uint256 targetTokenId - 校验该编号在发行总量范围内、未被铸造,满足通用铸造条件即可执行铸造
注意事项
- 无论用哪种方案,都必须做好tokenId的唯一性校验,避免出现重复铸造的漏洞
- 预约模式下可以根据需求扩展功能,比如给预留设置有效期,到期后未铸造的编号自动释放回公共铸造池
- 可以兼容原有顺序铸造的逻辑:无预留的普通用户仍按默认顺序铸造,有预留的用户仅能铸造自己的指定编号
内容的提问来源于stack exchange,提问作者Sowam
相关产品推荐
相关产品推荐

