我正在关注这里的文档: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;
}
}
当我尝试minting
用这个来估算 gas 成本时:
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
,我不确定还有什么可以将交易作为 from 签名MY_PUBLIC_KEY
。解决这个问题的简单方法是删除onlyOwner
from function mintNFT
,一切都按预期运行。但是假设我们想要保留onlyOwner
,我将如何签署超出上面已经写好的交易。
注意我hardHat
用来编译和部署合约。即:npx hardhat compile npx hardhat run scripts/deploy.js
==============================================
附录
alchemy 给出的部署薄荷的确切代码是:
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
地址,即我的公钥,部署合约的地址,以及调用 mint 的地址,现在调用者失败不是所有者错误。
搜索互联网,我看到其他人在这里遇到了这个问题:https://ethereum.stackexchange.com/questions/94114/erc721-testing-transferfrom,因为Truffle
您可以使用额外字段指定调用者:
await nft.transferFrom(accounts[0], accounts[1], 1, { from: accounts[1] })
额外参数在这里不是一个选项,因为我使用的是安全帽。