使用hardhat/ethers.js调用已经存在的合约
使用hre : https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment
Hardhat Runtime Environment 里边通过hardhat-ethers插件注入了一个ethers实例可以直接用。具体功能跟ethers.js是一致的。
Ethers.js相关文档:https://docs.ethers.io/v5/getting-started/#getting-started--contracts
call.js代码
我们在hardhat工程的script目录下新建call.js文件:
const main = async () => {
//合约地址
let contractAddress = "0x7e163122D7D0ce2f997d1AAFCb662C400F06e998";
//ABI合约接口定义
let contractABI = [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
......
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
];
//Provider
const quicknodeUrl = "https://bold-blue-fog.ethereum-goerli.discover.quiknode.pro/API_KEY/";
const alchemyUrl = "https://eth-goerli.g.alchemy.com/v2/API_KEY";
const provider = await new hre.ethers.getDefaultProvider(quicknodeUrl); //连接网络
//console.log(provider);
//只读操作
let balance = await provider.getBalance("0x4953BC5Fc7d5ABD0cD86A198A4A34EB2e3b8dC1d");
balance = hre.ethers.utils.formatEther(balance);
console.log("address[0x4953BC5Fc7d5ABD0cD86A198A4A34EB2e3b8dC1d] balance is: " + balance);
let blockNumber = await provider.getBlockNumber();
console.log("current block number: ", blockNumber);
//Signer签名
console.log("获取provider");
const signer = await new hre.ethers.Wallet("PRIVATE_KEY", provider);
//let signerAddress = await signer.getAddress();
//console.log("signer address", signerAddress);
console.log("获取signer");
//合约对象
const nftContract = await new ethers.Contract(contractAddress, contractABI, provider);
console.log("获取nftContract");
const nftWithSinger = await nftContract.connect(signer); //合约的写方法,需要Signer
console.log("nftContract.connect(signer)");
//调用合约方法
let txn = await nftWithSinger.makeAnEpicNFT();
console.log("mint");
await txn.wait(); //等待mint结束
console.log("Minted NFT #1");
console.log(txn);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
输出:
$npx hardhat run scripts/call.js --network goerli
address[0x4953BC5Fc7d5ABD0cD86A198A4A34EB2e3b8dC1d] balance is: 0.804995619844421299
current block number: 7984396
linyangdeMacBook-Air:epic-nfts hayashihiroshi$ npx hardhat run scripts/call.js --network goerli
address[0x4953BC5Fc7d5ABD0cD86A198A4A34EB2e3b8dC1d] balance is: 0.804995619844421299
current block number: 7984414
获取provider
获取signer
获取nftContract
nftContract.connect(signer)
mint
Minted NFT #1
{
type: 2,
chainId: 5,
nonce: 21,
maxPriorityFeePerGas: BigNumber { value: "1500000000" },
maxFeePerGas: BigNumber { value: "1500000052" },
gasPrice: null,
gasLimit: BigNumber { value: "94870" },
to: '0x7e163122D7D0ce2f997d1AAFCb662C400F06e998',
value: BigNumber { value: "0" },
data: '0xde9d132f',
accessList: [],
hash: '0x9dc1040d736dfbe0ac5aa56f8d4b4d16aee7cd1ff183a1a0f0d4f60da3c888fd',
v: 1,
r: '0x4fad2fba284aec58c9d3f8d9238cc074ea4d0a6c2fe4b31ba15b166f29638fbd',
s: '0x76d8635fcb8f7e8d351ee0e2ab02f51979524b9ca8b77edaf55e49c97f83b52f',
from: '0x4953BC5Fc7d5ABD0cD86A198A4A34EB2e3b8dC1d',
confirmations: 0,
wait: [Function (anonymous)]
}
浏览器查看合约,可以看到多了一个交易:https://goerli.etherscan.io/address/0x7e163122d7d0ce2f997d1aafcb662c400f06e998
PS:ERC-721合约的部署真的贵,0.5个goerli ETH,但是调用mint就便宜很多、才0.00014
总结一下
1、Provider是区块链连接的抽象
Web3Provider用在浏览器上,MetaMask插件向window注入ethereum对象,这个对象作为Provider的构造参数。
在Hardhat工程里边,非浏览器环境,一般用DefaultProvider就够了。这里指定quicknode的endpoint作为入参数进行构造。
2、Signer是区块链账户的抽象
一般有Provider就可以做只读操作了,但是要做写操作需要Signer签名。
Signer是抽象类,需要具体的实现,这里用的是Wallet:
const signer = await new hre.ethers.Wallet(PRIVATE_KEY, provider);
3、获得合约对象
我们获得合约对象之后就可以用它来调用合约的方法了。
const nftContract = await new ethers.Contract(address, abi, provider);
const nftContractWithSigner = await nftContract.connect(signer);
上面一共得到了两个对象nftContract
和nftContractWithSigner
,前者用来调用合约的查询方法,后者可以调用写方法。比如前文代码里的mint操作就需要用后者了。