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).