chi*_*ro2 7 ethereum solidity ether
我正在按照此处的文档进行操作:https://docs.alchemyapi.io/alchemy/tutorials/how-to-create-an-nft/how-to-mint-a-nft。并拥有以下形式的智能合约:
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract NFTA is ERC721, Ownable {
using Counters for Counters.Counter;
Counters.Counter public _tokenIds;
mapping (uint256 => string) public _tokenURIs;
mapping(string => uint8) public hashes;
constructor() public ERC721("NFTA", "NFT") {}
function mintNFT(address recipient, string memory tokenURI)
public onlyOwner
returns (uint256)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试用这个来估计天然气成本时minting:
const MY_PUBLIC_KEY = '..'
const MY_PRIVATE_KEY = '..'
const ALCHEMY = {
http: '',
websocket:'',
}
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
const web3 = createAlchemyWeb3(ALCHEMY.http);
const NFTA = require("../artifacts/contracts/OpenSea.sol/NFTA.json");
const address_a = '0x...';
const nft_A = new web3.eth.Contract(NFTA.abi, address_a);
async function mint({ tokenURI, run }){
const nonce = await web3.eth.getTransactionCount(MY_PUBLIC_KEY, 'latest');
const fn = nft_A.methods.mintNFT(MY_PUBLIC_KEY, '')
console.log( 'fn: ', fn.estimateGas() )
}
mint({ tokenURI: '', run: true })
Run Code Online (Sandbox Code Playgroud)
我收到错误:
(node:29262) UnhandledPromiseRejectionWarning: Error: Returned error: execution reverted: Ownable: caller is not the owner
Run Code Online (Sandbox Code Playgroud)
大概是因为mintNFT是public onlyOwner。但是,当我检查 Etherscan 时,该From字段与 相同MY_PUBLIC_KEY,并且我不确定还可以做什么来签署来自 的交易MY_PUBLIC_KEY。解决这个问题的简单方法是删除onlyOwnerfrom function mintNFT,一切都会按预期运行。但是假设我们想保留onlyOwner,除了上面已经写的内容之外,我将如何签署交易。
请注意,我正在用来hardHat编译合约并部署它们。即:npxhardhat编译npxhardhat运行脚本/deploy.js
===============================================
附录
alchemy 给出的部署 mint 的确切代码是:
async function mintNFT(tokenURI) {
const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //get latest nonce
//the transaction
const tx = {
'from': PUBLIC_KEY,
'to': contractAddress,
'nonce': nonce,
'gas': 500000,
'data': nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI()
};
Run Code Online (Sandbox Code Playgroud)
请注意,交易中的from字段为,与部署合约的字段PUBLIC_KEY相同,在本例中已指定。这正是我所做的。那么从概念上来说谁拥有这个 NFT 代码呢?在etherscan上,它是地址(合约地址),或者是我的公钥的地址,部署合约的地址,以及调用mint的地址,现在由于调用者不是所有者错误而失败。PUBLIC_KEYnftContractpublic onlyOwnertofrom
搜索互联网,我看到其他人在这里遇到了这个问题: https: //ethereum.stackexchange.com/questions/94114/erc721-testing-transferfrom,因为Truffle你可以用额外的字段指定调用者:
await nft.transferFrom(accounts[0], accounts[1], 1, { from: accounts[1] })
Run Code Online (Sandbox Code Playgroud)
此处无法选择额外参数,因为我使用的是安全帽。
OpenZeppelin 的Ownable.sol将默认owner值定义为合约部署者。您可以稍后通过致电transferOwnership()或放弃所有者来更改它(即设置为0x0)renounceOwnership()。
onlyOwner如果当前 未发送交易,则修改器将恢复该交易owner。(见代码)
因此,您需要mintNFT()从部署合约的同一地址调用该函数,因为这是当前的owner. 或者您可以更改owner或者您可以通过致电transferOwnership()(从当前owner一个。
onlyOwner从函数中删除修饰符mintNFT()将允许任何人调用该函数。