使用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);

上面一共得到了两个对象nftContractnftContractWithSigner,前者用来调用合约的查询方法,后者可以调用写方法。比如前文代码里的mint操作就需要用后者了。

posted on 2022-11-20 11:31  肥兔子爱豆畜子  阅读(1495)  评论(0编辑  收藏  举报

导航