区块链之以太坊Hardhat开发框架——部署在windows为例

Hardhat 提供了一个灵活且易于使用的开发环境,可以轻松地编写、测试和部署智能合约。Hardhat还内置了Hardhat 网络(Hardhat Node),它是为开发而设计的本地以太坊网络。

下面是hardhat的官方文档

https://hardhat.org/hardhat-runner/docs/getting-started

一、创建及配置Hardhat项目

Hardhat 构建在 Node.js 之上, 使用 Hardhat 要求我们在电脑先安装好Node.js (>= 16.0),创建hardhat-tutorial文件夹。

1、初始化Node项目

2、安装Hardhat 

 3、运行hardhat

用键盘选择create a JavaScript project

生成project后的项目目录 

二、编写合约 

合约开发推荐使用 VSCode 编辑器 + solidity 插件,在VSCode下添加solidity插件

contracts 文件夹下新建一个合约文件 Counter.sol

Counter.js代码如下: 

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Counter {
    uint counter;

    constructor() {
        counter = 0;
    }

    function count() public {
        counter = counter + 1;
    }

    function get() public view returns (uint) {
        return counter;
    }
}

 在编写合约时,尽量不要重复造轮子,基于优质开源的第三方库,不仅可以提高效率,还可以让我们的合约代码更安全,例如要开发一个 Token,可以用npm 安装OpenZepplin 库:

npm install @openzeppelin/contracts --save-dev

然后在合约中 import 相应库中的合约文件及可。

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
  constructor(uint256 initialSupply) ERC20("Token Name", "Token Symbol") {
    _mint(msg.sender, initialSupply);
  }
}

 三、编译合约

hardhat.config.js 有默认的Solidity 编译器配置,因此我们直接编译合约即可,在终端中运行 npx hardhat compile。

成功编译后,会在 artifacts/contracts/ 目录下生成Counter.json 和 build-info, Counter.json包含了智能合约的 ABI 、字节码(Bytecode)等

智能合约的ABI信息,包括了合约的函数、事件等接口信息。这个文件通常会与其他合约交互时使用,因为它可以被其他合约和DApp使用。

Bytecode是部署合约所需的字节码,部署合约时候就是把该字节码作为交易的输入数据发送链上。

 四、编写测试用例

为智能合约编写自动化测试至关重要,因为事关用户资金。

使用 Harhdat 内置的网络,使用ethers.js与前面的合约进行交互,并使用 Mocha 作为测试运行器。在test文件夹下创建Counter.js文件代码如下:

// 引入 Hardhat 提供的 ethers 库,用于部署和交互智能合约
const { ethers } = require("hardhat");

// 引入 chai 的断言函数 expect,用于编写测试判断条件
const { expect } = require("chai");

// 定义一个全局变量,用于存储部署后的合约实例
let counter;

// 定义测试套件,描述被测试的合约模块为 "Counter"
describe("Counter", function () {

  // 初始化函数:部署 Counter 合约并获取实例
  async function init() {
    // 获取测试账户数组,其中 owner 是部署者,otherAccount 可用于后续扩展测试权限等
    const [owner, otherAccount] = await ethers.getSigners();

    // 获取 Counter 合约工厂(ContractFactory),可以用来部署合约
    const Counter = await ethers.getContractFactory("Counter");

    // 部署合约并返回实例(此时合约已经部署完成,不需要调用 .deployed())
    counter = await Counter.deploy();

    // 打印部署后合约的地址(ethers v6 中使用 .target 属性获取地址)
    console.log("counter:" + counter.target);
  }

  // 所有测试用例运行前执行一次初始化操作(部署合约)
  before(async function () {
    await init();
  });

  // 第一个测试用例:测试合约初始值是否为 0
  it("init equal 0", async function () {
    // 调用 counter 合约的 get() 方法,断言返回值为 0
    expect(await counter.get()).to.equal(0);
  });

  // 第二个测试用例:调用 count() 函数自增,验证是否变为 1
  it("add 1 equal 1", async function () {
    // 调用 count() 方法进行加 1 操作
    let tx = await counter.count();

    // 等待交易被打包确认
    await tx.wait();

    // 调用 get() 方法获取当前计数值,断言为 1
    expect(await counter.get()).to.equal(1);
  });
});

运行npx hardhat test之后输出全部通过,证明测试通过。 

还可以在Solidity代码中调用console.log()打印日志信息和合约变量,可以方便我们调试代码。

在合约代码中导入Hardhat console.log就可以使用它。

 五、部署合约

部署合约我们需要编写一个部署脚本。

在项目下新建scripts文件夹,新建一个deploy.js 用来写部署脚本,代码如下

const { ethers } = require("hardhat");

async function main() {
    // 获取合约工厂
    const Counter = await ethers.getContractFactory("Counter");

    // 部署合约(v6 会自动等待部署完成)
    const counter = await Counter.deploy();

    // 输出部署的合约地址(v6 使用 counter.target)
    console.log("Counter address:", counter.target);
}

main().catch((error) => {
    console.error(error);
    process.exitCode = 1;
});

运行 npx hardhat run scripts/deploy.js 时,合约会部署到 Hardhat 内置网络上。 

 为了在运行任何任务时指示Hardhat连接到特定的EVM网络,可以使用--network参数。

