I have Caller and ERC721 contract just like this :
contract SampleToken is ERC721MetadataMintable {
string private name;
string private symbol;
constructor (address _creator, string _name, string _symbol, string _tokenURI)
ERC721MetadataMintable()
ERC721Metadata(_name, _symbol) public {
uint256 _tokenId = 0;
mintWithTokenURI(_creator, _tokenId, _tokenURI);
}
}
and I want this Caller to be able to transfer the NFT to the person who is msg.sender
. Caller behave like factory contract of FRC721 contract.
contract Caller {
mapping(uint256 => address) public ERC721Address;
using Address for address;
bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;
struct ERCs {
address owner;
}
ERCs[] public ercs;
function create(
string _name,
string _symbol,
string _tokenURI
) public returns(bool) {
ERCs memory _ercs = ERCs({
owner: msg.sender
});
uint256 contractId = ercs.push(_ercs) -1;
ERC721Address[contractId] = new SampleToken(msg.sender, _name, _symbol, _tokenURI);
return true;
}
function tokenTransferTo(
address _to,
uint256 _contractId,
uint256 _tokenId,
bytes _data
) public {
require(msg.sender == ownerAddress(_contractId, _tokenId), "You do not have a right to mint token.");
SampleToken(ERC721Address[_contractId]).setApprovalForAll(msg.sender, true);
safeTransferFrom(msg.sender, _to, _contractId, _tokenId, _data);
}
function ownerAddress(uint256 _contractId, uint256 _tokenId) public view returns(address) {
return SampleToken(ERC721Address[_contractId]).ownerOf(_tokenId);
}
function safeTransferFrom(
address _from,
address _to,
uint256 _contractId,
uint256 _tokenId,
bytes _data
) public {
SampleToken(ERC721Address[_contractId]).transferFrom(_from, _to, _tokenId);
// solium-disable-next-line arg-overflow
require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
}
function checkAndCallSafeTransfer(
address _from,
address _to,
uint256 _tokenId,
bytes _data
) internal returns (bool) {
if (!_to.isContract()) {
return true;
}
bytes4 retval = ERC721Holder(_to).onERC721Received(address(this), _from, _tokenId, _data);
return (retval == ERC721_RECEIVED);
}
}
Every time I try to call tokenTransferTo
after calling create()
function I get the error message like below. Does anyone knows what's wrong with this?
transact to Caller.tokenTransferTo errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value. Debug the transaction to get more information.
Best Answer
I guess there are no current solutions for this situation besides implementing Dapps layer to directly call
transferFrom(msg.sender, {Caller.contractAddress}, _tokenid)
from ERC721 contract side. Since it's always revert when checkingrequire(_isApprovedOrOwner(msg.sender, tokenId));
part.https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721.sol
So you should do as follows:
msg.sender
to caller contract address from ERC721 contract.msg.sender
with owner check ofERC721(address).ownerOf({contractAddress})