是否可以在 ERC721 合约中调用 ERC20 函数?
Is it possible to call a ERC20 function inside a ERC721 contract?
我想要实现的是从 ERC721 合约中的 ERC20 合约调用 transferFrom
,如下所示:
我的 ERC20 合约:
pragma solidity ^0.7.0;
import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
contract ERC20Token is IERC20 {
using SafeMath for uint256;
bytes32[] public candidateList;
uint public totalTokens;
uint public balanceTokens;
uint public tokenPrice;
// what is the voter address?
// total tokens purchased
// tokens voted per candidate
struct voter {
address voterAddress;
uint tokensBought;
uint256[] tokensUsedPerCandidate;
}
mapping(address => voter) public voterInfo;
mapping(bytes32 => uint256) public votesReceived;
string public symbol;
string public name;
uint8 public decimals;
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
symbol = "NCToken";
name = "NCSOFT TOKEN";
decimals = 0;
totalTokens = _totalTokens;
balanceTokens = _totalTokens;
tokenPrice = _tokenPrice;
candidateList = _candidateNames;
emit Transfer(address(0), msg.sender, totalTokens);
function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
balances[from] = SafeMath.sub(balances[from], tokens);
allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
balances[to] = SafeMath.add(balances[to], tokens);
emit Transfer(from, to, tokens);
return true;
}
}
我的 ERC721 合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
import "../openzeppelin-contracts/contracts/utils/Address.sol";
import "../openzeppelin-contracts/contracts/utils/Counters.sol";
import "./ERC20Token.sol";
contract NFTtoken is ERC721 {
using SafeMath for uint256;
using Address for address;
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
address payable public owner;
mapping(bytes4 => bool) supportedInterfaces;
mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
// mapping (uint256 => string) idToUri;
uint8 public decimals;
uint256[] public allValidTokenIds;
mapping(uint256 => uint256) private allValidTokenIndex;
string[] public allNFTNames;
struct NFT {
//uint NFTID;
string name;
address creator;
}
mapping(address => NFT) public nftInfo;
constructor() ERC721("NC NFT example", "NCNFT") {
owner = msg.sender;
decimals = 0;
}
function mint(string calldata nftName) external payable {
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
nftInfo[msg.sender].name = nftName;
nftInfo[msg.sender].creator = msg.sender;
allValidTokenIndex[newItemId] = allValidTokenIds.length;
allValidTokenIds.push(newItemId);
_tokenIds.increment();
}
function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
transferFrom(from, to, tokenId);
ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
}
function allNFTs() public view returns (uint256[] memory) {
return allValidTokenIds;
}
}
从 ERC721 调用 transferNFT
时的错误消息。
MetaMask - RPC Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token","code":-32000,"data":{"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f":{"error":"revert","program_counter":7889,"return":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000","reason":"ERC721: operator query for nonexistent token"},"stack":"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\Program Files\WindowsApps\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\app\resources\static\node\node_modules\ganache-core\lib\utils\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\Program Files\WindowsApps\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\app\resources\static\node\node_modules\ganache-core\lib\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}'
{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`}
code: -32603
message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
[[Prototype]]: Object
localhost/:1 Uncaught (in promise)
{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`, stack: '{\n "code": -32603,\n "message": "[ethjs-query] wh…gaeaoehlefnkodbefgpgknn/background-0.js:1:216902)'}
code: -32603
message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
stack: "{\n \"code\": -32603,\n \"message\": \"[ethjs-query] while formatting outputs from RPC '{\\"value\\":{\\"code\\":-32603,\\"data\\":{\\"message\\":\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\",\\"code\\":-32000,\\"data\\":{\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\":{\\"error\\":\\"revert\\",\\"program_counter\\":7889,\\"return\\":\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\",\\"reason\\":\\"ERC721: operator query for nonexistent token\\"},\\"stack\\":\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\",\\"name\\":\\"RuntimeError\\"}}}}'\",\n \"stack\": \"Error: [ethjs-query] while formatting outputs from RPC '{\\"value\\":{\\"code\\":-32603,\\"data\\":{\\"message\\":\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\",\\"code\\":-32000,\\"data\\":{\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\":{\\"error\\":\\"revert\\",\\"program_counter\\":7889,\\"return\\":\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\",\\"reason\\":\\"ERC721: operator query for nonexistent token\\"},\\"stack\\":\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\",\\"name\\":\\"RuntimeError\\"}}}}'\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)\"\n}\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)"
[[Prototype]]: Object
setTimeout (async)
(anonymous) @ inpage.js:1
write @ inpage.js:1
这是我的 javascript 文件,调用两个合约的函数。
// Import libraries we need.
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import voting_artifacts from '../../build/contracts/Voting.json'
import voting_artifacts2 from '../../build/contracts/DeedToken.json'
window.App = {
start: function() {
var self = this;
self.transferNFT();
},
transferNFT: function() {
NFTContract.deployed().then(function(contractInstance) {
let toAddress = $("#to-address").val();
let NFTid_temp = $("#nft-id").val();
let NFTid = NFTid_temp.substring(7);
contractInstance.transferFrom(web3.currentProvider.selectedAddress, toAddress, NFTid, {gas: 140000, from: web3.eth.accounts[0]});
})
}
}
window.addEventListener('load', async function() {
if (window.ethereum) {
await window.ethereum.send('eth_requestAccounts');
window.web3 = new Web3(window.ethereum);
}
else {
console.warn("No web3 detected.");
window.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
}
App.start();
});
为了与 ERC20 代币交互,您必须从所需的合约中创建它的实例。您需要将 ERC20 导入您的 nfts 合约,然后创建一个指向您的代币的 ERC20 代币实例。应该是这样的:
// Inside the nfts contract
ERC20 token = ERC20("your token address here");
然后您将能够与该令牌进行交互:
token.transferFrom("args");
希望此信息对您有用:)
如果您不想要合约的全部功能,您可以使用该界面。
您在项目中复制了完整代码。也许创建一个接口目录。然后将其导入您的合约:
import "../interfaces/IERC20.sol";
为了调用合同方法,您始终需要 ABI。由于您将文件导入到合约中,IERC721
将在您的合约中全局可用。为了调用 transferFrom
你需要传递 3 个参数。 “发件人地址”、“收件人地址”和金额。如何使用它的一个例子是这样的
function stakeTokens(uint256 _amount,address _token) public{
// add require staments
// IERC20(_token) this will initialize the contract
IERC20(_token).transferFrom(msg.sender,address(this),_amount);
}
我想要实现的是从 ERC721 合约中的 ERC20 合约调用 transferFrom
,如下所示:
我的 ERC20 合约:
pragma solidity ^0.7.0;
import "../openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
contract ERC20Token is IERC20 {
using SafeMath for uint256;
bytes32[] public candidateList;
uint public totalTokens;
uint public balanceTokens;
uint public tokenPrice;
// what is the voter address?
// total tokens purchased
// tokens voted per candidate
struct voter {
address voterAddress;
uint tokensBought;
uint256[] tokensUsedPerCandidate;
}
mapping(address => voter) public voterInfo;
mapping(bytes32 => uint256) public votesReceived;
string public symbol;
string public name;
uint8 public decimals;
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
constructor(uint256 _totalTokens, uint256 _tokenPrice, bytes32[] memory _candidateNames) {
symbol = "NCToken";
name = "NCSOFT TOKEN";
decimals = 0;
totalTokens = _totalTokens;
balanceTokens = _totalTokens;
tokenPrice = _tokenPrice;
candidateList = _candidateNames;
emit Transfer(address(0), msg.sender, totalTokens);
function transferFrom(address from, address to, uint256 tokens) public override returns (bool) { //This is the function I am trying to call from ERC721 contract
balances[from] = SafeMath.sub(balances[from], tokens);
allowed[from][msg.sender] = SafeMath.sub(allowed[from][msg.sender], tokens);
balances[to] = SafeMath.add(balances[to], tokens);
emit Transfer(from, to, tokens);
return true;
}
}
我的 ERC721 合约:
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "../openzeppelin-contracts/contracts/token/ERC721/IERC721.sol";
import "../openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
import "../openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol";
import "../openzeppelin-contracts/contracts/math/SafeMath.sol";
import "../openzeppelin-contracts/contracts/utils/Address.sol";
import "../openzeppelin-contracts/contracts/utils/Counters.sol";
import "./ERC20Token.sol";
contract NFTtoken is ERC721 {
using SafeMath for uint256;
using Address for address;
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
bytes32[] candidates = [bytes32('Rama'), bytes32('Nick'), bytes32('Jose')];
ERC20Token ERC20TokenContract = new ERC20Token(1000, 1, candidates); //instantiating an ERC20 contract
address payable public owner;
mapping(bytes4 => bool) supportedInterfaces;
mapping(uint256 => address) tokenOwners; //a mapping from NFT ID to the address that owns it
mapping(address => uint256) balances; //a mapping from NFT ID to the address that owns it
mapping(uint256 => address) allowance; //a mapping from NFT ID to approved address
mapping(address => mapping(address => bool)) operators; //Mapping from owner address to mapping of operator addresses.
// mapping (uint256 => string) idToUri;
uint8 public decimals;
uint256[] public allValidTokenIds;
mapping(uint256 => uint256) private allValidTokenIndex;
string[] public allNFTNames;
struct NFT {
//uint NFTID;
string name;
address creator;
}
mapping(address => NFT) public nftInfo;
constructor() ERC721("NC NFT example", "NCNFT") {
owner = msg.sender;
decimals = 0;
}
function mint(string calldata nftName) external payable {
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
nftInfo[msg.sender].name = nftName;
nftInfo[msg.sender].creator = msg.sender;
allValidTokenIndex[newItemId] = allValidTokenIds.length;
allValidTokenIds.push(newItemId);
_tokenIds.increment();
}
function transferNFT(address from, address to, uint256 tokenId) public returns (bool){
transferFrom(from, to, tokenId);
ERC20TokenContract.transferFrom(to, nftInfo[from].creator, 10);
//<-----***********This is throwing an error! I am trying to call ERC20Token.transferFrom.
}
function allNFTs() public view returns (uint256[] memory) {
return allValidTokenIds;
}
}
从 ERC721 调用 transferNFT
时的错误消息。
MetaMask - RPC Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token","code":-32000,"data":{"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f":{"error":"revert","program_counter":7889,"return":"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000","reason":"ERC721: operator query for nonexistent token"},"stack":"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\Program Files\WindowsApps\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\app\resources\static\node\node_modules\ganache-core\lib\utils\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\Program Files\WindowsApps\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\app\resources\static\node\node_modules\ganache-core\lib\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)","name":"RuntimeError"}}}}'
{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`}
code: -32603
message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
[[Prototype]]: Object
localhost/:1 Uncaught (in promise)
{code: -32603, message: `[ethjs-query] while formatting outputs from RPC '{…/task_queues.js:93:5)","name":"RuntimeError"}}}}'`, stack: '{\n "code": -32603,\n "message": "[ethjs-query] wh…gaeaoehlefnkodbefgpgknn/background-0.js:1:216902)'}
code: -32603
message: "[ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"message\":\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\",\"code\":-32000,\"data\":{\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\":{\"error\":\"revert\",\"program_counter\":7889,\"return\":\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\",\"reason\":\"ERC721: operator query for nonexistent token\"},\"stack\":\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\n at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\",\"name\":\"RuntimeError\"}}}}'"
stack: "{\n \"code\": -32603,\n \"message\": \"[ethjs-query] while formatting outputs from RPC '{\\"value\\":{\\"code\\":-32603,\\"data\\":{\\"message\\":\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\",\\"code\\":-32000,\\"data\\":{\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\":{\\"error\\":\\"revert\\",\\"program_counter\\":7889,\\"return\\":\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\",\\"reason\\":\\"ERC721: operator query for nonexistent token\\"},\\"stack\\":\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\",\\"name\\":\\"RuntimeError\\"}}}}'\",\n \"stack\": \"Error: [ethjs-query] while formatting outputs from RPC '{\\"value\\":{\\"code\\":-32603,\\"data\\":{\\"message\\":\\"VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\",\\"code\\":-32000,\\"data\\":{\\"0x0b5d04087c39a8caa2f730815e42f619d33c9d0c3b8682c8c01d3f1ecf0e7d0f\\":{\\"error\\":\\"revert\\",\\"program_counter\\":7889,\\"return\\":\\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e0000000000000000000000000000000000000000\\",\\"reason\\":\\"ERC721: operator query for nonexistent token\\"},\\"stack\\":\\"RuntimeError: VM Exception while processing transaction: revert ERC721: operator query for nonexistent token\\n at Function.RuntimeError.fromResults (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\utils\\\\runtimeerror.js:94:13)\\n at BlockchainDouble.processBlock (C:\\\\Program Files\\\\WindowsApps\\\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\\\app\\\\resources\\\\static\\\\node\\\\node_modules\\\\ganache-core\\\\lib\\\\blockchain_double.js:627:24)\\n at runMicrotasks (<anonymous>)\\n at processTicksAndRejections (internal/process/task_queues.js:93:5)\\",\\"name\\":\\"RuntimeError\\"}}}}'\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)\"\n}\n at new i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:148782)\n at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146325)\n at Object.internal (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:146935)\n at y.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:210928)\n at Object.h (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:18:35204)\n at u (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:117610)\n at y.a.emit (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/common-0.js:1:118146)\n at y._setTransactionStatus (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:46740)\n at y.setTxStatusFailed (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-1.js:1:45972)\n at B._failTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:225990)\n at B.approveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:217659)\n at async B.updateAndApproveTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background-0.js:1:216902)"
[[Prototype]]: Object
setTimeout (async)
(anonymous) @ inpage.js:1
write @ inpage.js:1
这是我的 javascript 文件,调用两个合约的函数。
// Import libraries we need.
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import voting_artifacts from '../../build/contracts/Voting.json'
import voting_artifacts2 from '../../build/contracts/DeedToken.json'
window.App = {
start: function() {
var self = this;
self.transferNFT();
},
transferNFT: function() {
NFTContract.deployed().then(function(contractInstance) {
let toAddress = $("#to-address").val();
let NFTid_temp = $("#nft-id").val();
let NFTid = NFTid_temp.substring(7);
contractInstance.transferFrom(web3.currentProvider.selectedAddress, toAddress, NFTid, {gas: 140000, from: web3.eth.accounts[0]});
})
}
}
window.addEventListener('load', async function() {
if (window.ethereum) {
await window.ethereum.send('eth_requestAccounts');
window.web3 = new Web3(window.ethereum);
}
else {
console.warn("No web3 detected.");
window.web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
}
App.start();
});
为了与 ERC20 代币交互,您必须从所需的合约中创建它的实例。您需要将 ERC20 导入您的 nfts 合约,然后创建一个指向您的代币的 ERC20 代币实例。应该是这样的:
// Inside the nfts contract
ERC20 token = ERC20("your token address here");
然后您将能够与该令牌进行交互:
token.transferFrom("args");
希望此信息对您有用:)
如果您不想要合约的全部功能,您可以使用该界面。
您在项目中复制了完整代码。也许创建一个接口目录。然后将其导入您的合约:
import "../interfaces/IERC20.sol";
为了调用合同方法,您始终需要 ABI。由于您将文件导入到合约中,IERC721
将在您的合约中全局可用。为了调用 transferFrom
你需要传递 3 个参数。 “发件人地址”、“收件人地址”和金额。如何使用它的一个例子是这样的
function stakeTokens(uint256 _amount,address _token) public{
// add require staments
// IERC20(_token) this will initialize the contract
IERC20(_token).transferFrom(msg.sender,address(this),_amount);
}