【发布时间】:2022-01-06 21:00:06
【问题描述】:
我正在编写一份合同,其中涉及将 ERC-721 令牌从一个用户转移到另一个用户。为了测试这是否适用于现有的 NFT 集合,我正在使用 ganache-cli 来分叉主网并模拟相关 ERC-721 令牌的持有者。我已在 Etherscan 上确认我正在解锁的地址确实是我尝试转移的 ERC-721 令牌的持有者。
首先,我正在使用 ganache-cli 分叉主网:
ganache-cli -f <INFURA_MAINNET_ENDPOINT> -d -i 66 1 --unlock <HOLDER_ADDRESS>
我的智能合约代码包括:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC721 {
function ownerOf(uint256 _tokenId) external returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
}
interface CryptopunkInterface {
function transferPunk(address _to, uint _tokenId) external;
}
并包含此功能:
/// @dev Sells NFT into a bid (i.e., "hits" the bid)
/// @param _bidderAddress Address of the bidder
/// @param _nftAddress Address of collection to which the bid applies
/// @param _tokenId Token id of the NFT in question
/// @param _expectedWeiPriceEach Price (in wei) that seller expects to receive for each NFT
/// @return Proceeds remitted to seller
function hitBid(address _bidderAddress, address _nftAddress, uint256 _tokenId, uint256 _expectedWeiPriceEach) public returns (uint256) {
console.log("msg.sender of hitBid: ", msg.sender);
// Initialize bid
Bid memory bid = bids[_bidderAddress][_nftAddress];
// Require that bid exists
require(bid.quantity > 0, "This bid does not exist.");
// Require that bid amount is at least what the seller expects
require(bid.weiPriceEach >= _expectedWeiPriceEach, "Bid is insufficient.");
// Decrement bidder's bid quantity for this collection
bids[_bidderAddress][_nftAddress].quantity = bid.quantity - 1;
// Compute platform fee proceeds
uint256 platformFeeProceeds = bid.weiPriceEach * platformFee / 10000;
// Remit platform fee proceeds to owner
sendValue(OWNER, platformFeeProceeds);
// Transfer NFT to bidder
// Check whether _nftAddress is Cryptopunks address
if (_nftAddress == 0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB) {
CryptopunkInterface(_nftAddress).transferPunk(_bidderAddress, _tokenId);
} else {
console.log("ownerOf NFT being sold: ", IERC721(_nftAddress).ownerOf(_tokenId));
IERC721(_nftAddress).safeTransferFrom(msg.sender, _bidderAddress, _tokenId);
}
// Compute seller proceeds
uint256 sellerProceeds = bid.weiPriceEach - platformFeeProceeds;
// Remit seller proceeds to seller
sendValue(payable(msg.sender), sellerProceeds);
// Emit new trade event
emit NewTrade(_bidderAddress, msg.sender, _nftAddress, bid.weiPriceEach, 1, _tokenId);
// Return seller proceeds
return sellerProceeds;
}
当我运行 truffle 测试,代表解锁的持有者地址执行函数时,我收到此错误:
Error: Returned error: VM Exception while processing transaction: revert ERC721: transfer caller is not owner nor approved -- Reason given: ERC721: transfer caller is not owner nor approved.
更新:
我从使用 ganache-cli 切换到使用 Hardhat 来分叉主网。我正在模拟我的 test.js 文件中的相关地址:
const BAYC_HOLDER_ADDRESS = "0x54BE3a794282C030b15E43aE2bB182E14c409C5e";
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [BAYC_HOLDER_ADDRESS],
});
我还通过上面的 console.log 语句验证了 hitBid 的 msg.sender 确实是相关 NFT 的所有者。
msg.sender of hitBid: 0x54be3a794282c030b15e43ae2bb182e14c409c5e
ownerOf NFT being sold: 0x54be3a794282c030b15e43ae2bb182e14c409c5e
尽管如此,我仍然遇到同样的错误:
Error: VM Exception while processing transaction: reverted with reason string 'ERC721: transfer caller is not owner nor approved'
【问题讨论】: