简体   繁体   中英

Unexpected msg.sender in onERC721Received

I have an auction contract with a constructor like following:

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

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

I have enabled the contract to receive tokens using 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;
}

Following is how I mint tokens:

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;
    }
}

The idea is that whomever deploys the auction contract should be the only one that can transfer a token into the auction contract.

The problem is that even though I'm using the same account I've deployed the auction contract with to mint a new token, I get the error Only the beneficiary can transfer the token into the auction. from the onERC721Received method when I try to use the constructor function to mint and transfer the token to the auction contract.

I wasn't sure if msg.sender becomes MyMintingContract since it's the immediate one that's calling the onERC721Received method, but when I checked Remix, it showed the account that called the mintToken to be from (which is the same account I've used to deploy the auction contract), which means it should coincide with the beneficiary variable.

在此处输入图片说明

If I query the beneficiary variable, I get 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 which is the same as the address in from from the image above. Am I correct in assuming that msg.sender is the same as from ?

In a given context, msg.sender points to immediate parent (caller of current contract) in call-chain, and tx.origin points to the root (entry-point) of call-chain.

Consider a call chain:

user
  contract A
    contract B
      contract C

For context of contract C, msg.sender is contract B and tx.origin is user.

from value in your screenshot is tx.origin , but not necessarily msg.sender (it's the msg.sender of contract A only).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM