Documentation Index Fetch the complete documentation index at: https://docs.qu.ai/llms.txt
Use this file to discover all available pages before exploring further.
本文展示如何使用 Hardhat 在 Quai Network 的任何链上部署 Solidity 智能合约。
前提条件
要在 Quai 上部署单链智能合约,我们需要一些工具包和依赖项。以下是我们将使用的所有依赖项概述:
NodeJS Javascript 运行时环境。请使用 LTS 版本。 hardhat-example 包含 Quai Network 示例合约和部署脚本的 Hardhat 项目。 Quais.js 用于与 Quai Network 交互的 JavaScript 库。 @quai/hardhat-deploy-metadata 将合约元数据上传到 IPFS 的 Hardhat 插件,用于在 Quaiscan 上验证合约。 @openzeppelin/contracts 示例 ERC20 和 ERC721 合约使用的智能合约库。
环境设置
安装示例仓库
首先克隆 hardhat-example 仓库,导航到本教程将使用的 Solidity 目录,并通过 npm 安装依赖项。
git clone https://github.com/dominant-strategies/hardhat-example.git
cd hardhat-example/Solidity
npm install
智能合约
Solidity/ 目录包含 2 个示例合约:contracts/ 目录中的 ERC20.sol 和 ERC721.sol。这两个合约都是从 Open Zeppelin 库 派生的实现。
本教程将使用 ERC20.sol 示例合约,但您也可以添加自己的合约或使用其他库的合约。
Quai Network EVM 支持 Solidity 版本最高到 0.8.20。使用更新版本的 Solidity 可能会在部署智能合约时导致错误。
环境变量
我们在 hardhat-example 仓库的根目录中包含了一个示例环境文件 .env.dist,用于安全地管理代币详情、私钥和 RPC URL。
.env.dist 文件是一个模板文件,不应直接使用。您应该将 .env.dist 文件复制到新的 .env 文件。此文件位于 hardhat-example 仓库的根目录,作为 Solidity/ 目录的配置文件。
使用以下命令将根目录中的 .env.dist 文件复制到仓库根目录的新 .env 文件:
打开 .env 文件并添加您的私钥、RPC URL 和要部署的合约的代币参数。.env 文件应如下所示:
## 示例环境文件 - 根据需要更改所有值
# 部署地址的唯一私钥
CYPRUS1_PK = "0x0000000000000000000000000000000000000000000000000000000000000000" # 以 0x00 开头的公钥
# 链 ID(本地:1337,Orchard 测试网:15000,主网:9)
CHAIN_ID = "15000"
# RPC 端点
RPC_URL = "https://orchard.rpc.quai.network"
# ERC20 参数
ERC20_NAME = "TestERC20"
ERC20_SYMBOL = "TE20"
ERC20_INITIALSUPPLY = 1000000
# ERC721 参数
ERC721_NAME = "TestERC721"
ERC721_SYMBOL = "TE721"
ERC721_BASE_URI = "ipfs://METADATA_CID/"
ERC721_MAX_TOKENS = 1000
示例 .env.dist 默认指向 Orchard 测试网 ,因此您无需消耗真实 QUAI 即可部署。
要部署到主网,请将 CHAIN_ID 更改为 9,将 RPC_URL 更改为
https://rpc.quai.network。
有关 RPC 端点的更多信息,请参阅网络 页面。
hardhat-example 仓库使用 Quais SDK 仅使用一个 RPC URL 配置网络连接。要了解有关 SDK 如何配置网络提供者的更多信息,请访问 SDK 提供者示例 部分。
填写私钥和 RPC URL 后,我们现在可以在 hardhat.config.js 中安全地使用它们了。
Hardhat 配置
Hardhat 使用 hardhat.config.js 文件来配置智能合约部署。配置文件允许您定义部署网络、任务、编译器等。
hardhat-example 包含一个预构建的 hardhat.config.js 文件,其中包含用于在 Cyprus-1 上部署和验证智能合约的配置。
此示例配置文件作为 hardhat-example 仓库的一部分提供。 /**
* @type import('hardhat/config').HardhatUserConfig
*/
require ( '@nomicfoundation/hardhat-toolbox' )
require ( '@quai/quais-upgrades' )
require ( '@quai/hardhat-deploy-metadata' )
const dotenv = require ( 'dotenv' )
dotenv . config ({ path: '../.env' })
module . exports = {
defaultNetwork: 'cyprus1' ,
networks: {
cyprus1: {
url: process . env . RPC_URL ,
accounts: [ process . env . CYPRUS1_PK ],
chainId: Number ( process . env . CHAIN_ID ),
},
},
solidity: {
compilers: [
{
version: '0.8.17' ,
settings: {
optimizer: { enabled: true , runs: 1000 },
metadata: {
bytecodeHash: 'ipfs' ,
useLiteralContent: true ,
},
evmVersion: 'london' ,
},
},
{
version: '0.8.20' ,
settings: {
optimizer: { enabled: true , runs: 1000 },
metadata: {
bytecodeHash: 'ipfs' ,
useLiteralContent: true ,
},
evmVersion: 'london' ,
},
},
],
},
paths: {
sources: './contracts' ,
cache: './cache' ,
artifacts: './artifacts' ,
},
mocha: {
timeout: 20000 ,
},
}
Cyprus-1 是目前 Quai Network 上唯一活跃的区域,因此示例配置仅定义了一个
cyprus1 网络。完整的区域端点列表请参阅网络 。 metadata.bytecodeHash: 'ipfs' 和 useLiteralContent: true 编译器设置是
@quai/hardhat-deploy-metadata 生成可验证输出所必需的。删除它们将导致
Quaiscan 验证失败。
部署合约时,hardhat.config.js 将从 .env 文件中提取您的私钥和 RPC URL。您还可以在 solidity 对象中指定 Solidity 版本和编译器设置。
部署和交互
使用 Hardhat 编译
使用 Hardhat 进行智能合约编译很简单,可以在 CLI 中使用 npx 完成。 使用以下命令编译 contracts/ 目录中的所有合约: 应该输出: Downloading compiler 0.8.20
Compiled 2 Solidity files successfully
配置部署脚本
在 scripts/ 目录中,您会找到 ERC20 和 ERC721 合约的部署脚本:deployERC20.js 和 deployERC721.js。在本教程中,我们将部署一个 ERC20 合约。 deployERC20.js 脚本从 hardhat.config.js 中提取您的网络配置,从仓库根目录的 .env 文件中提取您的代币参数,并使用它们来部署您的合约。代币参数通过 tokenArgs 数组使用: const tokenArgs = [ process . env . ERC20_NAME , process . env . ERC20_SYMBOL , quais . parseUnits ( process . env . ERC20_INITIALSUPPLY )]
在部署合约之前,该脚本使用 @quai/hardhat-deploy-metadata 插件将已编译合约的元数据推送到 IPFS 并返回生成的 CID: const { deployMetadata } = require ( "hardhat" )
// ...
const ipfsHash = await deployMetadata . pushMetadataToIPFS ( "ERC20" )
然后 CID 作为第四个参数传递给 ContractFactory,将其嵌入已部署的字节码中。Quaiscan 稍后通过该 CID 获取您的源代码进行验证 — 没有它,合约虽可部署,但无法验证。 const provider = new quais . JsonRpcProvider ( hre . network . config . url , undefined , { usePathing: true })
const wallet = new quais . Wallet ( hre . network . config . accounts [ 0 ], provider )
const ERC20 = new quais . ContractFactory ( ERC20Json . abi , ERC20Json . bytecode , wallet , ipfsHash )
我们将在下一步中使用这些概念来正确修改代币参数和网络规范以部署我们的合约。 deployERC721.js 脚本遵循相同的结构,但具有不同的合约参数以及不同的
ABI/字节码。您可以为要部署的任何合约复制此配置。
部署您的合约
部署脚本接受一个 --network 标志来指定您要部署到的网络。示例配置仅定义了 cyprus1,我们将在此使用它。 npx hardhat run scripts/deployERC20.js --network cyprus1
应该输出: File added with CID: QmPCoBa1bCFmRoTD7GuexJqBAy7pqg8J4b8B48q5DgxUEV
Original IPFS hash found in bytecode: QmPCoBa1bCFmRoTD7GuexJqBAy7pqg8J4b8B48q5DgxUEV
Metadata JSON for ERC20 saved to /.../hardhat-example/Solidity/metadata/ERC20_metadata.json
Transaction broadcasted: 0x235fdeb85db5b6cee8da9780e2246907e8342751849f5ce3514847a5dffd916f
Contract deployed to: 0x00735E9B2c731Fd3eCC8129a3653ACb99dF969cC
第一行打印的 CID 是您在 Quaiscan 上验证合约所需的 IPFS 哈希 — 请保存它。 恭喜,您现在已经在 Quai Network 上部署了一个 ERC20 代币! ERC20.sol 和 ERC721.sol 示例合约是每种代币的基本实现,仅供示例使用。强烈建议在将这些合约用于任何生产用途之前,根据您的具体用例进行修改。
与合约交互
Hardhat 控制台目前不支持与 Quai Network 上的智能合约交互。 要与合约交互,您可以使用 Quais SDK 配置一个简单的脚本。下面的脚本为我们部署到 0x00735E9B2c731Fd3eCC8129a3653ACb99dF969cC 的 ERC20 代币配置了一个 Contract 实例,以获取代币的名称、符号和总供应量。 const quais = require ( 'quais' )
const ERC20Json = require ( '../artifacts/contracts/ERC20.sol/ERC20.json' )
async function getContractDetails () {
// 配置提供者、钱包和合约工厂
const provider = new quais . JsonRpcProvider ( hre . network . config . url , undefined , { usePathing: true })
const wallet = new quais . Wallet ( hre . network . config . accounts [ 0 ], provider )
const ERC20 = new quais . Contract ( "0x00735E9B2c731Fd3eCC8129a3653ACb99dF969cC" , ERC20Json . abi , wallet )
const tokenName = await ERC20 . name ()
const tokenSymbol = await ERC20 . symbol ()
const tokenDecimals = await ERC20 . decimals ()
const tokenTotalSupply = await ERC20 . totalSupply ()
}
getContractDetails ()
. then (() => process . exit ( 0 ))
. catch (( error ) => {
console . error ( error )
process . exit ( 1 )
})
现在您拥有了创建简单 Hardhat 项目、部署和与自己的智能合约交互所需的所有工具。
由于部署脚本已将您的合约元数据推送到 IPFS,您现在可以在 Quaiscan 上验证它 — 详见在 Quaiscan 上验证合约 了解下一步。