我有两个单独部署的合同。
第一合约.sol
contract FirstContract is ERC721 {
using Counters for Counters.Counter;
Counters.Counter public _id;
constructor(address admin) ERC721("Token Name", "TOKEN") {
}
function incrementToken() public {
_id.increment();
}
function currentToken() public view returns (uint256) {
return _id.current();
}
function mint(address to, uint256 tokenId) public {
_mint(to, tokenId);
}
}
第二合约.sol
import "./FirstContract.sol";
contract SecondContract {
FirstContract firstContract;
constructor(address _address) {
firstContract = FirstContract(_address);
}
// Mint a token to msg.sender
function createToken() external {
firstContract.incrementToken();
uint256 newTokenId = firstContract.currentToken();
firstContract.mint(msg.sender, newTokenId);
}
// Transfer the ownership of the token
function transferToken(from address, address to, uint256 tokenId) external {
// Error here. transferFrom is the method inherited from ERC721
firstContract.transferFrom(from, to, tokenId);
}
}
createToken使用in铸造令牌后SecondContract,当我调用 时transferToken,出现以下错误:
ERC721:转接呼叫者既不是所有者也不是批准的
这很可能是因为SecondContract调用msg.sender时transferFrom是tx.origin令牌的实际所有者。我尝试批准SecondContract作为一次性操作员通过 传输令牌approve(address(this), tokenId),但仍然遇到相同的错误。我也尝试过approve(address(firstContract), tokenId)or setApproveForAll(address(firstContract), true),但结果相同。
完成这项工作的唯一方法是如果我使用_transferin FirstContract:
function transferByAnybody(address from, address to, uint256 tokenId) public {
_transfer(from, to, tokenId);
}
并从以下位置调用该方法SecondContract:
function transferToken(from address, address to, uint256 tokenId) external {
firstContract.transferByAnybody(from, to, tokenId);
}
这不太理想,因为无论您是否是代币的所有者,任何人都可以调用 transfer 方法。