onERC721Received 中出现意外 msg.sender

Unexpected msg.sender in onERC721Received

我与构造函数有如下拍卖合同:

address payable public beneficiary;
ERC721 nftContract;
bool tokenAdded;
uint256 public tokenId;

constructor() public payable {
    beneficiary = msg.sender;
}

我已启用合约以使用 safeTransferFrom:

接收代币
function onERC721Received(address, address _from, uint256 _tokenId, bytes memory) public virtual override returns (bytes4) {
    require(beneficiary == _from, "Only the beneficiary can transfer the token into the auction.");
    require(tokenAdded == false, "The auction already has a token.");
    
    nftContract = ERC721(msg.sender);
    tokenId = _tokenId;
    tokenAdded = true;
    return this.onERC721Received.selector;
}

以下是我铸造代币的方式:

pragma solidity ^0.8.0;

import "./ERC721.sol";
import "./Counters.sol";

contract MyMintingContract is ERC721 {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor() ERC721("MyToken", "MTK") {}

    function mintToken(address receiver) external returns (uint256) {
        _tokenIds.increment();

        uint256 newTokenId = _tokenIds.current();
        _safeMint(receiver, newTokenId);

        return newTokenId;
    }
}

这个想法是,无论谁部署拍卖合约,都应该是唯一可以将代币转移到拍卖合约中的人。

问题是,即使我使用部署拍卖合约的同一个帐户来铸造新代币,我从 onERC721Received 方法中得到错误 Only the beneficiary can transfer the token into the auction.我尝试使用构造函数来铸造代币并将代币转移到拍卖合约中。

我不确定 msg.sender 是否变为 MyMintingContract,因为它是调用 onERC721Received 方法的直接方法,但是当我检查 Remix 时,它显示了调用该方法的帐户mintToken 变为 from(这是我用来部署拍卖合约的同一个帐户),这意味着它应该与 beneficiary 变量重合。

如果我查询 beneficiary 变量,我得到 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 与上图中 from 中的地址相同。我假设 msg.senderfrom 相同是否正确?

在给定的上下文中,msg.sender 指向调用链中的直接父级(当前合约的调用者),tx.origin 指向调用链的根(入口点)。

考虑一个调用链:

user
  contract A
    contract B
      contract C

对于合同 C 的上下文,msg.sender 是合同 B,tx.origin 是用户。

from 截图中的值是tx.origin,但不一定是msg.sender(它只是合同A的msg.sender)。