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.sender
as the first argument to functionsafeMint
, not as its actual caller! What made you think it would somehow "become" themsg.sender
when that function is called? For example, what did you think would happen to the second argument that you are passing? – goodvibration Sep 3 '20 at 16:52msg.sender
) and call youronlyOwner
protected function. – goodvibration Sep 3 '20 at 16:54contract A
to be the owner of the contract which implements this function, then you need to create that contract from a function incontract A
. – goodvibration Sep 3 '20 at 16:57