如何实现智能合约支持ERC20代币替代ETH支付NFT铸造费用
NFT合约新增ERC20支付铸造渠道开发配置指南
合约层改造
- 引入必要依赖
直接用OpenZeppelin的标准组件,不用自己重复造轮子:
其中import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol";SafeERC20用来兼容非标准ERC20代币(比如USDT这类老合约不返回成功布尔值),Ownable做管理权限控制,ReentrancyGuard防重入攻击。 - 新增状态变量
using SafeERC20 for IERC20; // 支持的支付代币映射:key为ERC20合约地址,value为是否支持 mapping(address => bool) public supportedPaymentTokens; // 各支付代币对应的单NFT铸造价格,单位为对应代币的最小精度 mapping(address => uint256) public mintPricePerToken; // 收款国库地址,所有铸造收入直接打该地址,不留在NFT合约内 address public treasury; - 保留原有ETH支付的mint逻辑不动,避免影响已有功能,单独新增ERC20支付的铸造函数:
function mintWithERC20(address paymentToken, uint256 quantity) external nonReentrant { // 基础校验:代币在支持列表、铸造数量不超总上限、数量不为0 require(supportedPaymentTokens[paymentToken], "Payment token not accepted"); require(quantity > 0 && totalSupply() + quantity <= MAX_SUPPLY, "Invalid mint quantity"); // 计算应付总金额 uint256 totalPayment = mintPricePerToken[paymentToken] * quantity; // 直接从用户地址转代币到国库,不经过合约中转 IERC20(paymentToken).safeTransferFrom(msg.sender, treasury, totalPayment); // 复用原有ETH铸造的NFT发放逻辑,给用户转对应数量的NFT _mintBatchTo(msg.sender, quantity); } - 新增仅合约所有者可调用的管理函数:
- 配置支持的支付代币和对应价格:设置时必须核对代币小数精度,比如USDC精度为6,若单NFT价格为10U,对应价格值要填
10 * 10**6,填错会直接导致定价错误被薅。 - 更新国库地址:避免地址私钥丢失后无法接收资金。
- (可选)新增紧急提现函数:万一有用户误转代币到合约,能由owner提到国库。
- 配置支持的支付代币和对应价格:设置时必须核对代币小数精度,比如USDC精度为6,若单NFT价格为10U,对应价格值要填
测试与上线配置要点
- 测试阶段优先fork主网环境验证,必须覆盖USDT、USDC、DAI等主流非标准/标准ERC20代币的支付流程,重点测授权、转账、NFT到账全链路,别等上线才发现某类代币转不了。
- 前端交互要加两个提示:一是ERC20支付需要用户先给NFT合约授权对应消费额度,建议默认授权当次支付的精准金额,不要引导用户无限授权,降低用户资产风险;二是明确标注不同代币的支付价格,避免用户付错。
- 上线后前20笔铸造手动核对国库地址的资金到账情况,确认代币收款金额、NFT发放数量都对得上,再放开大规模铸造。
高频踩坑提醒
- 不要图省事把ERC20支付逻辑硬塞进原有的
payablemint函数,很容易搞混msg.value判断逻辑,出现免费铸造、多扣钱的问题。 - 不要用原生的
transferFrom方法转ERC20,必须用SafeERC20的safeTransferFrom,不然碰到不返回布尔值的非标准代币会直接交易失败。 - 不要把铸造收入留在NFT合约里,收款直接打多签控制的国库地址,减少合约被攻击时的资金损失。
- 不要硬写死各代币的铸造价格,留好owner调整价格的入口,方便根据币价波动、运营需求调整定价。
内容的提问来源于stack exchange,提问作者anibe
相关产品推荐
相关产品推荐