npx hardhat run scripts/deploy.js --network <network-name>

network-name 需要在 hardhat.config.js 文件中进行配置:

require("@nomicfoundation/hardhat-toolbox");

// 填入自己的私钥或助记词,
const PRIVATE_KEY1 = "0x.... YOUR PRIVATE KEY1";
const PRIVATE_KEY2 = "0x....  YOUR PRIVATE KEY1";
const Mnemonic = "YOUR Mnemonic";


module.exports = {
  solidity: "0.8.9", // solidity的编译版本
  networks: {
    goerli: {
      url: "https://eth-goerli.api.onfinality.io/public",
      accounts: [PRIVATE_KEY1,PRIVATE_KEY2],
      chainId: 5,
    },
    
     mumbai: {
      url: "https://endpoints.omniatech.io/v1/matic/mumbai/public",
      accounts: {
        mnemonic: Mnemonic,
      },
      chainId: 80001,
    },
  }
};

以上配置了两个网络,一个是以太坊测试网 goerli, 一个是 Polygon 测试网mumbai, 我们可以在 https://chainlist.org 找到每个网络的节点 URL 及 chainID。

在网络配置中,需要提供提交交易账号, 可以通过私钥或助记词 进行配置,这里配置的账号(需要提前充币进入到账号中),在hardhat 脚本中(测试及部署脚本)调用getSigners 即可获得:

const [owner, otherAccount] = await ethers.getSigners();

六、代码开源验证

智能代码开源会增加了合约的透明度和可靠性,是项目建立信任很重要的一个步骤。

1、安装 hardhat-toolbox 或 hardhat-etherscan , 这一步我们这里已经完成,因为在初始化项目的时候安装了 hardhat-toolbox , 如果没有安装,可以使用以下命令安装

npm install --save-dev @nomiclabs/hardhat-etherscan

2、在hardhat.config.js 中配置您的 Etherscan API 密钥和网络设置,例如: 

      require("@nomicfoundation/hardhat-toolbox");
      或
      // require("@nomiclabs/hardhat-etherscan");
      
      etherscan: {
        apiKey: ""
      },
      
     

     如何获取 Etherscan API 密钥?

    1. 访问部署网络对应主网的 Etherscan 网站,并注册一个账号(如果还没有账号的话)。
    2. 登录你的账号并进入 Etherscan 的「我的帐户」页面。
    3. 点击页面左侧的「API-KEYs」标签页。
    4. 在页面上方的「Create New API KEY」部分,输入 API 密钥的名称和描述,然后选择需要访问的 API 权限。
    5. 点击「Generate」按钮来生成 API 密钥。

     

    3、执行验证命令:

    npx hardhat verify <deployed-contract-address> "参数(若有)" --network <network-name> 
    

    该命令会为我们上传合约代码并验证其源代码。如果一切顺利(网络顺畅的话),在 Etherscan 上看到的合约被成功验证。

    ### 配置服务器环境以调用云笔记智能合约 为了成功配置服务器环境以便能够调用云笔记智能合约,需确保服务器具备必要的软件栈以及适当的安全措施。以下是关于如何准备这一环境的具体说明: #### 安装依赖项 首先,在ECS实上安装所需的开发工具包和库文件。这通常涉及更新操作系统包管理器,并安装诸如Node.js、npm(Node Package Manager)、Git等基础组件[^1]。 对于特定于区块链交互的部分,则需要部署支持Web3 API接口的应用程序或框架,比如Truffle Suite或是Hardhat,这些工具可以帮助简化与以太坊虚拟机(EVM)兼容平台上的智能合约之间的通信过程[^2]。 #### 设置节点运行环境 接着要搭建一个本地或者远程的以太坊客户端作为RPC服务端点用于发起请求给目标网络中的矿工节点处理交易。可以选择Geth(Go Ethereum)或者是更轻量级的选择如Infura这样的托管解决方案来减少运维负担[^3]。 一旦选择了合适的客户端类型之后就要按照官方文档指导完成其初始化流程并启动同步区块数据直至最新状态;如果采用的是第三方API网关形式则只需注册账号获取访问令牌即可立即投入使用而无需关心底层细节维护工作[^4]。 #### 编译部署智能合约 利用Solidity编译器将源码转换为目标字节码格式(.bin),同时生成ABI(Application Binary Interface)(.abi/.json)[^5]。随后借助之前提到过的IDE/CLI工具集把它们上传至指定地址处创建新的合约实体对象供后续操作引用。 最后一步就是编写应用程序逻辑部分了——即怎样封装好HTTP RESTful风格的服务函数去触发相应事件动作并与前端界面相集成展示最终效果出来让用户可以直观感受到整个系统的运作方式[^6]。 ```javascript // 示代码片段:使用web3.js连接到智能合约 const Web3 = require('web3'); const web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID')); async function interactWithContract() { const contractAddress = '0xYourSmartNotebookContractAddress'; const abiDefinition = [...]; // ABI定义数组 let myContract = new web3.eth.Contract(abiDefinition, contractAddress); try { await myContract.methods.someMethod().call({from: "your_account_address"}); console.log("Successfully called the smart notebook contract method."); } catch(error){ console.error(`Error occurred while calling contract methods: ${error.message}`); } } ```
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值