I'm trying to mint an NFT token in contract B by calling a method on contract A, but I want msg.sender (in contract B) to be the address that calls the function on A, not contract A's address.
I thought this should work, but it doesn't. (it reverts on onlyOwner(), etherscan says: Although one or more Error Occurred [Reverted] Contract Execution Completed)
What am I doing wrong here? If I remove onlyOwner on safeMint, it works. So it's definitely a problem with delegatecall. Any help appreciated. Thanks.
contract A {
using Counters for Counters.Counter;
using SafeMath for uint256;
Counters.Counter private _tokenIds;
address public nftContract;
constructor(address _nftContract) public {
nftContract = _nftContract;
}
function mintItem() public returns (uint256) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
nftContract.delegatecall(abi.encodeWithSignature("safeMint(address,uint256)",msg.sender,newItemid));
}
}
contract B is ERC721 {
address public owner;
modifier onlyOwner() {
require(owner == msg.sender, "Ownable: caller is not the owner");
_;
}
constructor(string memory name,string memory ticker,string memory uri) ERC721(name,ticker) public {
owner = msg.sender;
_setBaseURI(uri);
}
function safeMint(address to, uint256 tokenId) public onlyOwner{
_mint(to, tokenId);
}
}
msg.senderas the first argument to functionsafeMint, not as its actual caller! What made you think it would somehow "become" themsg.senderwhen that function is called? For example, what did you think would happen to the second argument that you are passing? – goodvibration Sep 03 '20 at 16:52msg.sender) and call youronlyOwnerprotected function. – goodvibration Sep 03 '20 at 16:54contract Ato be the owner of the contract which implements this function, then you need to create that contract from a function incontract A. – goodvibration Sep 03 '20 at 16:57msg.sender). Hope you understand that, because it's a pretty fundamental concept in the Ethereum blockchain. – goodvibration Sep 03 '20 at 17:05