You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现自有NFT市场中用户BVC Token支付的钱包授权?

如何获取用户BVC Token权限完成NFT购买

首先,你当前合约里的授权逻辑完全搞反了:ERC20的授权是用户(Token持有者)主动授权给市场合约,允许合约从用户地址划转指定数量的Token,而不是合约给用户授权。下面是正确的实现方案:

一、核心流程说明

用户购买NFT时的正确流程是:

  1. 前端检查用户对市场合约的BVC Token授权额度是否≥NFT售价
  2. 如果授权额度不足,调用BVC Token合约的approve(address spender, uint256 amount)方法,让用户签名完成授权
  3. 授权完成后,调用市场合约的购买函数,由合约从用户地址划转Token完成交易

二、合约代码修正

你当前的n2DMarketSale和approveCRI函数存在严重逻辑错误,以下是修正后的关键代码:

1. 移除错误的授权函数

删除approveCRI和allowenceCRI函数,因为这两个函数的逻辑完全错误(合约不能给自己授权用户的Token),授权操作应该由前端直接调用BVC Token合约完成。

2. 修正购买函数n2DMarketSale

function n2DMarketSale(address nftContract, uint256 itemId, uint256 _pid) public nonReentrant {
    TokenInfo storage tokens = AllowedCrypto[_pid];
    IERC20 paytoken = tokens.paytoken;
    uint256 listingFee = tokens.listingFee;
    uint256 price = idToVaultItem[itemId].price; // 从VaultItem取对应NFT的价格,而非全局固定价格
    uint256 tokenId = idToVaultItem[itemId].tokenId;
    VaultItem storage item = idToVaultItem[itemId];

    require(!item.sold, "该NFT已售出");
    require(msg.sender != item.seller, "不能购买自己的NFT");
    // 检查用户授权额度是否足够覆盖售价
    require(paytoken.allowance(msg.sender, address(this)) >= price, "授权额度不足");
    // 检查用户Token余额是否足够
    require(paytoken.balanceOf(msg.sender) >= price, "Token余额不足");

    // 划转Token:用户 -> 卖家
    require(paytoken.transferFrom(msg.sender, item.seller, price), "向卖家转账失败");
    // 划转平台手续费:用户 -> 平台持有者
    require(paytoken.transferFrom(msg.sender, holder, listingFee), "手续费转账失败");

    // 转移NFT所有权
    IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId);
    item.holder = payable(msg.sender);
    item.sold = true;
    _itemsSold.increment();
}

3. 修正createVaultItem函数(优化建议)

当前函数固定使用TokenInfo里的价格,建议改成由卖家自定义价格,更符合NFT市场逻辑:

function createVaultItem(address nftContract, uint256 tokenId, uint256 _pid, uint256 customPrice) public nonReentrant {
    TokenInfo storage tokens = AllowedCrypto[_pid];
    IERC20 paytoken = tokens.paytoken;
    uint256 listingFee = tokens.listingFee;
    uint256 price = customPrice;

    require(price > 0, "价格不能为0");
    // 若listingFee收取BVC Token,替换msg.value逻辑为Token转账:
    // require(paytoken.allowance(msg.sender, address(this)) >= listingFee, "手续费授权不足");
    // require(paytoken.transferFrom(msg.sender, holder, listingFee), "手续费转账失败");

    _itemIds.increment();
    uint256 itemId = _itemIds.current();
    idToVaultItem[itemId] = VaultItem(itemId, nftContract, tokenId, payable(msg.sender), payable(address(0)), price, false);
    IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
    emit VaultItemCreated(itemId, nftContract, tokenId, msg.sender, address(0), price, false);
}

4. 修正withdraw函数

原函数逻辑错误,调整为仅允许owner提取合约内的Token:

function withdraw(uint256 _pid) public onlyOwner {
    TokenInfo storage tokens = AllowedCrypto[_pid];
    IERC20 paytoken = tokens.paytoken;
    uint256 balance = paytoken.balanceOf(address(this));
    require(balance > 0, "没有可提取的Token");
    require(paytoken.transfer(msg.sender, balance), "提取失败");
}

三、前端实现步骤

用户点击购买按钮时,前端需执行以下操作:

  1. 获取目标NFT的售价price、对应BVC Token合约地址及市场合约地址
  2. 调用BVC Token合约的allowance(userAddress, marketContractAddress)方法,检查当前授权额度
  3. 若授权额度 < 售价,调用BVC Token合约的approve(marketContractAddress, price)方法,触发用户钱包签名授权
  4. 等待授权交易上链确认后,调用市场合约的n2DMarketSale方法完成购买

示例前端伪代码:

async function buyNFT(nftContract, itemId, pid, price) {
  const bvcToken = new ethers.Contract(bvcAddress, bvcAbi, signer);
  const marketContract = new ethers.Contract(marketAddress, marketAbi, signer);

  // 检查授权额度
  const allowance = await bvcToken.allowance(signer.address, marketAddress);
  if (allowance.lt(price)) {
    // 发起授权请求
    const approveTx = await bvcToken.approve(marketAddress, price);
    await approveTx.wait();
  }

  // 执行NFT购买
  const buyTx = await marketContract.n2DMarketSale(nftContract, itemId, pid);
  await buyTx.wait();
  alert("NFT购买成功!");
}

四、注意事项

  • 确保你的BVC Token合约符合标准ERC20规范,已实现approve和transferFrom方法
  • 若平台手续费收取ETH,保留原msg.value逻辑;若收取BVC Token,需替换为Token转账逻辑
  • 合约中所有涉及Token操作的地方,需添加转账结果检查(require(transferResult, "转账失败")),避免异常情况

内容的提问来源于stack exchange,提问作者CRYPTO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 21:55:20