Solidity
如何使用外部合約向 msg.sender 發送 ERC721 代幣?
我有 Caller 和 ERC721 契約,就像這樣:
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); } }
我希望這個來電者能夠將 NFT 轉移給
msg.sender
. 呼叫者的行為類似於 FRC721 合約的工廠合約。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); } }
每次我
tokenTransferTo
在呼叫create()
函式後嘗試呼叫時,都會收到如下錯誤消息。有誰知道這有什麼問題?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.
transferFrom(msg.sender, {Caller.contractAddress}, _tokenid)
我想除了實現 Dapps 層直接從 ERC721 合約端呼叫之外,目前還沒有針對這種情況的解決方案。require(_isApprovedOrOwner(msg.sender, tokenId));
因為它總是在檢查零件時恢復。https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC721/ERC721.sol
因此,您應該執行以下操作:
- 將代幣從
msg.sender
ERC721 合約轉移到呼叫者合約地址。- 將代幣從合約地址轉移到
msg.sender
所有者檢查ERC721(address).ownerOf({contractAddress})