什么是zkEVM?
Polygon zkEVM是第一个开源的zk-Rollup,以太坊提供安全性保证、 完整的EVM操作码等价,确保无摩擦的用户体验。
github: https://polygon.technology/solutions/polygon-zkevm
-- 它是一个与Polygon Matic POS不同的网络吗?
是的,它是一个完全不同的网络,有自己的代币和钱包配置。
-- 这是否意味着它使用自己的代币?
是的,它使用自己的原生代币,而不是Matic或Mumbai Testnet代币。
-- EVM 等价(EVM-equivalence) 是什么意思?
等价指的是Type2 ZK-EVM,Vitalik 博客:不同类型的 ZK-EVMs 对其有更好的定义。
Type2 ZK-EVMs努力做到完全等同于EVM,但不完全等同于以太坊。也就是说,它们 "从内部 "看起来和以太坊完全一样,但它们在外部有一些差异,特别是在数据结构上,如块结构和状态树。
https://vitalik.eth.limo/general/2022/08/04/zkevm.html
-- 对于开发者来说
这意味着你可以部署你现有的solidity代码,而不需要通过任何额外的步骤来编译你的代码,让它在这个网络上工作。与其他ZK-EVM解决方案相比,Type 2提供了一种更简单的方式与该ZK-EVM解决方案结合。
目标是与现有的应用程序完全兼容,但对以太坊做一些小的修改,使开发更容易,并使证明生成更快。
了解了这些, 让我们开始吧
钱包配置
需要注意的是,这些信息有很多已经存在于官方的Polygon Wiki For zkEVM,当zkEVM主网可用时,这些设置可能会改变。
zkEVM的钱包配置在Chainlist.org上吗?很遗憾还没有,因为网络配置和端口号可能会改变。
我们对zkEVM Testnet的配置设置如下:
- 网络名称: Polygon zkEVM Testnet
- rpc网址: https://rpc.public.zkevm-test.net
- 链的ID: 1402
- 货币符号: ETH
- 区块链浏览器网址: https://explorer.public.zkevm-test.net
你可以通过进入网络,手动添加一个网络,将其添加到当前的MetaMask钱包:
MetaMask手动添加一个网络
使用Polygon zkEVM Testnet配置MetaMask
让我们看看在zkEVM浏览器上的钱包信息:
https://explorer.public.zkevm-test.net/address/0xB3f03B93F0bd65B960EE950d9aFC6867D461C33f
从水龙头获取测试代币
与其他Testnet网络相比,zkEVM获得测试代币的方式有点不同。你需要先获得Goerli Testnet代币,然后将它们桥接到zkEVM。
我们将使用QuickNode Goerli Faucet,但你也可以使用从以下任何一个链接获取:
一旦我们有了Goerli Testnet代币,我们需要通过使用https://public.zkevm-test.net/, 将它们桥接到zkEVM Testnet上。
连接你喜欢的钱包,确保网络设置为以太坊 Goerli,输入需要桥接的金额,然后点击继续。
确认桥接交易:
通过切换到zkEVM,然后确认交易,最终完成交易。
如果交易成功,你应该有一个确认屏幕,并在区块浏览器上看到结果。
将ERC20合约部署到zkEVM Testnet上
接下来,我们要用Hardhat来设置和部署ERC20合约到zkEVM。
安装依赖
请确保在你的电脑上事先安装好以下依赖:
- nvm或node v18.12.1
- pnpm v7.15.0
设置Hardhat
我们要做的第一件事是创建一个新的项目文件夹,启动pnpm,安装Hardhat,并对其进行配置:
mkdir zkevm-erc20;
cd zkevm-erc20;
git init;
pnpx hardhat;
# Expected Prompts
# 888 888 888 888 888
# 888 888 888 888 888
# 888 888 888 888 888
# 8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
# 888 888 "88b 888P" d88" 888 888 "88b "88b 888
# 888 888 .d888888 888 888 888 888 888 .d888888 888
# 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
# 888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888
#
# Welcome to Hardhat v2.12.3
#
# ? What do you want to do? …
# Create a JavaScript project
# ❯ Create a TypeScript project
# Create an empty hardhat.config.js
# Quit
# ? Hardhat project root: › /path/to/zkevm-erc20
# ? Do you want to add a .gitignore? (Y/n) › y
# ? Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) › y
pnpm install;
让我们通过运行一个节点,部署默认的合约,然后测试该合约,来仔细检查我们的Hardhat设置是否按预期工作。
在终端1
# FROM: ./zkevm-erc20
./node_modules/.bin/hardhat node;
# Expected Output:
# Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
#
# Accounts
# ========
#
# WARNING: These accounts, and their private keys, are publicly known.
# Any funds sent to them on Mainnet or any other live network WILL BE LOST.
# ...
在终端2
将 "Lock.sol" 合约部署到我们正在运行的本地节点:
# FROM: ./zkevm-erc20
./node_modules/.bin/hardhat run scripts/deploy.ts
# Expected Output:
# Compiled 1 Solidity file successfully
# Lock with 1 ETH and unlock timestamp 1701595951 deployed to 0x5FbDB2315678afecb367f032d93F642f64180aa3
运行由原始脚手架项目生成的测试:
# FROM: ./zkevm-erc20
./node_modules/.bin/hardhat test;
# Expected Output:
# Lock
# Deployment
# ✔ Should set the right unlockTime (894ms)
# ✔ Should set the right owner
# ✔ Should receive and store the funds to lock
# ✔ Should fail if the unlockTime is not in the future
# Withdrawals
# Validations
# ✔ Should revert with the right error if called too soon
# ✔ Should revert with the right error if called from another account
# ✔ Shouldn't fail if the unlockTime has arrived and the owner calls it
# Events
# ✔ Should emit an event on withdrawals
# Transfers
# ✔ Should transfer the funds to the owner
#
# 9 passing (1s)
创建一个ERC20合约
我们将以OpenZeppelin的ERC20 Solidity合约为基础,它将创建初始10,000个代币的代币,并允许所有者铸造更多的代币。
添加依赖
# FROM: ./zkevm-erc20
pnpm add -D @openzeppelin/contracts;
配置ERC20
使用OpenZepplin Wizard来配置ERC20代币:
编写新的合约
重命名现有的Lock.sol为zkerc20.sol,并用我们从OpenZeppeling向导中生成的代码替换它:
# FROM: ./zkevm-erc20
mv ./contracts/Lock.sol ./contracts/zkERC20.sol;
文件: ./contracts/zkERC20.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract ZkERC20 is ERC20, Ownable {
constructor() ERC20("zkERC20", "ZK20") {
_mint(msg.sender, 10000 * 10 ** decimals());
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
测试ERC20合约
首先我们要为我们的ERC20合约做一个单一的测试,然后验证它是否正常工作。
部署脚本
首先,我们需要修改我们的部署脚本,以考虑到新的合约名称。
文件: ./scripts/deploy.ts。
// Imports
// ========================================================
import { ethers } from "hardhat";
// Main Deployment Script
// ========================================================
async function main() {
// Make sure in the contract factory that it mateches the contract name in the solidity file
// Ex: contract ZkERC20
const zkERC20Contract = await ethers.getContractFactory("ZkERC20");
const contract = await zkERC20Contract.deploy();
await contract.deployed();
console.log(`ZkERC20 deployed to ${contract.address}`);
};
// Init
// ========================================================
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
创建测试
接下来要把Lock.ts测试文件重命名为zkERC20.test.ts,并添加一个测试,确认铸造erc20代币的总余额:
# FROM: ./zkevm-erc20
mv ./test/Lock.ts ./test/zkERC20.test.ts;
文件: ./test/zkERC20.test.ts:
// Imports
// ========================================================
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { ethers } from "hardhat";
// Tests
// ========================================================
describe("zkERC20", function () {
// We define a fixture to reuse the same setup in every test.
// We use loadFixture to run this setup once, snapshot that state,
// and reset Hardhat Network to that snapshot in every test.
async function deployZkERC20() {
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await ethers.getSigners();
// Make sure in the contract factory that it mateches the contract name in the solidity file
// Ex: contract ZkERC20
const zkERC20Contract = await ethers.getContractFactory("ZkERC20");
const zkERC20 = await zkERC20Contract.deploy();
return { zkERC20, owner, otherAccount };
};
/**
*
*/
describe("Deployment", function () {
/**
*
*/
it("Should deploy with initial 10,000 supply", async function () {
// Setup
const { zkERC20 } = await loadFixture(deployZkERC20);
// Init + Test
expect(await zkERC20.totalSupply()).to.equal(ethers.utils.parseEther(`10000`).toString());
});
});
/**
*
*/
describe("Minting", function () {
/**
*
*/
it("Should mint and increase the supply by 137", async function () {
// Setup
const { zkERC20, owner } = await loadFixture(deployZkERC20);
// Init
await zkERC20.connect(owner).mint(owner.address, ethers.utils.parseUnits('137', 18));
// Init + Test
expect(await zkERC20.totalSupply()).to.equal(ethers.utils.parseEther(`10137`).toString());
});
});
});
让我们运行Hardhat节点并测试这个合约。
在终端1
运行一个本地节点:
# FROM: ./zkevm-erc20
./node_modules/.bin/hardhat node;
# Expected Output:
# Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
#
# Accounts
# ========
#
# WARNING: These accounts, and their private keys, are publicly known.
# Any funds sent to them on Mainnet or any other live network WILL BE LOST.
# ...
在终端2
运行测试:
# FROM: ./zkevm-erc20
./node_modules/.bin/hardhat test;
# Expected Output:
# zkERC20
# Deployment
# ✔ Should deploy with initial 10,000 supply (803ms)
# Minting
# ✔ Should mint and increase the supply by 137
#
# 2 passing (819ms)
部署ERC20合约
需要注意的是,目前Hardhat中不支持zkEVM的部署。为了部署你的合约,你需要使用以太坊 Remix的Injected Provider配置。
确保在remix中创建一个zkERC20.sol文件,其中包含上面的合约代码:
切换到编译部分,点击“编译按钮”,得到绿色的复选标记,表示一切编译正确。
切换到左侧导航栏的部署部分,将环境设置为 "Injected Provider - Metamask"。并确保你的钱包被设置为zkEVM网络。
准备好后,点击部署按钮,在你的钱包中确认交易。
在MetaMask中查看代币
打开MetaMask钱包,点击交易,在区块浏览器上查看该交易。在区块浏览器中点击合约地址,打开合约。在区块浏览器中加载合约后,复制合约地址。
打开你的MetaMask,点击Asset(资产),并点击Import tokens(导入代币):
粘贴合约地址,并根据需要填写其他字段。它们可能会自动弹出,然后点击添加自定义代币:
现在你应该能够按照提示操作,然后在你的钱包里看到新的ZK20代币,并有正确的初始金额。
你已经完全部署了一个ERC20合约到Polygon Hermes zkEVM 测试网上。
完整的代码
zkEVM ERC20 代币的完整代码。请记住,目前还不支持Hardhat部署。
GitHub - codingwithmanny/zkevm-erc20
如果其他 zkEVM 教程,我们会及时更新,欢迎在 Twitter 关注 @登链社区 。