1

我有两个单独部署的合同。

第一合约.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.sendertransferFromtx.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 方法。

4

0 回答 0