我有两个单独部署的合同。
第一合约.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)
,但结果相同。
完成这项工作的唯一方法是如果我使用_transfer
in 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 方法。