我正在按照这里的文档进行操作: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;
}
}
当我尝试使用以下代码估算“铸造”所需的燃气成本时:
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 })
我收到错误:
(node:29262) UnhandledPromiseRejectionWarning: Error: Returned error: execution reverted: Ownable: caller is not the owner
由于
mintNFT
是public onlyOwner
,所以可能会出现这种情况。但是,当我检查Etherscan时,From
字段与MY_PUBLIC_KEY
相同,我不确定还能做什么来将交易标记为来自MY_PUBLIC_KEY
。解决这个问题的简单方法是从function mintNFT
中删除onlyOwner
,然后一切都按预期运行。但是假设我们想保留onlyOwner
,我该如何签署交易超出上面已经写的内容呢?注意,我使用
hardHat
编译合同并部署它们。即:
npx hardhat compile
npx hardhat run scripts/deploy.js
=============================================
附录
炼金术提供的精铸部署代码如下:
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()
};
请注意,在交易中,
from
字段是PUBLIC_KEY
,与部署合同的相同的PUBLIC_KEY
,在这种情况下,nftContract
指定了public onlyOwner
。 这正是我所做的。 因此,从概念上讲,谁拥有这个NFT代码? 在etherscan上,它是to
地址(合同地址),还是from
地址,即我的公钥,部署合同的地址,并且正在调用铸造,现在因为调用者不是所有者而失败。 ![enter image description here](https://istack.dev59.com/GbbrU.webp)
Truffle
,您可以使用额外的字段指定调用方。 await nft.transferFrom(accounts[0], accounts[1], 1, { from: accounts[1] })
这里不考虑额外参数,因为我正在使用 hardhat。
methods.mintNFT
时,我猜你需要传递测试账户发送地址。 - Mikko Ohtamaa