【问题标题】:How do you transfer an ERC-721 token using an impersonated address on an Ethereum mainnet fork?如何使用以太坊主网分叉上的模拟地址转移 ERC-721 代币?
【发布时间】: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'

【问题讨论】:

    标签: ethereum solidity


    【解决方案1】:

    您收到此错误的原因是因为 hitBid() 的 msg.sender 与 IERC721(_nftAddress).safeTransferFrom() 的 msg.sender 不同。

    卖家需要签署两笔交易:

    1. 用户需要签署approve(yourContractAddress, tokenId)
    2. 用户需要签署hitBid()

    这将阻止 hitBid() 恢复,因为您的合约地址(safeTransferFrom() 的 msg.sender)将被批准进行转移。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-17
      • 2022-01-23
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 2018-05-17
      • 2018-01-03
      • 1970-01-01
      相关资源
      最近更新 更多