# DocsZH | 区块链中文图书馆

### Docs 中文资源 <a href="#docs-chinese-library" id="docs-chinese-library"></a>

<table data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Monad Docs 中文版</strong></td><td>EVM兼容的并行执行Layer 1</td><td><a href="/spaces/PaHQrSOuX4vToXCmyjn9/pages/2VcRiek1xQFLw2nkvkY2">/spaces/PaHQrSOuX4vToXCmyjn9/pages/2VcRiek1xQFLw2nkvkY2</a></td></tr><tr><td><strong>Berachain Docs 中文版</strong> </td><td>EVM兼容的流动性证明Layer 1</td><td><a href="/spaces/ltBXuLzX87VmBIvzSIHJ/pages/hSJTNqZFSkiUEl3C9fwq">/spaces/ltBXuLzX87VmBIvzSIHJ/pages/hSJTNqZFSkiUEl3C9fwq</a></td></tr><tr><td><strong>Babylon Docs 中文版</strong></td><td>比特币再质押协议</td><td><a href="/spaces/SWFRW10B9ZJ8MsqhgZoh/pages/fCIbrJYnue1XvdovSNk9">/spaces/SWFRW10B9ZJ8MsqhgZoh/pages/fCIbrJYnue1XvdovSNk9</a></td></tr><tr><td><strong>Solv Docs 中文版</strong></td><td>基于SolvBTC的比特币储备货币</td><td><a href="/spaces/fjdUISsbS8UDYAUQEGRk/pages/b56zWFRG7C6UDzAxvtxx">/spaces/fjdUISsbS8UDYAUQEGRk/pages/b56zWFRG7C6UDzAxvtxx</a></td></tr><tr><td><strong>Story Docs 中文版</strong>      </td><td>EVM兼容的IP资源代币化Layer 1</td><td><a href="/spaces/Ls9wLBYeJNjIL9Wsvuv2/pages/DSQqnsAqJPnIRyPgQJ1S">/spaces/Ls9wLBYeJNjIL9Wsvuv2/pages/DSQqnsAqJPnIRyPgQJ1S</a></td></tr><tr><td><strong>Sahara AI 用户指南中文版</strong></td><td>去中心化的人工智能网络</td><td><a href="/spaces/sWLeYnus1nYBWKYFQfzJ">/spaces/sWLeYnus1nYBWKYFQfzJ</a></td></tr><tr><td><strong>Hyperlane Docs 中文版</strong></td><td>跨链消息互操作性协议</td><td><a href="/spaces/LCBNpaHC8rMootw9Jrj6/pages/4ACR4kCSxJQf8jew9ssn">/spaces/LCBNpaHC8rMootw9Jrj6/pages/4ACR4kCSxJQf8jew9ssn</a></td></tr></tbody></table>

### Blog 中文资源 <a href="#blog-chinese-library" id="blog-chinese-library"></a>

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>释放 Monad 的潜力：区块产出经济学的关键作用 | aPriori</td><td><a href="/spaces/OSs7EEWwLCe1NwYciNre/pages/vxzOoiGCUHEniGFX0pWd">/spaces/OSs7EEWwLCe1NwYciNre/pages/vxzOoiGCUHEniGFX0pWd</a></td></tr></tbody></table>


# 关于 DocsZH

2024年9月29日，币安 (全球最大的加密货币交易所) 创始人，前华人首富[CZ](https://x.com/cz_binance)出狱，此前CZ因洗钱罪被美国联邦法院判处4个月监禁。出狱后，在迪拜的家中，CZ发布了一条[推特](https://x.com/cz_binance/status/1839861237850497271)，以告诉人们他重获自由。

### 一条推文引发的讨论

#### 从CZ刑满释放的第一条推文说起...

<figure><img src="/files/yN0BAQC4svVOQ2VAQmLp" alt="" width="563"><figcaption></figcaption></figure>

遗憾的是，作为中文流利的华人首富，CZ出狱后的第一条推文并未使用母语，且只有两英文字母：`gm`。

#### `gm`的中文意思？通用汽车？

CZ加入了通用汽车？CZ要向[Musk](https://x.com/elonmuskhttps://x.com/elonmusk) (特斯拉创始人) 发出挑战？CZ要颠覆新能源汽车制造业？那是不是可以叫小鹏汽车，大鹏汽车，敞篷汽车...不对，长鹏汽车！

#### 真相只有一个

上面图片里的翻译结果，由微软翻译提供，它错误地将`gm`识别为通用汽车的缩写 (英语：General Motors，缩写为GM）。然而，喜欢在项目方discord里冲浪的Web3黑奴都知道，`gm`的习惯用法，在中文里是`早安`的意思，即`good morning`的首字母缩写。与之相似的，晚安`good night`可以缩写为`gn`。

#### 从Web3黑奴的e-beggar经历说起...

当你立志成为一名Web3黑奴的时候，深夜打开某项目方的协议交互页。由于不知从何下手，你找到了该项目的使用文档，例如：<https://docs.ebeggar.com，映入眼帘的是满屏英文，黑夜给了你黑色的眼睛，你却用它寻找中文。此时，你的浏览器可能会提醒你，要不要将网页翻译为中文。>

<figure><img src="/files/2espfj04Ub10n0kT4glF" alt="" width="329"><figcaption></figcaption></figure>

恭喜，黑夜给了你黑色的眼睛，你用它寻找到了中文。接下来，我们会用一个翻译示例，阐述浏览器的自动翻译有多糟糕。

### 不友好的机器翻译

这里，以我们最近翻译的来自[aPriori](https://beta.rootdata.com/zh/Projects/detail/aPriori?k=OTUwMg%3D%3D)的技术博客为例，此处为博客节选的原文链接：[段落原文](https://0xapr.substack.com/p/unlocking-monads-potential-the-critical?open=false#%C2%A7one-block-producer-per-slot-block-space-auction)

**英文原文：**

<figure><img src="/files/LWxVRMKTPk0BskKRm05J" alt="" width="563"><figcaption></figcaption></figure>

**谷歌自动翻译结果：**

<figure><img src="/files/hUuAC4gyRLuPIU7JdfrB" alt="" width="563"><figcaption></figcaption></figure>

在谷歌自动翻译的结果中，任何人都能察觉到显而易见的错误，例如：

* `One Block Producer per Slot ＞ 每个区块生产者一个区块` 语义不通，这是一个病句。

在谷歌自动翻译的结果中，总会有一般人无法理解的内容，例如：

* `slot ＞ 时隙` 时隙是什么意思？

在谷歌自动翻译的结果中，总会有专业术语被错误翻译，但一般人无法察觉，例如：

* `inclusion ＞ 包含` 在区块链技术原语中，`包含`翻译为 `(区块) 打包`，更符合语境。

### DocsZH 的翻译优化

#### 我们尝试优化自动翻译结果

在上述博客节选翻译中，我们改正了错误的病句，对专业术语附注了名词解释，并对语义错误的单词译文进行了符合技术语境的演化。以下是我们的最终译文：

> #### 每个时隙 (Slot) 对应一个区块生产者 ⇒ 区块空间拍卖 <a href="#mei-ge-slot-dui-ying-yi-ge-qu-kuai-sheng-chan-zhe-qu-kuai-kong-jian-pai-mai" id="mei-ge-slot-dui-ying-yi-ge-qu-kuai-sheng-chan-zhe-qu-kuai-kong-jian-pai-mai"></a>
>
> 我们假设，对于任何给定的 [Slot](https://ethereum.org/zh/glossary/#slot)，都有一个区块生产者，对区块排序拥有垄断权力，该区块生产者唯一决定交易的打包和排序，我们将在未来的博文中探讨多个并发领导人设置 ([Solana. 2024](https://docs.google.com/document/d/1zSkhW_Urp2RbTp_hKGCefc8o895eCczm5fS1RqzTVVE/edit#heading=h.73njnkwdob7a)) 中的拍卖。鉴于每个 Slot 的区块空间有限，区块生产者必须分配这种稀缺资源，每次对区块排序时，都必须有效地进行区块空间拍卖。

#### 改正自动翻译中出现的病句

在上述博客节选的谷歌自动翻译中，`One Block Producer per Slot`被翻译为`每个区块生产者一个区块`，造成这种错误的原因是谷歌翻译无法理解区块链的技术原语。以[以太坊](https://ethereum.org/zh/learn/)为例，[时隙](https://ethereum.org/zh/glossary/#slot) (Slot) 是一种时间单位，用于确定网络中[区块提议](https://ethereum.org/zh/developers/docs/consensus-mechanisms/pos/block-proposal/)的频率，设计目的是让[验证者](https://ethereum.org/zh/glossary/#validator)有机会提议新区块。在以太坊中，每12秒为一个时隙，验证者可以在每个时隙中提议区块。

在翻译之前，我们已经对技术原语有足够了解，对于`One Block Producer per Slot`，我们知道作者想说明的是：在排除空时隙的情况下，每个时隙都会有一个验证者提议、打包区块。因此可以将其翻译为：`每个时隙 (Slot) 对应一个区块生产者`。

#### 对专业术语附注解释

在上述博客节选的翻译中，我们保留了`时隙`对应的英文单词`Slot`，并为其添加了名词解释超链接。读者可以通过链接阅读以太坊基金会关于`时隙`解释的中文文档，详细了解`时隙`的名词解释及技术原语。这么做的好处，读者会对`Slot`的名词概念和相关技术原语保留印象，再次看到涉及该名词的内容，阅读会轻松得多。

#### 演化不符合技术语境的单词语义

在上述博客节选的谷歌自动翻译中，`inclusion`被翻译为`包含`，这看起来并没有什么错误，`inclusion`的普遍用法即为`包含`。正因为我们对区块链技术原语的了解，我们知道，此处的`inclusion`指的是打包 (区块)，意为将用户的交易打包进某个区块中，以形成链上区块。因此，应将`inclusion`翻译为`打包`。

#### 消除可能存在的歧义隐患

我们需要更换一个翻译示例，接下来，以我们最近翻译的Solv Protocol Documentation中的两张图片的标题为例，此处为标题的原文链接：[段落原文](https://docs.solv.finance/solv-documentation/getting-started/the-state-of-bitcoin#proven-demand)

**英文原文：**

<figure><img src="/files/GHmnC9SndEH8Xpty6mCd" alt="" width="563"><figcaption></figcaption></figure>

**ChatGPT GPT-4o 翻译结果：**

<figure><img src="/files/GnC7r39PK8z8YEeKeDHH" alt="" width="563"><figcaption></figcaption></figure>

**DeepL Pro 翻译结果：**

<figure><img src="/files/o7qJ2iLCDKSL9POpkfiM" alt="" width="563"><figcaption></figcaption></figure>

无可争议的是，GPT-4o和DeepL Pro是目前除人工翻译外，最优秀的翻译工具。对于上述示例，这两款工具的翻译结果毫无差别，但只有我们自己知道，`Solv Protocol’s Bitcoin Holdings Is Ranked 5th Among Chains`翻译为`Solv协议的比特币持有量在区块链中排名第五`并不合适。

因为如果将`Holdings`翻译为其最常用的含义：`持有量`，可能会被协议用户错误理解——我的比特币怎么变成协议持有了，这是否存在隐患。

因此，在此处，我们演化了`Holdings`的原本含义，将其翻译为`存款量`。

我们试图将这句话翻译为：`Solv协议的比特币存款量在区块链中排名第五`，该翻译结果很好的消除了可能会产生的用户误会，阐明了Solv协议中的比特币资产是用户的存款，而不是被协议私自持有，不会被挪作他用。

但是，上述翻译结果我们并不满意，因为其并没有在感官上刺激到读者，引导读者阅读图片信息。

#### 对文档结构做出合理优化

在上述图片标题翻译中，我们根据上下文，揣摩作者试图向读者传达的实际信息，对文档结构做出优化。最终结果如下：

**原文标题 1：**

Solv Protocol’s Bitcoin Holdings Is Ranked 5th Among Chains

我们的翻译结果：

与L1 / ETH L2 / BTC L2比较：Solv的$BTC存款量位列第五

**原文标题 2：**

Solv Protocol’s Bitcoin Holdings Is Ranked 7th Among Bitcoin ETFs & Ethereum

我们的翻译结果：

与BTC ETFs / Ethereum比较：Solv的$BTC存款量位列第七

通过阅读原文上下文，我们了解到作者试图向读者强调Solv的比特币存款量排名很靠前这个事实，但没有通过文字具体阐述，而是使用了两张对比图。因此，我们我们使用了 “XXX: XXXXXX” 的结构，在标题里简明扼要的表述了图片试图说明的信息，以帮助读者提前理解图片信息，以引导读者阅读图片。

### **DocsZH 存在的意义**

正如DocsZH slogan所说，我们致力于前沿区块链技术文档的中文本地化，这显然是一个又脏又累的活。但在Crypto层林世界里，华人一度占据主导地位，从川西的水电站到被称为“三大”的交易所，从华人首富CZ到联合国特权代表Justin Sun，从古典派的ICOer到流行派的e-beggar，以中文为母语的Crypto猎人生生不息。

在ICO的荒蛮时代，Crypto层林里的古典猎人并不需要过多的用户教育，只有简单的“可以转币了”。随着行业的发展和迭代，生存越来越依赖于对行业的深度了解，项目迭代成协议，打币迭代成DeFi。每一年甚至于每个月，都有不同的行业叙事，Layer、Restaking，Ordinals等等。

受限于语言环境和区块链专业的技术原语，中文用户试图了解某个协议的技术路径，未来路线，参与方式等信息是有阻碍的，自动中文翻译并不能很友好的将内容还原成协议想表达的真实意图，如同`gm`和`早安`。这可能对中文Crypto猎人造成安全隐患，甚至蒙受损失，例如：将资产质押进了DeFi，却无法自主的完成赎回操作；将资产铸造成了某种稳定币，却不了解存在价格脱锚。

这些并非不可避免，几乎所有协议都会在文档或博客里详细说明和解释，内容包括但不限于：协议技术介绍，协议资产介绍，DApp功能介绍，DApp操作流程，操作风险说明等。因此，只需要将协议文档或博客翻译为中文，相信大部分中文区Crypto猎人都会主动去了解所参与的协议，这关系着个人的资产安全。

**以上，也是DocsZH的价值所在。**

### 换种方式做Web3黑奴

长话短说，缺贡献者，召唤e-beggar，加入我们！

#### **勾搭方式**

* 推特私信，我的推特：[@Scaling\_News](https://x.com/Scaling_News)

#### **贡献者要求**

* 能延迟满足，劳而无获不搞对立，这是e-beggar常态，所以丑话说在前头。
* 能主动学习，快速掌握ChatGPT, Notion, DeepL, Gitbook等工具的熟练使用。

#### **按劳分配**

* DocsZH会力所能及的申请一些具有潜在回报的社区贡献计划，采用proof-of-work进行贡献分配。

#### **初步分配方案：**

1. **Scaling News Treasury - 30%**

* Managed by multi-signature account, transfer requires creating a proposal.
* Used to pay for ChatGPT Plus, Notion Plus, DeepL Ultimate, Gitbook Enterprise, domain, server and other expenses, the team relies on these tools for collaboration.

2. **Core Contributors & Advisors - 30%**

* 20% is available on day 1 and the rest is vested over 12 months.
* They are always with Scaling News, dedicated to solving the toughest problems.

3. **General Contributors - 40%**

* Adopting proof-of-work mechanism, distribution by contribution output.
* We offer incentives in exchange for contributors joining. They may not be long-term companions, but they are indeed important partners.

最后的**分配方案**是不是像极了项目方的TGE文档，给你一种马上就可以claim的错觉。

非也，论e-beggar的自我养成，勾搭我之前，请将**初步分配方案**翻译为简体中文，DM给我。

**Da Da Da... Let's have fun together... by Chin.**


# 介绍 Monad

Monad 是与以太坊兼容的高性能 Layer1，Monad 实质性推动了区块链去中心化和扩容间博弈的有效边界。

Monad 在以下四个方面进行了优化，使区块链的吞吐量达到每秒 10,000 笔交易（tps）：

* [MonadBFT 共识机制](/monad-docs/monad-architecture/consensus/monadbft)
* [延迟执行（Deferred Execution）](/monad-docs/monad-architecture/consensus/deferred-execution)
* [并行执行（Parallel Execution）](/monad-docs/monad-architecture/execution/parallel-execution)
* [MonadDb 数据库](/monad-docs/monad-architecture/execution/monaddb)

Monad 的优化解决了现有区块链的瓶颈问题，同时为应用程序开发人员（完全兼容 EVM 字节码）和用户（兼容以太坊 RPC API）保留了完全兼容性。因此，丰富的以太坊工具和应用密码学研究可以无缝接入到 Monad，同时受益于 Monad 的高吞吐量和交易规模：

* 应用程序（在以太坊上构建的任何 Dapp）
* 开发人员工具（如：Hardhat、Apeworx、Foundry）
* 钱包（如：MetaMask）
* 链上分析/索引工具（如：Etherscan、Dune）

Monad 客户端以性能为核心，采用 C++ 和 Rust 语言编写。下文将介绍 Monad 的主要优化及用户交互。


# 为什么选择区块链？

“是什么” 和 “为什么” 的简单心智选择。

区块链是不同参与者就以下两件事达成的去中心化协议：

1. 交易的官方排序（账本）。
2. 官方全局状态，包括用户账户余额和各种程序的状态。

在以太坊等现代区块链中，交易包括余额转移、创建新程序以及对现有程序的函数调用。到目前为止，所有交易的总结果就是当前状态，这就是为什么（1）的一致性意味着（2）的一致性。

区块链系统有一组协议规则，这些规则描述了当前同步的分布式节点集将如何相互通信，以商定每个节点应该使用的新交易列表。归纳法使节点保持同步：它们从相同的状态开始，同步相同的交易，因此在使用新的交易列表结束时，它们仍然具有一致的状态。(本文将忽略这种节点系统如何达成一致的细节，但你可以参阅 Monad [共识机制](/monad-docs/monad-architecture/consensus)的文档，了解更多）。

共享全局状态用于开发去中心化应用程序——链上程序，即在区块链系统的每个节点上运行的应用程序。去中心化应用程序是一个代码块（以及长期的、特定于应用程序的状态），可以被任何用户调用，用户只需提交指向该应用程序功能的交易即可，区块链中的每个节点都负责正确执行被调用的字节码，重复工作可保证每个节点的诚实。

### 去中心化应用程序示例

去中心化应用程序可以实现我们可能期望以中心化方式实现的功能，去中心化应用程序的一个非常简单的例子就是虚拟银行（在加密领域通常被称为借贷协议）。

在现实世界中，银行是吸收存款并以较高利率放贷的企业，银行赚取存款和借贷之间的利差。借款人获得贷款，去做一些有经济效益的事情，存款人则从存款中赚取利息，大家都是赢家！

区块链虚拟银行只是一个拥有四种主要功能的应用程序：`存款`、`取款`、`借款`、`还款` ，每种功能的逻辑主要是记账，以确保正确跟踪存款和贷款：

```
class VirtualBank:
  def deposit(sender, amount):
    # transfer amount from sender to myself (the bank)
    # do internal bookkeeping to credit the sender

  def withdraw(sender, amount):
    # ensure the sender had enough on deposit
    # do internal bookkeeping to debit the sender
    # transfer amount from myself (the bank) to sender

  def borrow(sender, amount):
    # ...

  def repay(sender, amount);
    # ...
```

在以太坊或 Monad 中，有人可以为这个虚拟银行编写代码并上传，然后任何人都可以利用它进行借贷，与其所在国实体银行相比，区块链虚拟银行服务可能方便得多。

这个简单的例子显示了去中心化应用程序的威力，这里还有其他优势值得一提：

* **开放式应用程序接口/可组合性**：去中心化应用程序可被其他去中心化应用程序原子调用，允许开发人员通过堆栈现有组件来构建更复杂的程序功能。
* **透明性**：去中心化应用程序的功能逻辑纯粹通过代码实现，因此任何人都可以审查程序的安全性，状态是透明和可审计的，默认情况下在 DeFi 中进行开源证明。
* **抗审查和可信中立性:** 任何人都可以无需许可地向区块链提交交易或上传应用程序。
* **全球覆盖**：任何人只要能上网，就能获得重要的金融服务，包括 unbanked/underbanked 用户。


# 为什么选择 Monad: 去中心化+性能

### 去中心化很重要

区块链有几个主要组成部分：

* **共识机制**，用于就添加到分类账的交易确认达成一致。
* **执行/存储系统**，用于维持区块链活动状态。

在提高这些组件的性能时，可以偷工减料，例如要求所有节点在物理上相互靠近（以节省达成共识的开销），或要求大量使用 RAM（以将大部分或全部状态缓存在内存中），但这是以牺牲去中心化为代价的。

而去中心化正是关键所在！

正如”[为什么是区块链](https://docs.monad.xyz/technical-discussion/why-blockchain)“章节中所讨论的，去中心化的全局状态共享允许多方协调，同时依赖于单一、共享、客观的真实消息源。去中心化是问题的关键，由一小群节点操作员（或在极端情况下，一个操作员！）维护的区块链将无法拥有去信任化、可信的中立性和抗审查性等特征。

对于任何区块链网络来说，去中心化都应该是主要关注点，提高性能不应以牺牲去中心化为代价。

### 当下区块链性能瓶颈

以太坊当前的执行限制（1.25M Gas/每秒）设置得比较保守，这样做有几个理由：

* 低效的存储访问模式
* 单线程执行
* 执行时间预算非常有限，因为没有执行就无法达成共识
* 对状态增长的担忧，以及状态增长对未来状态访问成本的影响

Monad 通过改进算法和架构来解决这些局限性，开创了多项创新，有望在未来几年成为以太坊的标准。保持高度去中心化，同时进行实质性的性能优化，这是关键的考虑因素。

### 通过优化解决瓶颈问题

Monad 在以下四个主要方面实现了流水线作业并有其他优化，从而使以太坊虚拟机具有卓越的性能，极大地推动了区块链的去中心化和可扩展性博弈的有效边界。下文将介绍这些主要方面的优化：

* [MonadBFT 共识机制](/monad-docs/monad-architecture/consensus/monadbft)
* [延迟执行（Deferred Execution）](/monad-docs/monad-architecture/consensus/deferred-execution)
* [并行执行（Parallel Execution）](/monad-docs/monad-architecture/execution/parallel-execution)
* [MonadDb 数据库](/monad-docs/monad-architecture/execution/monaddb)


# 面向用户的 Monad

Monad 是与以太坊兼容的高性能 Layer1，为用户提供了两全其美的解决方案：**可复制性**和**性能**。

从可复制性的角度来看，Monad 为以太坊虚拟机（EVM）提供了**完整的字节码兼容性**，因此在太坊上构建的应用程序无需修改代码即可复制到 Monad；并且提供了**完整的以太坊RPC兼容性**，因此用户可以使用 MetaMask 或 Etherscan 等基础设施。

从性能角度来看，Monad 拥有 **10,000 tps** 的吞吐量，即每天 10 亿笔的交易量，另外 Monad 的**出块时间和区块确认时间仅为 1 秒**。这使得 Monad 能够支持比现有区块链更多的用户高并发交互，同时拥有更低廉的单笔交易成本。

### 对比以太坊，Monad 有什么相似之处？

从用户角度来看，Monad 的链上操作与以太坊非常相似。你可以使用熟悉的钱包（如 MetaMask）或区块浏览器（如 Etherscan）来签署或查看交易，在以太坊上构建的应用程序也可以复制到 Monad 上，无需修改代码，因此用户可以在 Monad 上使用最喜欢的以太坊应用程序。Monad 中的地址空间与以太坊中的地址空间相同，因此用户可以使用现有的密钥在 Monad 上创建钱包。

与以太坊一样，Monad 也具有 linear blocks 和区块内 linear ordering 排序的特点。

与以太坊一样，Monad 也是一个由去中心化的验证者维护的权益证明网络。任何人都可以运行一个节点来独立验证交易的执行情况，并且已经采取了大量措施来保持最低的硬件要求。

### 对比以太坊，Monad 有什么不同之处？

Monad 通过在以太坊虚拟机中引入**并行执行（parallel execution）**&#x548C; **超标量流水线（superscalar pipelining）**&#x6280;术，使卓越的性能成为可能。

**并行执行** 是指利用多个内核和线程有策略地并行执行交易，同时仍按原始排序提交交易结果。虽然交易在"内部"是并行执行的，但从用户和开发人员的角度来看，它们是串行执行的；一系列交易的结果总是相同的，就像这些交易是一个接一个地执行一样。

**超标量流水线** 是一种将执行单元划分为不同阶段，并且并行执行这些阶段的技术。可以通过以下图例阐明该技术：

<div align="center" data-full-width="false"><figure><img src="/files/Bm9NinS8jYvWKZANiPED" alt=""><figcaption><p>pipelining 作业的熟悉案例：智能洗衣<br>上图：普通洗衣作业；下图：pipelined 洗衣作业<br>资料来源：<a href="https://www.cs.fsu.edu/~hawkes/cda3101lects/chap6/index.html?$$$F6.1.html$$$">Prof. Lois Hawkes, FSU</a></p></figcaption></figure></div>

当洗四件衣服时，“普通洗衣作业”的策略是在洗第二件衣服之前，完成第一件衣服的洗涤、烘干、折叠和储存；“pipelined 洗衣作业”的策略是当第一件衣服洗涤完成进入烘干机时，开始洗涤第二件衣服，通过同时利用多个资源来更有效地完成工作。

Monad 引入了 pipelining 执行技术，以解决现有区块链在状态存储、交易处理和分布式共识中的瓶颈。具体而言，Monad 在以下四个方面引入了 pipelining 技术和其他优化：

* [MonadBFT 共识机制](/monad-docs/monad-architecture/consensus/monadbft)（pipelined HotStuff 共识机制，以及更多的研究改进）
* [Deferred Execution / 延迟执行](/monad-docs/monad-architecture/consensus/deferred-execution)（在达成共识和执行之间进行 pipelining 作业，以大幅增加执行预算）
* [Parallel Execution / 并行执行](/monad-docs/monad-architecture/execution/parallel-execution)
* [MonadDb 数据库](/monad-docs/monad-architecture/execution/monaddb)（高性能状态后端）

Monad 客户端采用 C++ 和 Rust 语言编写，它反映了在这些架构上的优化，为去中心化应用程序提供了一个平台，可以真正扩展到全球范围。

### 应该关心什么？

去中心化应用程序是中心化服务的替代品，具有若干显著优势：

* **开放式应用程序接口和可组合性**：去中心化的应用程序可以被其他去中心化应用程序原子调用，允许开发人员通过堆栈现有组件来构建更复杂的功能。
* **透明性**：应用程序的逻辑纯粹通过代码表达，因此任何人都可以审查程序的安全性，状态是透明和可审计的，默认情况下在DeFi中进行开源证明。
* **抗审查和可信中立性:** 任何人都可以无需许可地向网络提交交易或上传应用程序。
* **全球覆盖**：任何人只要能上网，就能获得重要的金融服务，包括 unbanked/underbanked 用户。

然而，去中心化应用程序需要廉价、高性能的基础设施，才能达到预期的影响水平。一个拥有 100 万日活跃用户（DAUs）和每个用户每天进行10笔交易的应用程序，每天需要吞吐 1000 万笔交易，即 100 tps。快速浏览一下 [L2Beat](https://l2beat.com/scaling/activity)（一个研究 EVM 兼容的 Layer1 和 Layer2 区块链网络吞吐量和去中心化程度的网站）就会发现，目前没有任何EVM区块链支持或接近 100 tps 的吞吐量水平。

Monad 极大地提高了与 EVM 兼容的区块链网络的性能，开创了多项创新，有望在未来几年成为以太坊的标准。

有了 Monad，开发人员、用户和研究人员可以采用大量现有的为 EVM 而构建的应用程序、库和应用密码学研究。

### 如何使用 Monad ？

Monad 的首个公共测试网将在未来几个月内上线。

届时，用户可以在兼容以太坊的钱包中添加相应的 RPC URL 和 链 ID，然后像使用其他兼容以太坊的区块链一样开始使用 Monad 。在此之前，敬请期待！


# 面向开发人员的 Monad

Monad 是与以太坊兼容的 Layer1 区块链，吞吐量为 10,000 tps，区块时间为1秒，采用[单时隙确定性](https://ethereum.org/zh/roadmap/single-slot-finality/)（single-slot finality）。

Monad 对以太坊虚拟机的优化符合[上海升级](https://www.evm.codes/?fork=shanghai)的要求，使用 Monad 执行环境模拟以太坊历史交易会产生相同的结果。Monad 还与以太坊 RPC 完全兼容，因此用户可以使用 MetaMask 和 Etherscan 等熟悉的工具与 Monad 进行交互。

Monad 通过引入以下四项重大创新实现了这些性能的优化：

* [MonadBFT 共识机制](/monad-docs/monad-architecture/consensus/monadbft)（pipelined HotStuff 共识机制，以及更多的研究改进）
* [Deferred Execution / 延迟执行](/monad-docs/monad-architecture/consensus/deferred-execution)（在达成共识和执行之间进行 pipelining 作业，以大幅增加执行预算）
* [Parallel Execution / 并行执行](/monad-docs/monad-architecture/execution/parallel-execution)
* [MonadDb 数据库](/monad-docs/monad-architecture/execution/monaddb)（高性能状态后端）

虽然 Monad 具有并行执行和流水线执行功能，但需要注意的是，Monad 中的区块是线性的，交易在每个区块中也是线性排序的。

### 交易格式

<table><thead><tr><th width="128">相关属性</th><th>属性描述</th></tr></thead><tbody><tr><td>地址空间</td><td>使用 ECDSA 匹配以太坊 20 字节地址</td></tr><tr><td>交易格式</td><td><p>符合 <a href="https://ethereum.org/zh/developers/docs/transactions/">以太坊</a> </p><p>符合 <a href="https://eips.ethereum.org/EIPS/eip-2718">EIP-2718</a>，使用 <a href="https://ethereum.org/zh/developers/docs/data-structures-and-encoding/rlp/">RLP</a> 编码。支持但不要求访问列表（<a href="https://eips.ethereum.org/EIPS/eip-2930">EIP-2930</a>）。</p></td></tr><tr><td>钱包兼容性</td><td>Monad 与 Metamask 等标准以太坊钱包兼容。唯一需要更改的是 RPC URL 和 ChainId。</td></tr></tbody></table>

### 智能合约

* Monad 支持 EVM 字节码，与以太坊字节码等效，支持所有 [操作码](https://www.evm.codes/?fork=shanghai)（截至上海升级）。

### 共识机制

<table><thead><tr><th width="134">相关属性</th><th>属性描述</th></tr></thead><tbody><tr><td>抗 51% 攻击</td><td>权益证明（PoS）</td></tr><tr><td>委托投票权</td><td>允许（协议原生）</td></tr><tr><td>共识机制和流水线机制</td><td><p><a href="/pages/T05vU59KLcUxPsfB1f5V">MonadBFT</a> 是一种基于领导人选举的共识算法，用于在部分同步条件下就交易排序和打包达成一致。广义上，它是 HotStuff 的衍生算法，并进行了额外的研究优化。</p><p></p><p>MonadBFT 是一种流水线式两阶段 BFT 算法，在一般情况下具有线性的 communication overhead。与大多数 BFT 算法一样，通信分阶段进行，在每个阶段，领导人向投票者发送签名信息，投票者再发回签名回执。流水线作业允许区块 <code>k</code> 的法定人数证书（QC）或超时证书（TC）包含区块 <code>k+1</code> 的提议，超时会进行二次消息传递。</p></td></tr><tr><td>区块时间</td><td>1秒</td></tr><tr><td>最终确定性</td><td>单时隙确定性，一旦2/3的验证者对整块提议投了"支持"票，区块即最终确定。</td></tr><tr><td>内存池</td><td>有<a href="/pages/sdGRyLDNSO7jvRhqfUZ5">内存池</a>，交易采用纠删码，并使用 broadcast tree 进行通信，以提高效率。</td></tr><tr><td>抵制垃圾交易</td><td>用户为交易打包进区块（“<a href="/pages/dldeiOBimXocPKRDWp6E">传输成本</a>”）和交易执行（“执行成本”）付费。</td></tr><tr><td>共识参与者</td><td>直接共识参与者对区块提议进行投票，并担任领导人。要成为直接参与者，节点必须至少有 <code>MinStake</code> 质押，并且按投票权排在 <code>MaxConsensusNodes</code> 参与者的前列，这些参数在代码中设定。</td></tr><tr><td>交易哈希</td><td>为提高效率，区块提议<a href="/pages/sdGRyLDNSO7jvRhqfUZ5">仅通过哈希值</a>来引用交易。如果一个节点没有参与交易，它将通过哈希向邻居节点请求交易。</td></tr><tr><td>延迟执行和燃料成本</td><td><p>在 Monad 中，共识和执行以流水线方式进行。节点在执行正式交易排序（<a href="/pages/cMIw5fSN91ghvMw16sN6">延迟执行</a>）之前，会就该排序达成共识，执行结果并不是达成共识的先决条件。</p><p></p><p>在区块链中，通常执行是达成共识的先决条件，而执行的时间预算只占区块时间的一小部分。将共识和执行流水线化后，Monad 就可以将全部区块时间用于共识和执行。</p><p></p><p>区块提议由交易哈希有序列表和 <code>D</code> 个区块前的状态 merkle 根组成，延迟参数 <code>D</code> 在代码中设定，预计最初 <code>D = 10</code>。</p><p></p><p>用户必须支付费用（"<a href="/pages/dldeiOBimXocPKRDWp6E">传输费用</a>"）才能将交易打包进区块。对于每个交易账户，节点保留两个余额：</p><p>• 储备余额，用于支付传输费用</p><p>• 执行余额，用于支付执行费用</p><p></p><p>当交易被纳入区块（共识）时，传输费用从储备余额中扣除；当交易被执行时，传输费用从执行余额中扣除（双重费用）；在 <code>D</code> 个区块的延迟期后，将剩余费用偿还给储备余额。</p><p></p><p>账户的储备余额实际是"待处理"交易的费用预算，它的存在是为了确保只有已支付交易费用的交易被打包进区块。</p><p></p><p>每个账户都有一个预留储备余额，该余额可通过与内置的智能合约交互进行更改，例如，对于计划发送大量交易的 EOA 账户而言。</p></td></tr><tr><td>状态确认</td><td><p>最终确定性发生在共识时间，在这一点上，交易的官方排序是神圣的。对于任何全节点来说，结果都是完全确定的，它们通常会在1秒内执行该新块的交易。</p><p></p><p>状态 merkle 根的 <code>D</code> 区块延迟仅用于状态根验证，例如允许节点验证自己没有计算错误。</p></td></tr></tbody></table>

### 执行机制

每个区块的执行阶段，在该区块达成共识后开始，并允许节点继续就后续区块达成共识。

#### **并行执行**

交易是按线性顺序排列的，执行作业是得出串行执行交易列表后的状态，最简单的方法就是一个接一个地执行交易。我们能做得更好吗？可以！

Monad 采用[并行执行](/monad-docs/monad-architecture/execution/parallel-execution)：

* 执行器是执行交易的虚拟机，Monad 可并行运行多个执行器。
* 执行器接收一笔交易并产生一个**结果**，结果是该笔交易的**输入**和**输出**列表，其中输入是执行过程 SLOAD 的（ContractAddress、Slot、Value）元组，输出是交易结果 SSTORE 的（ContractAddress、Slot、Value）元组。
* 结果最初在待处理状态下产生，然后按照交易的原始排序提交，当结果提交时，其输出会更新当前状态。在结果提交时，Monad 会检查其输入是否仍与当前状态匹配，如果不匹配，Monad 会重新安排交易。由于采用了并发控制，Monad 能确保生成与串行执行交易相同的结果。
* 当交易被重新安排时，许多或全部需要的输入都已被缓存，因此重新执行的成本通常相对较低。需要注意的是，在重新执行时，交易可能会生成与上次执行不同的输入集。

#### **MonadDb：高性能状态后端**

所有交易的活动状态都存储在 [MonadDb](/monad-docs/monad-architecture/execution/monaddb) 中，MonadDb 是由固态硬盘（SSD）组成的存储后端，专为存储 merkle trie 数据而优化。该数据更新是分批进行的，因此可以提高 merkle 根的更新效率。

MonadDb 实现了内存缓存，并使用 [asio](https://think-async.com/Asio/) 实现了高效的异步读写。节点至少配置 32GB 内存，以获得最佳性能。

### 与以太坊的比较：用户角度

| 相关属性                                                                                  | Ethereum                                                                   | Monad                                                                      |
| ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| 每秒交易量（合约调用和转账）                                                                        | \~10次                                                                      | \~10,000次                                                                  |
| 区块时间                                                                                  | 12秒                                                                        | 1秒                                                                         |
| 最终确定性                                                                                 | [2 epochs](https://hackmd.io/@prysmaticlabs/finality) (12-18分钟)            | 单时隙确定性 (1秒)                                                                |
| 字节码标准                                                                                 | EVM ([上海升级](https://www.evm.codes/?fork=shanghai))                         | EVM ([上海升级](https://www.evm.codes/?fork=shanghai))                         |
| RPC API                                                                               | [Ethereum RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/) | [Ethereum RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/) |
| 密码学                                                                                   | ECDSA                                                                      | ECDSA                                                                      |
| 账户                                                                                    | ECDSA 算法中，keccak-256 公钥的最后20个字节                                            | ECDSA 算法中，keccak-256公钥的最后20个字节                                             |
| 共识机制                                                                                  | Gasper (Casper-FFG finality gadget + LMD-GHOST fork-choice rule)           | MonadBFT (pipelined HotStuff 以及更多的研究优化)                                    |
| 内存池                                                                                   | 有                                                                          | 有                                                                          |
| 交易排序                                                                                  | <p>Leader's discretion </p><p>(实际：PBS)</p>                                 | <p>Leader's discretion </p><p>(默认方案：PGA)</p>                               |
| 抗51%攻击                                                                                | PoS                                                                        | PoS                                                                        |
| 投票权委托                                                                                 | 不允许，需通过 LSTs 实现                                                            | 允许                                                                         |
| [硬件要求](https://docs.monad.xyz/using-monad/running-a-node/hardware-requirements) (全节点) | <p>4核 CPU </p><p>16GB 内存 </p><p>1TB 固态硬盘 </p><p>25Mbit/s 带宽</p>            | <p>16核 CPU</p><p>32GB 内存</p><p>2TB 固态硬盘</p><p>100Mbit/s 带宽</p>             |


# Devnet 开发者申请

目前，Monad 正在内部开发网中运行，开发者可以按照以下步骤，申请加入内部开发网。

* 添加 Monad DevRel 工作人员微信：Box，微信号：box1234567890
* 加入全球开发者社区：[Monad Developer Discord](https://discord.com/invite/monaddev)
* 填写申请表：<https://tally.so/r/nWDeAR>


# 快速入门


# 部署合约


# 使用 Foundry 部署合约

[Foundry](https://book.getfoundry.sh/) 是一个快速、可复制的模块化工具包，适用于 Rust 语言编写的以太坊应用程序的开发。

### 先决条件

开始之前，需要安装以下工具：

* [Rust](https://doc.rust-lang.org/book/)
* [Cargo](https://doc.rust-lang.org/cargo/index.html)

### 安装 `foundryup`

Foundryup 是 Foundry 工具链的官方安装程序。

```bash
curl -L https://foundry.paradigm.xyz
```

按照屏幕上的说明操作，安装 Foundryup，接下来便可以在本地 CLI 中使用 `foundryup` 命令。

### 安装 `forge`、`cast`、`anvil` 和 `chisel` 文件 <a href="#id-2-installing-forge-cast-anvil-and-chisel-binaries" id="id-2-installing-forge-cast-anvil-and-chisel-binaries"></a>

```bash
foundryup
```

{% hint style="info" %}
**注意：**&#x5982;果你使用的是 Windows 系统，则需要安装并使用 Git BASH 或 WSL 终端，因为 Foundryup 目前不支持 Powershell 或命令提示符 (Cmd）。
{% endhint %}

### 创建 Foundry 示例项目

{% hint style="info" %}
**提示：**&#x4F60;可以使用 `foundry-monad` 模板来创建一个新项目。

[Foundry-Monad](https://github.com/monad-developers/foundry-monad) 是一个具有 Monad 配置的 Foundry 模板。使用该模板，开发者不必在 Foundry 中针对 Monad 网络进行初始配置。
{% endhint %}

运行以下命令，使用 `foundry-monad` 模板，创建一个新的 foundry 项目：

```bash
forge init --template monad-developers/foundry-monad [project_name]
```

或者，可以运行以下命令，创建默认的 foundry 项目：

```bash
forge init [project_name]
```

### 修改 Foundry 配置 <a href="#id-4-modify-foundry-configuration" id="id-4-modify-foundry-configuration"></a>

{% hint style="info" %}
**注意：**&#x76EE;前，开发网 RPC 和区块浏览器尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

{% hint style="info" %}
**注意：**&#x4E0A;述步骤&#x4E2D;**，**&#x5982;果你使用了 `foundry-monad` 模板，请跳过本步骤。
{% endhint %}

更新 `foundry.toml` 文件以添加 Monad 配置：

```bash
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

# Monad Configuration
# TODO: Add RPC URL and Chain ID
eth-rpc-url="MONAD_RPC_URL"
chain_id = "MONAD_CHAIN_ID"

# TODO: Add Explorer URL and Chain ID
[etherscan]
monadDevnet = { key = "DUMMY_VALUE", url = "EXPLORER_URL", chain = MONAD_CHAIN_ID }
```

### 编写智能合约 <a href="#id-5-write-a-smart-contract" id="id-5-write-a-smart-contract"></a>

你可以在 `src` 文件夹下编写智能合约。此项目中已有一个 `Counter` 合约，位于 `src/Counter.sol`。

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Counter {
    uint256 public number;

    function setNumber(uint256 newNumber) public {
        number = newNumber;
    }

    function increment() public {
        number++;
    }
}
```

### 编译智能合约 <a href="#id-6-compile-the-smart-contract" id="id-6-compile-the-smart-contract"></a>

```bash
forge compile
```

编译结果输出在新创建的 `out` 目录下，其中包括 Contract ABI 和 bytecode。

### 部署智能合约 <a href="#id-7-deploy-the-smart-contract" id="id-7-deploy-the-smart-contract"></a>

{% hint style="info" %}
**注意：**&#x5BF9;于合约部署，不建议使用与真实资产相关联的钱包地址及私钥，务必创建一个新钱包或使用仅用于开发的钱包地址。
{% endhint %}

#### 获取测试代币

{% hint style="info" %}
目前，开发网水龙头尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

部署智能合约需要测试网测试代币，可通过测试网水龙头领取。

#### 部署智能合约

{% tabs %}
{% tab title="使用 Keystore（推荐）" %}
Keystore 是 Foundry 项目中使用私钥的一种更安全的方式，因为 keystore 会加密私钥，且可以在任何需要私钥的命令中引用。

运行以下命令，创建新的钱包密钥库：

```bash
cast wallet import <keystore_name> --interactive
```

出现提示时，输入钱包私钥，并设置密码进行加密。

运行以下命令，部署智能合约：

```bash
forge create src/Counter.sol:Counter --account <keystore_name>
```

结果输出如下示例，表示合约成功部署：

```bash
Deployer: 0xB1aB62fdFC104512F594fCa0EF6ddd93FcEAF67b
Deployed to: 0x67329e4dc233512f06c16cF362EC3D44Cdc800e0
Transaction hash: 0xa0a40c299170c9077d321a93ec20c71e91b8aff54dd9fa33f08d6b61f8953ee0
```

{% endtab %}

{% tab title="直接使用钱包私钥" %}
运行以下命令，直接在终端中粘贴私钥，并部署智能合约。

```bash
forge create --private-key <your_private_key> src/Counter.sol:Counter
```

结果输出如下示例，表示合约成功部署：

```bash
Deployer: 0xB1aB62fdFC104512F594fCa0EF6ddd93FcEAF67b
Deployed to: 0x67329e4dc233512f06c16cF362EC3D44Cdc800e0
Transaction hash: 0xa0a40c299170c9077d321a93ec20c71e91b8aff54dd9fa33f08d6b61f8953ee0
```

{% endtab %}
{% endtabs %}

### 后续步骤

{% hint style="info" %}
**注意：**&#x76EE;前，开发网区块浏览器尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

了解如何在 Monad Explorer 上验证合约，请参阅 [验证 Foundry 合约](/monad-docs/getting-started/verify-contract/foundry)。


# 使用 Hardhat 部署合约

[Hardhat](https://hardhat.org/docs) 是一个综合开发环境，由不同组件组成，用于编写、编译、调试和部署智能合约和 dApps。

### 先决条件

开始之前，需要安装以下依赖项：

* [npm](https://docs.npmjs.com/about-npm) (建议`npm 7`以上版本) 或 [yarn](https://yarnpkg.com/getting-started)
* [Node.js](https://nodejs.org/en/download) v18.0.0 或更高版本

{% hint style="info" %}
如果你使用的是 Windows 系统，强烈建议安装并使用 [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/about) 终端来完成以下步骤。
{% endhint %}

### 创建 Hardhat 示例项目

首先，创建一个新的文件夹目录，并导航到该目录：

```bash
mkdir my-hardhat-project && cd my-hardhat-project
```

在该目录中初始化一个新的 Hardhat 项目：

```bash
npx hardhat init
```

在出现 CLI 选择提示时，输入 “y/n“，选择你的首选项，或使用下方推荐的首选项。

```bash
✔ What do you want to do? · Create a TypeScript project (with Viem)
✔ Hardhat project root: · /path/to/my-hardhat-project
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install this sample project's dependencies with npm (hardhat @nomicfoundation/hardhat-toolbox-viem)? (Y/n) · y
```

### 设置配置变量 <a href="#id-2-setting-up-configuration-variables" id="id-2-setting-up-configuration-variables"></a>

Hardhat 项目可以将配置变量用于用户特定值，或用于不应包含在代码存储库中的数据。

{% hint style="info" %}
**注意：**&#x76EE;前，开发网 RPC 尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

运行以下命令，设置配置变量：

```bash
npx hardhat vars set <variable_name>
```

例如，运行以下命令，设置 `MONAD_RPC_URL` 变量：

```bash
npx hardhat vars set MONAD_EXPLORER_URL
```

{% hint style="info" %}
**注意**：在设置 `MONAD_EXPLORER_URL` 配置变量时，请勿包含 `/api` 部分。
{% endhint %}

然后在提示符中，为此变量输入自定义值：

```bash
Enter value: ********************************
```

同样，你还可以设置 `MONAD_CHAIN_ID` 变量。

{% hint style="danger" %}
**警告**：配置变量以纯文本形式存储在磁盘上。对于需要加密保存的敏感或重要数据，请避免使用此功能。你可以运行 `npx hardhat vars path` 查找存储的文件位置。
{% endhint %}

### 更新 `hardhat.config.ts` 文件以生效 `monadDevnet` 配置 <a href="#id-2-update-your-hardhatconfigts-file-to-include-the-monaddevnet-configuration" id="id-2-update-your-hardhatconfigts-file-to-include-the-monaddevnet-configuration"></a>

```bash
import type { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox-viem";
import { vars } from "hardhat/config";

const config: HardhatUserConfig = {
    solidity: "0.8.27",
    ...
    etherscan: {
        apiKey: `DUMMY_VALUE_FOR_BLOCKSCOUT`,
        customChains: [
            {
                network: "monadDevnet",
                chainId: Number(vars.get("MONAD_CHAIN_ID")),
                urls: {
                    browserURL: vars.get("MONAD_EXPLORER_URL"),
                    apiURL: `${vars.get("MONAD_EXPLORER_URL")}/api`,
                },
            },
            ...
        ],
    },
};

export default config;
```

### 编写智能合约 <a href="#id-4-write-a-smart-contract" id="id-4-write-a-smart-contract"></a>

你可以在 `contracts` 目录中创建新的合约，下方示例中，将创建名为`GMonad.sol`的智能合约：

```bash
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract GMonad {
    function sayGmonad() public pure returns (string memory) {
        return "gmonad";
    }
}
```

### 编译智能合约 <a href="#id-5-compile-the-smart-contract" id="id-5-compile-the-smart-contract"></a>

```bash
npx hardhat compile
```

结果输出如下示例，表示合约成功编译：

```bash
Compiled 2 Solidity file successfully (evm target: paris).
```

{% hint style="info" %}
**注意**：如果你没有从 Hardhat 中删除默认的 `Lock.sol` 合约，则`GMonad.sol` 和`Lock.sol`均会被编译。
{% endhint %}

### 部署智能合约 <a href="#id-6-deploy-the-smart-contract" id="id-6-deploy-the-smart-contract"></a>

你可以使用声明式部署系统 [Hardhat Ignition](https://hardhat.org/ignition/docs/getting-started#overview) 来部署合约。

你可以使用示例项目中附带的 Ignition 模块部署 `GMonad` 合约。

#### 创建 Hardhat Ignition 模块 <a href="#creating-a-hardhat-ignition-module" id="creating-a-hardhat-ignition-module"></a>

运行以下命令，在 `ignition/modules` 目录中创建一个名为 `GMonad.ts` 的文件：

```solidity
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

const GMonadModule = buildModule("GMonadModule", (m) => {
    const gmonad = m.contract("GMonad");

    return { gmonad };
});

module.exports = GMonadModule;
```

现在，你可以进行合约部署了。

#### 部署智能合约 <a href="#deploying-the-smart-contract" id="deploying-the-smart-contract"></a>

```bash
npx hardhat ignition deploy ./ignition/modules/GMonad.ts --network monadDevnet
```

当出现 `Confirm` 提示时，选择 `yes` ：

```bash
✔ Confirm deploy to network monadDevnet (<chain_id>)? … yes
```

结果输出如下示例，表示合约成功部署：

```bash
✔ Confirm deploy to network monadDevnet (<chain_id>)? … yes
Hardhat Ignition 🚀

Deploying [ GMonadModule ]

Batch #1
  Executed GMonadModule#GMonad

[ GMonadModule ] successfully deployed 🚀

Deployed Addresses

GMonadModule#GMonad - <contract_address>
```

### 后续步骤

了解如何在 Monad Explorer 上验证合约，请参阅 [验证 Hardhat 合约](/monad-docs/getting-started/verify-contract/hardhat)。


# 验证合约


# 验证 Foundry 合约

{% hint style="info" %}
**注意：**&#x76EE;前，开发网 RPC 和区块浏览器尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

{% tabs %}
{% tab title="Foundry Monad 模板（推荐）" %}
如果你使用 [`foundry-monad`](https://github.com/monad-developers/foundry-monad) 模板部署的合约，请运行以下命令：

```bash
forge verify-contract <contract_address> <contract_name>
```

你需要将 `contract_address` 和 `contract_name` 更换为你部署时使用的信息，例如：

```bash
forge verify-contract 0x195B9401D1BF64D4D4FFbEecD10aE8c41bEBA453 src/Counter.sol:Counter
```

结果输出如下示例，表示合约成功验证：

```bash
Start verifying contract `0x1355a4f7829161a4d27BDb8970D32b89ef89A1Be`

Submitting verification for [src/Counter.sol:Counter] 0x1355a4f7829161a4d27BDb8970D32b89ef89A1Be.
Submitted contract for verification:
    Response: `OK`
    GUID: `1355a4f7829161a4d27bdb8970d32b89ef89a1be67448d78`
```

{% endtab %}

{% tab title="默认 Foundry 项目 " %}

### 使用 Monad 配置更新 `foundry.toml` <a href="#id-1-update-foundrytoml-with-monad-configuration" id="id-1-update-foundrytoml-with-monad-configuration"></a>

{% hint style="info" %}
**提示**：如果你使用 [`foundry-monad`](https://github.com/monad-developers/foundry-monad) 模板部署的合约，则可以跳过本步骤。
{% endhint %}

```bash
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

# Monad Configuration
# TODO: Add RPC URL and Chain ID
eth-rpc-url="MONAD_RPC_URL"
chain_id = "MONAD_CHAIN_ID"


# TODO: Add Explorer URL and Chain ID
[etherscan]
monadDevnet = { key = "DUMMY_VALUE", url = "EXPLORER_URL", chain = MONAD_CHAIN_ID }
```

### 验证合约 <a href="#id-2-verify-the-contract-using-the-command-below" id="id-2-verify-the-contract-using-the-command-below"></a>

运行以下命令，验证合约：

```bash
forge verify-contract <contract_address> <contract_name>
```

你需要将 `contract_address` 和 `contract_name` 更换为你部署时使用的信息，例如：

```bash
forge verify-contract 0x195B9401D1BF64D4D4FFbEecD10aE8c41bEBA453 src/Counter.sol:Counter
```

结果输出如下示例，表示合约成功验证：

```bash
Start verifying contract `0x1355a4f7829161a4d27BDb8970D32b89ef89A1Be`

Submitting verification for [src/Counter.sol:Counter] 0x1355a4f7829161a4d27BDb8970D32b89ef89A1Be.
Submitted contract for verification:
    Response: `OK`
    GUID: `1355a4f7829161a4d27bdb8970d32b89ef89a1be67448d78`
```

{% endtab %}
{% endtabs %}


# 验证 Hardhat 合约

当你的合约被部署到区块链实时网络中，下一步将是在区块浏览器上验证其源代码。

验证合约意味着将合约源代码以及用于编译代码的设置上传到存储库（通常由区块资源管理器维护）。这样，任何人都可以对合约进行编译，并将生成的字节码与部署在链上的字节码进行比较。对于 Monad 这样的开放区块链平台来说，这样做极为重要。

{% hint style="info" %}
**注意：**&#x76EE;前，开发网区块浏览器尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

本章节将阐述如何在 Monad 区块浏览器中执行Hardhat 合约验证。

### 设置配置变量 <a href="#id-2-setting-up-configuration-variables" id="id-2-setting-up-configuration-variables"></a>

Hardhat 项目可以将配置变量用于用户特定值，或用于不应包含在代码存储库中的数据。

运行以下命令，设置配置变量：

```bash
npx hardhat vars set <variable_name>
```

例如，运行以下命令，设置 `MONAD_RPC_URL` 变量：

```bash
npx hardhat vars set MONAD_EXPLORER_URL
```

{% hint style="info" %}
**注意**：在设置 `MONAD_EXPLORER_URL` 配置变量时，请勿包含 `/api` 部分。
{% endhint %}

接下来，在提示符中，为此变量输入自定义值：

```bash
Enter value: ********************************
```

同样，你还可以设置 `MONAD_CHAIN_ID` 变量。

{% hint style="danger" %}
**警告**：配置变量以纯文本形式存储在磁盘上。对于需要加密保存的敏感或重要数据，请避免使用此功能。你可以运行 `npx hardhat vars path` 查找存储的文件位置。
{% endhint %}

### 更新 `hardhat.config.ts` 文件以生效 `monadDevnet` 配置 <a href="#id-2-update-your-hardhatconfigts-file-to-include-the-monaddevnet-configuration" id="id-2-update-your-hardhatconfigts-file-to-include-the-monaddevnet-configuration"></a>

```bash
import type { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox-viem";
import { vars } from "hardhat/config";

const config: HardhatUserConfig = {
    solidity: "0.8.27",
    ...
    etherscan: {
        apiKey: `DUMMY_VALUE_FOR_BLOCKSCOUT`,
        customChains: [
            {
                network: "monadDevnet",
                chainId: Number(vars.get("MONAD_CHAIN_ID")),
                urls: {
                    browserURL: vars.get("MONAD_EXPLORER_URL"),
                    apiURL: `${vars.get("MONAD_EXPLORER_URL")}/api`,
                },
            },
            ...
        ],
    },
};

export default config;
```

{% hint style="info" %}
**注意**：目前 Monad 区块浏览器是基于 Blockscout 的，因此不需要 API 密钥。现阶段使用了虚拟占位符值`DUMMY_VALUE_FOR_BLOCKSCOUT`，以避免错误。
{% endhint %}

### 验证智能合约 <a href="#id-3-verify-the-smart-contract" id="id-3-verify-the-smart-contract"></a>

运行以下命令，验证智能合约：

```bash
npx hardhat verify <contract_address> --network monadDevnet
```

结果输出如下示例，表示合约成功验证：

```bash
Successfully submitted source code for contract
contracts/GMonad.sol:GMonad at <contract_address>
for verification on the block explorer. Waiting for verification result...

Successfully verified contract GMonad on the block explorer.
<block_explorer_url>/address/0x690BE9B15b84c6487965d1cbf3372A9FB07A6eE1#code
```

使用上方输出结果末尾的链接，可以在区块浏览器中查看经过验证的智能合约。

{% hint style="info" %}
**注意：**&#x76EE;前，开发网区块浏览器尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}


# 开发指南


# EVM 资源


# EVM Behavior

### **EVM** B**ehavior 规范**

* [关于EVM的说明](https://github.com/CoinCulture/evm-tools/blob/master/analysis/guide.md)：EVM 的直接技术规范和一些 behavior 示例
* [EVM：从Solidity到字节码、内存和存储](https://www.youtube.com/watch?v=RxL_1AfV7N4): Peter Robinson 和 David Hyland-Wood 90 分钟的讲座
* [EVM图解](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf)：一套用于衡量开发者心智水平的出色图表
* [EVM深度挖掘：通往隐形超级编码器之路](https://noxx.substack.com/p/evm-deep-dives-the-path-to-shadowy)

### **操作码参考**

[evm.codes](https://www.evm.codes/)：操作码参考（包括 Gas 成本）和用于单步执行字节码的交互式沙盒

### **Solidity 存储布局**

EVM 允许智能合约将数据存储在 32 字节的单词（"存储槽"）中，但复杂数据结构（如列表或映射）则留给更高级的语言来处理，Solidity 有一种将变量分配到存储槽的特定方法，如下所述：

* [关于存储布局的官方文件](https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html)
* [Solidity中的存储模式](https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/)


# Solidity 资源

Monad 与 EVM 字节码完全兼容，支持[上海升级](https://www.evm.codes/?fork=shanghai)后的所有操作码和预编译，Monad 还保留了标准的以太坊 JSON-RPC 接口。

因此，以太坊主网的大部分开发资源都适用于 Monad。

本章节为在以太坊上构建去中心化应用程序的开发者提供了一套最基础的资源。

由于 [Solidity](https://docs.soliditylang.org/en/v0.8.25/) 是以太坊智能合约最常用的语言，因此本章节的资源主要集中在 Solidity，包括部分 [Vyper](/monad-docs/guides/evm-resources/other-languages/vyper) 和[Huff](/monad-docs/guides/evm-resources/other-languages/huff) 的资源。请注意，由于智能合约是可组合的，最初用一种语言编写的合约仍可以调用另一种语言的合约。

### **集成开发环境（IDEs）**

* [Remix](https://remix.ethereum.org/#lang=en\&optimize=false\&runs=200\&evmVersion=null)：一款交互式 Solidity 集成开发环境，它是编码和编译 Solidity 智能合约最简单快捷的方式，无需安装其他工具。
* [VSCode](https://code.visualstudio.com/) + [Solidity extension](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity)

### **Solidity 入门教程**

* [CryptoZombies](https://cryptozombies.io/en/course)：在 EVM 上构建去中心化应用程序的最佳学习教程。它为任何人提供了资源和课程，适用于从零代码编写经验，到希望探索区块链深度开发的所有人员。
* [Solidity by Example](https://solidity-by-example.org/)：通过简单的开发示例，循序渐进地介绍相关概念，最适合已有其他语言开发基础经验的人员阅读。
* [Blockchain Basics course by Cyfrin Updraft](https://updraft.cyfrin.io/courses/blockchain-basics)：区块链基础知识课程，内容包括区块链、DeFi 和智能合约的基础知识。
* [Solidity Smart Contract Development by Cyfrin Updraft](https://updraft.cyfrin.io/courses/solidity)：智能合约开发课程，开发人员可以通过此课程学习构建项目，以获得项目开发实践经验。
* [Ethereum Developer Degree by LearnWeb3](https://learnweb3.io/degrees/ethereum-developer-degree/)：适用于没有 Web3 开发背景的开发者构架 Web3 应用程序，课程提供了 Web3 开发领域关键协议、框架和概念的案例学习。

### **Solidity 中级教程**

* [Solidity Language](https://docs.soliditylang.org/en/v0.8.21/introduction-to-smart-contracts.html)：围绕 EVM 环境，对智能合约和区块链基础知识进行了详细阐述。除了 Solidity Language 文档外，它还涵盖了在 EVM 上编译代码、部署合约的基础知识，以及提供了在 EVM 上部署合约的相关基本组件。
* [Solidity Patterns](https://github.com/fravoll/solidity-patterns)：提供了代码模板库及其用法说明。
* [Uniswap V2](https://github.com/Uniswap/v2-core)：一个专业而易于理解的智能合约，它提供了一个正在运行中的 Solidity dApp 的全局视图，该合约的演示在[此处](https://ethereum.org/en/developers/tutorials/uniswap-v2-annotated-code/)。
* [Cookbook.dev](https://www.cookbook.dev/search?q=cookbook\&categories=Libraries)：提供了一套交互式合约模板示例，具有实时编译、一键部署和人工智能聊天集成功能，可帮助解决代码问题。
* [OpenZeppelin](https://www.openzeppelin.com/contracts)：为 ERC20、ERC712 和 ERC1155 等常见的以太坊代币部署提供了可定制的合约模板。请注意，它们没有进行 Gas 优化。
* [Rareskills Blog](https://www.rareskills.io/category/solidity)：一系列关于 Solidity 中各种概念的精彩深入的文章合集。
* [Foundry Fundamentals course by Cyfrin Updraft](https://updraft.cyfrin.io/courses/foundry)：一门全面的 Web3 开发课程，旨在向开发者介绍 Foundry，这是构建、部署和测试智能合约的行业标准框架。
* [Smart Contract Programmer YT channel](https://www.youtube.com/@smartcontractprogrammer)：一系列关于各种 Solidity 概念的视频合集，如 ABI 编码、EVM 内存等。

### **Solidity 高级教程**

* [Solmate](https://github.com/transmissions11/solmate) 和 [Solady](https://github.com/Vectorized/solady/tree/main) 资源库：利用 Solidity 或 Yul 提供 Gas 优化合约。
* [Yul](https://docs.soliditylang.org/en/latest/yul.html)：Solidity 的一种中间语言，一般可视为 EVM 的内联汇编。它并不完全是纯粹的汇编语言，它提供控制流结构并抽象出堆栈的内部工作，同时仍向开发人员提供原始内存后台。Yul 主要面向需要接触 EVM 原始内存后台的开发人员，以构建高性能、Gas 优化的 EVM 合约代码。
* [Huff](https://docs.huff.sh/get-started/overview/)：最接近于 EVM 的汇编语言，与 Yul 不同，Huff 不提供控制流结构，也不抽象程序堆栈的内部工作。只有对性能最敏感的应用程序才会使用 Huff，但它是学习 EVM 诠释最底层指令的绝佳教学工具。
* [Advanced Foundry course by Cyfrin Updraft](https://updraft.cyfrin.io/courses/advanced-foundry)：介绍 Foundry，以及如何开发 DeFi 协议和稳定币，如何开发 DAO，高级智能合约开发，高级智能合约测试、模糊测试以及手动验证。
* [Smart Contract Security course by Cyfrin Updraft](https://updraft.cyfrin.io/courses/security)：审计和编写安全协议所需的一切知识。
* [Assembly and Formal Verification course by Cyfrin Updraft](https://updraft.cyfrin.io/courses/formal-verification)：介绍 Assembly，以及使用 Huff 和 Yul 编写智能合约，介绍以太坊虚拟机 OPCode、Formal 验证测试、智能合约不变性测试以及 Halmos、Certora、Kontrol 等工具的使用。
* [Smart Contract DevOps course by Cyfrin Updraft](https://updraft.cyfrin.io/courses/wallets)：介绍使用钱包时的访问控制最佳实践，合约部署后的安全保障、智能合约和 Web3 DevOps 以及实时协议的维护和监控。
* [Secureum YT Channel](https://www.youtube.com/@SecureumVideos/videos)：一系列关于 Solidity 的视频合集，介绍从 Solidity 基础学习到模糊测试和 Solidity 审计等高级概念。

### &#x20;Solidity 游戏化教程

* [Ethernaut](https://ethernaut.openzeppelin.com/)：通过解谜学习 Solidity
* [Damn Vulnerable DeFi](https://www.damnvulnerabledefi.xyz/)：一系列智能合约的漏洞挑战游戏，由易受攻击的合约组成，开发者可以尝试寻找漏洞并破解合约。漏洞挑战是练习和获得 Solidity 开发技能的绝佳方法。

### **最佳实践/模式**

* [DeFi 开发者路线图](https://github.com/OffcierCia/DeFi-Developer-Road-Map)
* [Gas 优化技能书](https://www.rareskills.io/post/gas-optimization)

### **测试**

* [Echidna](https://github.com/crytic/echidna)：模糊测试
* [Slither](https://github.com/crytic/slither)：用于漏洞检测的静态分析
* [solidity-coverage](https://github.com/sc-forks/solidity-coverage/tree/master)：测试 Solidity 代码覆盖率

### **智能合约存档**

* [Smart contract sanctuary](https://github.com/tintinweb/smart-contract-sanctuary)：在以太坊上验证智能合约
* [EVM 函数签名数据库](https://www.4byte.directory/)


# 其他编程语言


# Vyper 语言

[Vyper](https://www.quicknode.com/guides/ethereum-development/smart-contracts/how-to-write-an-ethereum-smart-contract-using-vyper) 是一种流行的 EVM 编程语言，逻辑上类似于 Solidity，语法上类似于 Python。

[Vyper文档](https://docs.vyperlang.org/en/stable/index.html) 包括 Vyper 语言的安装、语法、编码示例和编译。

我们鼓励希望获得类似 Python 体验的典型 EVM 开发人员使用 Vyper 作为编程语言，并使用采用 Python 语言构建的 [ApeWorx](https://docs.apeworx.io/ape/stable/userguides/quickstart.html) 作为测试和部署框架，ApeWorx 还允许在分析测试结果时使用典型的 Python 库，如 Pandas。

Vyper 和 ApeWorx 可与 [Jupyter](https://jupyter.org/) 配合使用，后者提供了一个使用网络浏览器的交互式环境。 有关使用 Vyper 和 Jupyter 为 EVM 开发智能合约的快速指南，请点击[此处](https://medium.com/deepyr/interacting-with-ethereum-using-web3-py-and-jupyter-notebooks-e4207afa0085)。

### **Vyper相关资源**

* [Vyper示例](https://vyper-by-example.org/)
* [Snekmate](https://github.com/pcaversaccio/snekmate)：基于 Vyper 语言的智能合约 Gas 优化模块库
* [Curve contracts](https://github.com/curvefi/curve-contract)：Vyper 语言最突出的使用实例


# Yul 语言

[Yul](https://docs.soliditylang.org/en/latest/yul.html) 是 Solidity 的一种中间语言，通常被认为是 EVM 的内联汇编。它不完全是纯粹的汇编语言，Yul 提供了控制流结构并抽象出堆栈的内部工作，同时仍向开发人员公开原始内存后端。Yul 面向需要接触 EVM 原始内存后端的开发人员，以编写高性能、 具备 gas 优化的 EVM 代码。


# Huff 语言

[Huff](https://docs.huff.sh/) 最接近于 EVM 汇编语言，与 Yul 不同，Huff 不提供控制流结构，也不抽象程序堆栈的内部工作。只有对性能最敏感的应用程序才会使用 Huff，但它是学习 EVM 诠释最底层指令的绝佳教学工具。

* [Huff资源库](https://docs.huff.sh/resources/overview/)：提供关于 Huff 语言的资源


# 链上调试

### **交易反馈与追踪**

* [Tenderly](https://dashboard.tenderly.co/explorer)
* [EthTx Transaction Decoder](https://ethtx.info/)
* <https://openchain.xyz/>
* [Bloxy](https://bloxy.info/)
* <https://github.com/naddison36/tx2uml>：生成 UML 图表的操作系统工具
* <https://github.com/apeworx/evm-trace>： 追踪工具

### **合约反编译**

* <https://oko.palkeo.com/>：[Panoramix](https://github.com/palkeo/panoramix) 反编译器的托管版本

### **本地节点**

开发人员通常会发现，运行一个修改了参数的以太坊单节点，对交互测试很有帮助：

* [Anvil](https://github.com/foundry-rs/foundry/tree/master/crates/anvil) 是一个打包在 Foundry 工具包中的本地以太坊节点。
* [Hardhat](https://hardhat.org/hardhat-network/docs/overview) 是一个打包在 Hardhat 工具包中的本地以太坊节点。

如何安装相应工具包，并获得本地节点，下一章节将详细介绍。

### **工具包**

开发人员通常会发现，在一个功能齐全的开发框架内构建自己的程序能提高开发效率。开发框架可以组织外部依赖关系（即软件包管理），组织单元测试和集成测试，定义部署程序（针对本地节点、测试网和主网），记录Gas成本等。

以下是两种最常用的 Solidity 开发工具包：

* [Foundry](https://book.getfoundry.sh/) 是一个用于开发和测试的 Solidity 开发框架，Foundry 可以管理依赖关系、编译项目、运行测试、部署，并允许用户通过命令行或 Solidity 脚本与链进行交互，Foundry 用户通常使用 Solidity 语言编写智能合约和测试。
* [Hardhat](https://hardhat.org/docs) 是一个 Solidity 开发框架，搭配有 JavaScript 测试框架，它具有与 Foundry 类似的功能，在 Foundry 出现之前是 EVM 开发人员的主要工具链。

### **与以太坊 RPC API 交互**

去中心化应用程序的前端通常使用 JavaScript 或 Python 向 RPC 节点提交读取或写入查询，这些代码通常被称为 "客户端"，因为开发人员可以将区块链大致等同于后台服务器。

以下资源库提供了向 RPC 节点提交查询或交易的标准方法：

* Python:
  * [web3.py](https://web3py.readthedocs.io/en/stable/)
* Javascript:
  * [web3.js](https://web3js.readthedocs.io/)
  * [ethers.js](https://docs.ethers.org/) 开发了 [Web3.js](https://web3js.readthedocs.io/en/v1.10.0/getting-started.html) 和 [Web3.py](https://web3py.readthedocs.io/en/stable/quickstart.html)，它们分别是 Java Script 和 Python 资源库，这些开发旨在使开发人员能够更直观地与区块链进行交互。

这里是一个创建去中心化应用程序前端的快速示例：[create-eth-app](https://github.com/WalletConnect/create-eth-app)。

### **测试网**

Monad 测试网将在未来几个月内提供给开发者使用，由于字节码和 RPC 与 EVM 兼容，计划在 Monad 上部署的开发者可以初步使用[以太坊测试网](https://ethereum.org/en/developers/docs/networks/)。

### 更多资源

以下子页面添加了额外资源：

* [EVM behavior](/monad-docs/guides/evm-resources/evm-behavior)
* [更多 Solidity 资源](/monad-docs/guides/evm-resources/solidity-resources)
* [链上调试](/monad-docs/guides/evm-resources/debugging-on-chain)
* [其他编程语言](/monad-docs/guides/evm-resources/other-languages)
  * [Vyper](/monad-docs/guides/evm-resources/other-languages/vyper)
  * [Huff](/monad-docs/guides/evm-resources/other-languages/huff)

除了 "[建议资源](/monad-docs/guides/evm-resources) "中提到的资源外，这里还有一些其他资源：

### **教程**

* [Ethernaut](https://ethernaut.openzeppelin.com/)：通过解谜学习 Solidity

### **最佳实践/模式**

* [DeFi开发人员路线图](https://github.com/OffcierCia/DeFi-Developer-Road-Map)
* [Gas优化技能书](https://www.rareskills.io/post/gas-optimization)

### **测试**

* [Echidna](https://github.com/crytic/echidna)：模糊测试
* [Slither](https://github.com/crytic/slither)：用于漏洞检测的静态分析
* [solidity-coverage](https://github.com/sc-forks/solidity-coverage/tree/master)：测试 Solidity 代码覆盖率

### **智能合约存档**

*


# 使用 Scaffold-Eth-Monad 构建 dApp

Scaffold-Eth-Monad 是一个拥有Monad 配置功能的 [Scaffold-ETH 2](https://docs.scaffoldeth.io/) 分支。

Scaffold-Eth-Monad 旨在使开发者更容易在 Monad 上创建和部署智能合约，并提供了与合约交互的用户界面。

### 先决条件

开始之前，需要安装以下工具：

* [Node.js](https://nodejs.org/en/download) (v18.18 或更高版本)
* [Yarn](https://classic.yarnpkg.com/en/docs/install#mac-stable) (v1 或 v2+ 版本)&#x20;
* [Git](https://git-scm.com/downloads)

### 获取测试代币

{% hint style="info" %}
**注意：**&#x76EE;前，测试网水龙头尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

你需要在 Monad 测试网获得测试代币，才能部署智能合约。未来，你可以在此处从水龙头获取测试代币。

### 初始设置

1. 克隆 Scaffold-Eth-Monad 代码存储库

```bash
git clone https://github.com/monad-developers/scaffold-eth-monad.git
```

2. 打开项目目录并安装依赖项

```bash
cd scaffold-eth-monad && yarn install
```

3. 为 Hardhat 配置 `.env` 文件

在 `packages/hardhat` 文件夹中复制 `.env.example`，将其命名为 `.env` ，并设置以下自定义值。

* `DEPLOYER_PRIVATE_KEY`：部署智能合约所使用的钱包私钥。
* `MONAD_RPC_URL`：可以使用公共 RPC 或从 Monad 支持的 RPC 服务商获取私有 RPC 。

```bash
DEPLOYER_PRIVATE_KEY=
MONAD_RPC_URL=
MONAD_CHAIN_ID=
MONAD_EXPLORER_URL=
```

{% hint style="info" %}
**注意：**&#x76EE;前，开发网 RPC 尚未公开。如公开，此页面将更新，感谢您的耐心等待。
{% endhint %}

4. 在 Monad 上部署智能合约

完成 `.env` 文件配置后，接下来，你可以在终端中运行以下命令：

```bash
yarn deploy --network monadDevnet
```

此命令将 `YourContract.sol` 部署到 Monad 测试网，该合约位于 `packages/hardhat/contracts` 中，可根据需要进行修改。

`yarn deploy` 命令调用 `packages/hardhat/deploy` 中的部署脚本，将合约部署到网络，你可以自定义部署脚本。

5. 为 Next.js 应用程序设置 `.env` 文件 (可选)

在 `packages/nextjs` 文件夹中复制 `.env.example`，将其命名为 `.env` ，并设置以下自定义值。

```
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
```

6. 在另外的终端上，启动 NextJS 应用程序

```bash
yarn start
```

在浏览器中访问应用：**`http://localhost:3000`**

你应该会看到如下所示的 dApp 用户界面：

<figure><img src="/files/Kkb0ttDTVDa0VztPehlF" alt=""><figcaption></figcaption></figure>

你可以在 `Debug Contracts` 页面与智能合约交互，还可以在 `packages/nextjs/scaffold.config.ts` 中调整应用程序配置。

### 下一步 <a href="#whats-next" id="whats-next"></a>

* 在 `packages/hardhat/contracts` 编辑 `YourContract.sol` 智能合约。
* 在 `packages/nextjs/app/page.tsx` 编辑前端主页，有关路由和 `pages/layouts` 配置，请参阅 [Next.js 文档](https://nextjs.org/docs)。
* 在 `packages/hardhat/deploy` 编辑合约部署脚本。
* 在 `packages/hardhat/test` 编辑智能合约测试，可以使用 `yarn hardhat：test` 运行测试。


# Monad 架构


# 相关概念


# Asynchronous I/O

Asynchronous I/O 是一种输入/输出处理方式，它允许中央处理器在通信进行时继续并发执行。

硬盘和网络比中央处理器慢几个数量级，与启动输入/输出操作并等待结果相比，中央处理器可以在需要数据时立即启动输入/输出操作，并继续执行其他不依赖于输入/输出操作结果的指令。

一些粗略的比较，仅供参考：

| 硬件            | 延迟时间      | 传输速度              |
| ------------- | --------- | ----------------- |
| 中央处理器（三级缓存）   | 10 纳秒     | 400 GB/s          |
| 内存            | 100 纳秒    | 100 GB/s          |
| 硬盘（NVMe 固态硬盘） | 400 纳秒    | 380 MB/s          |
| 网络            | 50-200 毫秒 | 1 Gb/s (125 MB/s) |

(由 fio 报告的 2KB 随机读取的实际硬盘统计数据 - \~190k IOPS）

幸运的是，固态硬盘驱动器可以并发执行事务，因此 CPU 可以同时启动多个请求继续执行，然后同时接收多个事务的结果。

某些数据库（如：lmdb/mdbx）使用内存映射存储来读写磁盘，遗憾的是，内存映射存储是由内核（mmap）实现的，而不是异步的，因此在等待事务完成时会阻碍执行。

有关 Asynchronous I/O 的更多信息，请点击[此处](https://en.wikipedia.org/wiki/Asynchronous_I/O)。


# Pipelining

Pipelining 技术是一种实现并行化的技术，它将事务拆分成一系列可并行处理的较小事务。

Pipelining 技术用于计算机处理器，致力于提高以相同时钟频率顺序执行一系列指令的吞吐量(处理器中还使用了其他技术来提高吞吐量）。有关指令级并行（ILP）的更多信息，请点击[此处](https://en.wikipedia.org/wiki/Instruction_pipelining)。

解释 Pipelining 技术的一个简单案例：

<figure><img src="/files/aL74V1tzcCa7Ye1wYX80" alt=""><figcaption><p>Pipelining 洗衣作业的日常，上: 普通洗衣作业; 下: pipelined 洗衣作业<br>资料来源: <a href="https://www.cs.fsu.edu/~hawkes/cda3101lects/chap6/index.html?$$$F6.1.html$$$">Prof. Lois Hawkes, FSU</a></p></figcaption></figure>

当洗四件衣服时，“普通洗衣作业”的策略是在洗第二件衣服之前，完成第一件衣服的洗涤、烘干、折叠和储存。“pipelined 洗衣作业”的策略是当第一件衣服洗涤完成进入烘干机时，开始洗涤第二件衣服，通过同时利用多个资源来更有效地完成工作。


# 共识机制


# MonadBFT 共识机制

流水线式两阶段 HotStuff 共识机制（Pipelined two-phase HotStuff）

MonadBFT 是一种高性能共识机制，用于在拜占庭参与者存在的情况下，在部分同步条件下就交易排序达成一致。它是 [HotStuff](https://arxiv.org/pdf/1803.05069) 的衍生机制，在 [Jolteon](https://arxiv.org/pdf/2106.10362.pdf)/[DiemBFT](https://developers.diem.com/papers/diem-consensus-state-machine-replication-in-the-diem-blockchain/2021-08-17.pdf)/[Fast-HotStuff](https://arxiv.org/abs/2010.11454) 中采用了优化方案，即在领导人超时的情况下，利用二次通信复杂度将三轮共识减少到两轮。

MonadBFT 是一种流水线式两阶段 BFT 算法，具有乐观响应性，在普通情况下通信开销为线性，在超时情况下通信开销为二次方。与大多数 BFT 算法一样，通信分阶段进行，在每个阶段，领导人向投票者发送签名信息，投票者再向下一位领导人发送签名回执，流水线作业允许区块 `k` 的法定人数证书（QC）或超时证书（TC）捎带区块 `k+1` 的提议。

### **基本情况**

| 相关属性     | 属性描述       |
| -------- | ---------- |
| 抗51%攻击机制 | 权益证明 （PoS） |
| 区块时间     | 1 秒        |
| 最终确定性    | 单时隙确定性     |
| 投票权委托    | 允许         |

### **内存池**

请参阅 [共享内存池](/monad-docs/monad-architecture/consensus/shared-mempool)

### **共识协议**

MonadBFT 是一种流水线式共识机制，分轮次进行。以下内容提供了对协议的高级直观理解。

按照惯例，假设有 `n=3f+1` 个节点，其中 `f` 是拜占庭节点的最大数量， `2f+1`（即 2/3）个节点是非拜占庭节点。在下面的讨论中，我们将所有节点视为具有相同投票权，实际上，所有阈值都可以用投票权而不是节点数来表示。

* 在每一轮中，领导人都会发出一个新的区块，以及上一轮的 QC 或 TC（稍后将详细介绍）。
* 每个验证者都会审查该区块是否符合协议，如果通过，则将签名的”同意"选票发送给下一轮领导人，然后该领导人通过汇总（通过阈值签名）来自 `2f+1` 个验证者的 "同意"选票，得出 QC（法定人数证书）。请注意，这种情况下的消息是线性的：领导人向验证者发送区块，验证者直接向下一轮领导人发送选票。
* 另外，如果验证者在预先指定的时间内没有收到有效数据块，它就会向所有对等设备广播一个签名的超时消息，该超时消息还包括验证者观察到的最高 QC。如果任何验证者积累了 `2f+1` 个超时消息，它就会将这些消息（同样通过阈值签名）组合成一个 TC（超时证书），然后直接发送给下一轮领导人。
* 每个验证者在收到第 `k+1` 轮的 QC 时（在第 `k+2` 轮领导人的消息中），最终确定第 `k` 轮提出的区块。具体来说：
* 第 `k` 轮的领导人 ***Alice*** 会向所有人发送一个新的区块（同时发送第 `k-1` 轮的QC或TC。我们忽略这一点，因为它并不重要）。
* 如果有 `2f+1` 个验证者通过向 ***Bob***（第 `k+1` 轮的领导人）发送选票来对该区块投同意票，那么 `k+1` 中的区块将包含第 `k` 轮的 QC。然而，验证者 ***Valerie*** 此时看到第 `k` 轮的 QC 并不足以让她知道第 `k` 轮的区块已被纳入。原因例如：***Bob*** 可能是恶意的，他只向 ***Valerie*** 发送了该区块，***Valerie*** 所能做的就是对区块 `k+1` 进行投票，并将她的投票发送给 ***Charlie***（第 `k+2` 轮的领导人）。
* 如果有 `2f+1` 个验证者对区块 `k+1` 投同意票，那么 ***Charlie*** 就会发布 `k+1` 轮的 QC 以及 `k+2` 轮的区块提议。一旦 ***Valerie*** 收到这个区块，她就知道第 `k` 轮的区块（即 ***Alice*** 的区块）已经最终确定。
* 假设 ***Bob*** 在第 `k+1` 轮恶意发送了一个无效的区块提议，或者向少于 `2f+1` 个验证者发送了该提议，那么至少有 `f+1` 个验证者会超时，然后触发其他非拜占庭验证者超时，这样至少有一个验证者产生 `k+1` 轮的 TC。然后，***Charlie*** 将在他的提议中公布第 `k+1` 轮的 TC（他必须这样做才能提出提议，因为第 `k+1` 轮没有 QC）。
* 我们把这种提交流程称为 2-chain 提交规则，因为只要验证者看到 2 个相邻的被证明块 `B` 和 `B'`，就可以提交 `B` 及其所有祖先块。

参考资料：

* Maofan Yin, Dahlia Malkhi, Michael K. Reiter, Guy Golan Gueta, and Ittai Abraham. [HotStuff: BFT Consensus in the Lens of Blockchain](https://arxiv.org/abs/1803.05069), 2018.
* Mohammad M. Jalalzai, Jianyu Niu, Chen Feng, Fangyu Gai. [Fast-HotStuff: A Fast and Resilient HotStuff Protocol](https://arxiv.org/abs/2010.11454), 2020.
* Rati Gelashvili, Lefteris Kokoris-Kogias, Alberto Sonnino, Alexander Spiegelman, and Zhuolun Xiang. [Jolteon and ditto: Network-adaptive efficient consensus with asynchronous fallback](https://arxiv.org/pdf/2106.10362.pdf). arXiv preprint arXiv:2106.10362, 2021.
* The Diem Team. [DiemBFT v4: State machine replication in the diem blockchain](https://developers.diem.com/papers/diem-consensus-state-machine-replication-in-the-diem-blockchain/2021-08-17.pdf). 2021.

### **BLS多重签名**

证书（QC 和 TC）可以在 secp256k1 curve 上以 ECDSA 签名向量的形式简单实现，这些证书是明确的，易于构建和验证。但是证书的大小与签名者的数量成线性关系，除了投票信息外，几乎每条共识消息都包含证书，这限制了区块链扩容。

BLS12-381 curve 上基于配对的 BLS 签名有助于解决扩容问题，签名可以逐步聚合成一个签名，验证单个有效的聚合签名就能证明与公钥相关的投票权都已在消息上签名。

BLS 签名比 ECDSA 签名慢得多，出于性能考虑，MonadBFT 采用了一种混合签名方案：BLS 签名只用于可聚合的消息类型（投票和超时），消息的完整性和真实性仍由 ECDSA 签名提供。


# 延迟执行

Monad 区块链的一个新颖之处在于执行与共识分离，采用流水线式共识执行分级机制。

简而言之，共识是 Monad 节点就交易的官方排序达成一致的过程，而执行则是实际执行这些交易并更新状态的过程。

在 Monad 共识中，节点就交易的官方排序达成一致，但领导人节点或验证节点都无需执行这些交易。

也就是说，领导人在不知道结果状态根的情况下提出排序，验证节点投票区块的有效性，可以不知道区块中的所有交易执行是否可以回滚。

怎么会这样？为什么 Monad 会这样做？

这个答案是 Monad 设计的基石，它使 Monad 能够大幅提升交易速度，让单体分片区块链扩展到数百万用户。

### **交错执行和共识效率低下问题**

在以太坊中，执行是达成共识的先决条件。因此当节点就一个区块达成共识时，它们先要就以下两点达成共识：(1) 该区块中的交易列表；(2) 归集执行该交易列表后所有状态的 merkle 根。因此领导人在共享提议之前必须执行提议区块中的所有交易，而验证节点在响应投票之前也必须执行这些交易。

在这种模式下，执行的时间预算极为有限，因为它必须执行两次，并留出足够的时间进行多轮跨全局通信以达成共识。另外由于执行过程会限制共识达成，因此必须极其保守地选择 Gas 限制，以确保即使在最极端的情况下，所有节点上的计算都能在预算范围内完成。

### **确定的排序意味着状态确定性**

这里有一个显而易见却又至关重要的见解：给定一个官方的交易排序，正确的状态就完全确定了，需要执行才能揭示真相，但真相已经确定。

Monad 利用了这一见解，取消了节点在达成共识前执行交易的要求。节点协议仅是关于官方排序，每个节点独立执行区块 `N` 中的交易，同时开始就区块 `N+1` 达成共识。

这样就可以获得与整个区块时间相对应的 Gas 预算，因为执行过程只需紧跟共识即可。此外，这种方法对精确计算时间变化的容忍度更高，普遍而言，执行只需紧跟共识即可。

### **延迟merkle根仍能确保状态机复制**

人们可能对上述观点提出的主要反对意见是：

* 如果其中一个节点是恶意的，没有执行共识中指定的确定性交易，会发生什么情况？(例如，它忽略了某些交易，或者只是将状态变量设置为自己选择的任意值）。
* 如果其中一个节点在执行过程中出错，会发生什么情况？

为了解决以上问题，在 Monad 中，区块提议包含有一个延迟了 `D` 个区块的 merkle 根，其中 `D` 是一个全局参数（目前预计为 10）。因为这种延迟的 merkle 根：

1. 在网络就区块 `N` 达成共识（2/3 的多数票）后，意味着网络已同意区块 `N-D` 的官方结果处于遵循 merkle 根 `M` 的状态，此时轻客户端可以检索全节点，以获得区块 `N-D` 的状态变量值的 merkle 证明。
2. 在区块 `N-D` 执行中出现错误的任何节点将从区块 `N` 开始脱离共识层，这将触发该类节点回滚到区块 `N-D-1` 的结束状态，重新执行区块 `N-D` 中的交易（希望能实现 merkle 根匹配），接着重新执行 `N-D+1` 、`N-D+2` 等区块中的交易。

以太坊的方法是使用共识，以非常严格的方式执行状态机复制：在节点达成共识后，我们知道绝大多数认同官方排序和由该排序产生的状态结果。然而这种严格的方法带来了巨大的代价——极其有限的吞吐量，Monad 在此处稍微放宽了，取得了很好的效果。

### **最终确定性**

在 MonadBFT 中，最终确定性采用单时隙确定性（时间为 1 秒），对于使用全节点的人来说，执行结果一般会滞后不到 1 秒。让我们来解读一下这一点：

**Monad 中的最终确定性采用单时隙确定性（时间为 1 秒）**，如果你提交了一笔交易，你将在一个区块后看到该交易的官方排序（在所有其他交易中）。除非网络中的绝大多数人采取恶意行为，否则不存在回滚重新排序的可能性，这使得 Monad 的最终确定性速度远快于以太坊（2 个 epochs，时间为 12.8 分钟）。

**交易的执行结果**（成功还是失败？交易后的余额是多少？）通常会**在全节点上延迟不到1秒的最终确定性**，任何需要快速了解交易结果的人（例如，想要了解交易状态的高频交易员）都可以运行全节点。Monad 会最大限度地减少全节点的运行成本，更多信息请参阅[硬件要求](broken://pages/GeYkVy1UG4YtfzYC4b8v)。

任何人如果想在不运行全节点的情况下安全地查询交易结果，可以运行一个轻客户端，同时用 merkle 证明查询全节点的余额，在这种情况下，查询将滞后于 merkle 根（延迟`D=10` 个区块，即 10 秒）。请注意，目前大多数用户都是使用软件/浏览器钱包或通过区块浏览器查看区块链状态，此类查询方式均不涉及轻客户端。

有些读者可能会错误地将 merkle 根（延迟了 `D=10` 个区块）与最终确定性混为一谈，误以为最终确定性就是 10 个区块的时间。事实并非如此，官方交易排序是在 1 个区块后确定的，在此之后，如果没有绝大多数的拜占庭行为，就不会有任何更改。


# 共享内存池

### **内存池**

待处理的用户交易存储在每个验证者的内存池中，直到它们被包含在最终确认的区块中。待处理交易通过纠删码与其他验证者内存池共享，然后通过广播树进行通信，以提高效率。

### **交易哈希**

MonadBFT 是就任意有效负载达成一致的有效方法，然而区块广播仍然是一个重大瓶颈。例如，一个包含 10,000 笔交易和 500 个字节交易的区块将达到 5 MB，这种大小的区块将对验证者节点的带宽提出过高要求。

为了缓解这一问题，区块提议只通过哈希值引用交易，这大大节省了哈希，因为哈希值是 32 字节。因此所有验证者内存池在对提议进行投票以及提交区块时，都需要在自己的内存池中保存交易。提交给验证者内存池的交易会通过纠删码与其他验证者内存池共享，然后通过广播树进行通信，以提高效率。


# 传输成本和储备余额

### **方法与动机**

延迟执行的功能非常强大，因为它允许执行和共识并行作业，从而大大增加了执行的时间预算。

一个显而易见的反对意见是：既然共识节点没有最新的状态视图，那么如何防止它们误将已消耗掉所有 Gas的账户的交易打包进区块，这将会产生 DoS 攻击。

为了防止这种情况发生，Monad 为区块链上的交易传输设置了成本（即"传输成本"）。每个账户将保留一个储备余额，在交易达成共识时更新，并根据储备余额收取传输成本。

### **传输成本**

在 Monad 中，通过区块网络进行交易需要支付费用（"传输成本"），这是一项独立于执行成本的费用。

传输成本是防止垃圾交易所必需存在的，费用极低，但反映了利用网络资源的成本。

交易有可能被纳入共识（并被收取传输成本），但相对于指定的 Gas 限额，假设执行预算不足，在这种情况下，交易在执行时会失败，但仍会收取失败交易的 Gas 费用。请注意，这与以太坊并无不同：当账户中 ETH 不足时提交交易，将耗尽ETH并失败。为防止执行交易时出现失败，用户有必要在交易前为账户充值足够多的 Gas。

### **储备余额**

对于每个账户，节点保持同步两个余额：

* **储备余额**，用于支付传输成本
* **执行余额**，用于支付交易执行费用

当交易被纳入区块（达成共识）时，传输成本从储备余额中扣除；当交易执行时，费用从执行余额中扣除（双重费用）；在 `D` 个区块延迟（10 秒）后，对储备余额中的传输成本进行递减操作。

储备余额实际上是"待确认"交易的费用预算，它的存在是为了确保区块中只打包了已支付交易费用的交易。你可以认为储备余额是实时递减的（即在达成共识时），虽然节点对全局状态的洞察是滞后的，但储备余额总是反映最新的交易费用支出。

### **预留储备余额**

预留储备余额是每个账户已设定的参数，默认值预计为传输成本的较大倍数（200 倍），这样用户就可以顺利提交大量待确认交易。

如果用户计划从同一 EOA 账户发送大量待确认交易，则可通过与嵌入式智能合约交互来更改预留储备余额。预留储备余额的更改被视为执行，即只有在延迟期过后才会反映在储备余额中。


# 执行机制


# 并行执行

Monad 以并行方式执行交易，乍看起来，这似乎有着与以太坊不同的执行原语。实际并非如此，Monad 区块与以太坊区块相同：是一组线性有序的交易集，区块中执行交易的结果在 Monad 和以太坊中是相同的。

### **乐观执行**

在基础层面上，Monad 使用乐观执行，这意味着 Monad 会在区块中较早的交易完成之前开始执行当前交易。有时（但并不总是），这会导致执行错误。

思考两笔交易（在区块中按此顺序排列）：

1. `交易1`：读取并更新账户 A 的余额（例如，接收来自账户 B 的转账）。
2. `交易2`：仍会读取和更新账户 A 的余额（例如，向账户 C 转账）。

如果这些交易是并行执行的，而 `交易2` 在 `交易1` 完成之前就开始执行，那么它为账户 A 读取的余额可能与按顺序执行时的余额不同， 这可能导致执行错误。

乐观执行解决这个问题的方法是跟踪 `交易2` 执行时的输入，并将其与 `交易1` 的输出进行比较。如果两者不同，我们就检测到 `交易2` 在执行时使用了错误的数据，此时需要使用正确的数据再次执行。

在 Monad 并行执行交易的同时，每个交易的更新状态都是按顺序"合并”的，以便检查是否有上述问题出现。

于此相关的计算机科学研究有[乐观并发控制](https://en.wikipedia.org/wiki/Optimistic_concurrency_control)（OCC）和[软件事务内存](https://en.wikipedia.org/wiki/Software_transactional_memory)（STM）。

### **乐观执行的影响**

在乐观执行的朴素方式中，直到区块中的早期交易完成后，我们才会发现交易需要再次执行。此时，所有早期交易的状态更新都已合并，因此该交易不可能再次因乐观执行而失败。

在执行交易的过程中，有些步骤并不依赖于状态。例如，重复签名是一项昂贵的计算，再次执行交易时，这项工作无需重复。

此外，由于合并失败而再次执行交易时，访问的账户和存储往往不会改变，因为状态仍缓存在内存中，因此这项昂贵的工作不需要重复操作。

### **执行调度**

乐观执行的朴素方式会在处理器有可用资源时尝试开始执行下一笔交易，区块中可能存在相互依赖的长"链“交易，并行执行这些交易会导致大量故障。

提前确定交易之间的依赖关系，可以让 Monad 只在前序交易完成后才调度交易执行，从而避免资源浪费。Monad 采用静态代码分析技术，可以尝试做出这样的预测。在良好状态下，Monad 可以提前预测出许多依赖关系；在极端情况下，Monad 会退回到朴素执行方式。

### **未来工作**

探索更多避免重复执行交易的方法，并实现它们。


# MonadDb 数据库

MonadDb 是用于存储区块链状态的自定义数据库。

大多数以太坊客户端使用的键值数据库都是以 B-Tree（例如[LMDB](https://www.symas.com/lmdb)）或 LSM-Tree（例如 [LevelDB](https://github.com/google/leveldb) 和 [RocksDB](https://rocksdb.org/)）数据结构实现的，然而以太坊却使用 [Merkle Patricia Trie](https://ethereum.org/zh/developers/docs/data-structures-and-encoding/patricia-merkle-trie/)（MPT）数据结构来存储状态。这是一种次优解决方案，一种数据结构被嵌入到另一种不同类型的数据结构中。为了避免这种情况发生，MonadDb 在磁盘和内存中都原生实现了 Patricia Trie 数据结构。

Monad 可以并行执行多笔交易，当一笔交易需要从磁盘读取状态时，系统不应停滞等待前序操作完成，而应启动读取，然后在此期间同步处理另一笔交易。关键在于此操作要求数据库支持[异步输入/输出](/monad-docs/monad-architecture/concepts/asynchronous-i-o)（async i/o），而上述提到的键值数据库缺乏相应的异步输入/输出支持（尽管在这方面有一些改进）。MonadDb 充分利用了最新内核支持异步输入/输出（在 Linux 上是 [io\_uring](https://unixism.net/loti/index.html)），这就避免了为了异步执行交易而产生大量内核线程来处理待处理的输入/输出请求。

MonadDb 还对输入/输出进行了其他一些优化，例如绕过文件系统，因为文件系统会增加昂贵的开销。


# Monad 的交易生命周期

### 交易提交 <a href="#block-22af2c5f82f043228d62ccbe7d8ad026" id="block-22af2c5f82f043228d62ccbe7d8ad026"></a>

交易的生命周期开始于用户发起一个已签名的交易并将其提交给 RPC 节点。

交易通常由应用程序前端准备，然后提交给用户钱包进行签名。大多数钱包都会调用 `eth_estimateGas` RPC来预设该笔交易的 Gas **限制**，不过用户也可以在钱包中修改该限额，用户通常还会被要求选择交易的 Gas **价格**，即每单位 Gas 的本机代币数量。

用户在其钱包中批准签名后，签名交易将通过 `eth_sendTransaction` 或 `eth_sendRawTransaction` API 调用提交到 RPC 节点。

值得注意的是，在 Monad 中，Gas 限额是传输成本 Gas 和执行成本 Gas 之和，传输 Gas 是一个常数。

### 内存池广播 <a href="#block-657dc51bf3b540e3ba2aaad028492ebf" id="block-657dc51bf3b540e3ba2aaad028492ebf"></a>

RPC 节点会将待处理交易广播给参与共识的其他 Monad 节点，待处理交易集也叫"内存池"。有关内存池作业的更多详情，请参阅[内存池](/monad-docs/monad-architecture/consensus/shared-mempool)章节。

出于防止垃圾交易的原因，只有当[储备金余额](/monad-docs/monad-architecture/consensus/carriage-cost-and-reserve-balance)中有足够的 Gas 时，节点才会将该笔交易添加到其内存池中。

### 区块打包 <a href="#block-4f4825341e524560986b525f079e828d" id="block-4f4825341e524560986b525f079e828d"></a>

MonadBFT 采用轮值领导人机制来生成区块，每一轮的领导人都会从待处理交易集中选出一个区块。在将一笔交易打包进区块后，领导人会对储备金余额中的传输成本进行递减操作。

如 [MonadBFT](/monad-docs/monad-architecture/consensus/monadbft) 所述，区块会在网络中广播，该区块的法定人数证书（QC）会在随后一轮共识中广播（即由下一任领导人发出）；接收到 QC 证书后，投票节点会相互发送投票；当一个节点检测到 2/3 的投票权投同意票时，它就会最终确认该区块。

一旦区块被最终确认，该笔交易就在区块链交易历史上正式"发生"了。由于其排序已确定，因此其真值（即成功还是失败，以及执行后的结果）也就确定了。

### 本地执行 <a href="#block-fbd2d4f7131a40519c852bc20a1b451c" id="block-fbd2d4f7131a40519c852bc20a1b451c"></a>

节点一旦确认一个区块，就会开始执行该区块中的交易。出于效率考虑，交易以并行方式优化执行，由于结果总是按原始排序提交，因此就像串行执行交易一样。

### 结果查询 <a href="#block-0432fa8485ec4af5a93af1d14b51beef" id="block-0432fa8485ec4af5a93af1d14b51beef"></a>

用户可以在任何 RPC 节点上调用 `eth_getTransactionByHash` 或 `eth_getTransactionReceipt` 来查询交易结果，RPC 节点上的本地执行完成后，将立即返回结果。


# 硬件要求

运行 Monad 全节点的硬件要求如下：

* 中央处理器: 16 core CPU
* 内存: 32 GB RAM
* 硬盘: 2 TB NVMe SSD
* 带宽: 100 Mb/s


# 其他详细信息

### 账户 <a href="#block-0e0c4d2be856453c98d9e071c1482c1a" id="block-0e0c4d2be856453c98d9e071c1482c1a"></a>

Monad 中的账户与[以太坊账户](https://ethereum.org/en/developers/docs/accounts/)相同，使用与以太坊相同的地址空间（ ECDSA 的 20 字节地址）。与以太坊账户一样，Monad 也分外部账户（EOA）和合约账户。

### 交易 <a href="#block-7af06f7875d2419bb62672151ba60eb6" id="block-7af06f7875d2419bb62672151ba60eb6"></a>

Monad 中的交易格式与[以太坊一致](https://ethereum.org/en/developers/docs/transactions/)，即符合 [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) 标准，交易使用 [RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/) 编码。

支持可选访问列表 ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930))，但不是必需的。

### 区块和交易的线性 <a href="#block-1bc773c53b0a4b128696ae7c98a9d171" id="block-1bc773c53b0a4b128696ae7c98a9d171"></a>

区块仍然是线性的，区块内的交易也是线性的。并行执行仅用于提高效率，绝不会影响一系列交易的真实结果或结束状态。

### 燃料（Gas） <a href="#block-07e2a88f989443bea7514ba3d26cf84f" id="block-07e2a88f989443bea7514ba3d26cf84f"></a>

[Gas](https://ethereum.org/en/developers/docs/gas/)（或许更明确地命名为 "本币的计算单位"）的设置与以太坊相同，每个操作码都需要花费一定量的 Gas。在 Monad 中，每个操作码的 Gas 成本与以太坊相同，但未来可能会更新。

当用户提交交易时，会在交易中加入 Gas 限额（该函数调用在交易失败前可消耗的最大 Gas 数量）和 Gas 价格（每单位 Gas 成本，以本币为单位）。

默认 Monad 客户端中的领导人使用优先 Gas 竞拍（PGA）提交交易，即按照 Gas 报价从高到低排序交易，未来可能会有其他的交易排序机制。排序的选择与下游发生的一切无关，有效的排序选择并不包含在 Monad 协议中。


# 参考资料


# RPC 概述

Monad 是一个等效于 EVM 的第 1 层区块链。对于以前为以太坊开发的开发者来说，开始在 Monad 上构建应该很熟悉。

Monad 支持用于与区块链交互的 [JSON-RPC](https://www.jsonrpc.org/specification) 接口。有关支持方法的参考，请参阅 [RPC-API](https://docs.monad.xyz/docs/openrpc/json-rpc-api)。

Monad 正在积极开发中，目前在内部开发网中运行。有关公共 RPC 终端节点的详细信息将在未来几个月内披露。


# RPC 故障代码

Monad 支持用于与区块链交互的 [JSON-RPC](https://www.jsonrpc.org/specification) 接口。Monad JSON-RPC 旨在等效于以太坊 JSON-RPC，但由于以太坊客户端之间缺乏标准化，一些故障代码可能略有偏差，以下仅供参考。

### Monad 故障代码参考

<table><thead><tr><th width="148">故障代码</th><th width="239">消息提示</th><th>故障解释</th></tr></thead><tbody><tr><td><strong>-32601</strong></td><td>Parse error</td><td>无法解析 JSON-RPC 请求</td></tr><tr><td><strong>-32601</strong></td><td>Invalid request</td><td>请求无效，例如请求超出大小限制</td></tr><tr><td><strong>-32601</strong></td><td>Method not found</td><td>不符合 JSON-RPC 规范</td></tr><tr><td><strong>-32601</strong></td><td>Method not supported</td><td>符合 JSON-RPC 规范，但 Monad 尚未支持</td></tr><tr><td><strong>-32602</strong></td><td>Invalid block range</td><td>eth_getLogs 过滤器范围限制为 1000 个区块</td></tr><tr><td><strong>-32602</strong></td><td>Invalid params</td><td>请求包含与特定方法关联的错误参数</td></tr><tr><td><strong>-32603</strong></td><td>Internal error</td><td>由于内部错误而无法完成的请求</td></tr><tr><td><strong>-32603</strong></td><td>Execution reverted</td><td>eth_call 和 eth_estimateGas 模拟还原交易</td></tr><tr><td><strong>-32603</strong></td><td>Transaction decoding error</td><td>请求包含无法解码的原始交易</td></tr></tbody></table>


# Monad 官方链接

**Monad Twitter：**<https://twitter.com/monad_xyz>

**Monad** **Discord：**<https://discord.gg/monad>

**Monad 官网：**<https://monad.xyz/>

**Monad 文档：**<https://docs.monad.xyz/>

**Monad 博客：**<https://monadlabs.substack.com/>

**Monad 招聘：**<https://boards.greenhouse.io/monad>


# 相关链接


# DocsZH 相关链接

* Twitter：<https://x.com/Scaling_News>
* DocsZH | 致力于前沿区块链技术文档中文本地化
  * 网站：[https://www.docszh.com](https://www.docszh.com/)
* Scaling News | 致力于探索 scaling & parallel & modular 生态
  * 网站：[https://scaling.news](https://scaling.news/)
  * GuideHub：<https://guide.scaling.news>
* Monad News | 致力于探索 Monad 生态
  * 网站：[https://monad.news](https://monad.news/)


# 介绍 Berachain


# 什么是 Berachain

Berachain是一个具有[EVM等效性](https://www.datawallet.com/zh/%E9%9A%90%E8%94%BD%E6%80%A7/evm-equivalence-explained)的高性能Layer 1区块链，利用[流动性证明 (PoL)](/berachain-docs/learn/introduction/what-is-proof-of-liquidity)作为共识机制，建立在面向EVM的模块化共识客户端框架[BeaconKit](/berachain-docs/learn/introduction/what-is-beaconkit)之上。

### EVM等效性

Berachain的执行层与以太坊虚拟机（EVM）运行环境相同。这意味着它可以使用现有的[执行客户端](https://ethereum.org/zh/developers/docs/nodes-and-clients/#execution-clients)（如 Geth、Reth、Erigon、Nethermind等）来处理智能合约的执行，而无需修改和重新开发，并支持所有 EVM 原生工具。

这同样意味着无论何时升级EVM，Berachain都可以直接采用最新版本，例如对Dencun的开箱即用。并且包括与所有RPC命名空间和端点兼容，任何来自EVM执行客户端的改进都会在Berachain上同步。

### 流动性证明 <a href="#proof-of-liquidity" id="proof-of-liquidity"></a>

流动性证明是一种共识机制，它建立了一个生态流动性的奖励框架，有助于提高交易效率、稳定价格、保障区块链安全，并促进区块链网络/用户增长。

该框架旨在协调关键利益相关者/[PoL 参与者](/berachain-docs/learn/proof-of-liquidity/participants)验证者、链上协议、用户）的激励措施，助力区块链总体长期健康发展。

流动性证明为用户提供了出色的Berachain dApps初体验，其中，原生dApps (如[BEX](/berachain-docs/learn/native-dapps/bex)、[Bend](/berachain-docs/learn/native-dapps/bend)和[Berps](/berachain-docs/learn/native-dapps/berps)) 还可以为开发者在流动性证明之上构建dApps提供参考。

你可以在[什么是流动性证明](/berachain-docs/learn/introduction/what-is-proof-of-liquidity)中阅读更多内容。

### BeaconKit

BeaconKit是Berachain开发的用于构建EVM共识客户端的模块化框架。它整合了[CometBFT](https://cometbft.com/)共识的优点，包括更全面的可组合性、[单时隙最终性](https://ethereum.org/zh/roadmap/single-slot-finality/#what-is-finality) (SSF) 等。

你可以在[什么是 BeaconKit](/berachain-docs/learn/introduction/what-is-beaconkit)中阅读更多内容。


# 什么是流动性证明

流动性证明 (PoL) 是一种新颖的共识机制，通过增加链上流动性来调节和提高区块链的安全性。

PoL借鉴了权益证明（Proof-of-Stake，PoS）概念，通过提供原生代币（交易手续费使用的gas代币）作为初始质押来保护链的安全。PoL在PoS的基础上进行了扩展，引入了一种额外的不可转让的灵魂绑定治理代币（soulbound governance token）。该代币不仅通过权益委托来决定质押者的潜在奖励权重，还会通过治理奖励金库奖励那些为区块链提供流动性的用户。

<figure><img src="/files/xd6ZeRHMnyfZuTCifWbK" alt="" width="563"><figcaption></figcaption></figure>

这种模式将用于交易费用的gas代币和用于区块链安全治理的代币的功能分离了。

对应到Berachain，用于交易费用的原生gas代币是[`$BERA`](/berachain-docs/learn/proof-of-liquidity/tokens/bera)，用于区块链安全治理且不可转让的链上治理代币是[`$BGT`](/berachain-docs/learn/proof-of-liquidity/tokens/bgt) 。

| 奖励模块     | PoS / Ethereum | PoL / Berachain |
| -------- | -------------- | --------------- |
| 质押 / 安全性 | $ETH           | $BERA           |
| 验证者权重奖励  | $ETH           | $BGT (委托)       |
| 区块奖励     | $ETH           | $BGT (同时重新分配)   |

你可以在[流动性证明概述](/berachain-docs/learn/proof-of-liquidity/overview)中阅读更多内容。


# 什么是 BeaconKit

BeaconKit是一个模块化、可定制的共识层，适用于基于以太坊开发的区块链，查看 [BeaconKit GitHub 储存库](https://github.com/berachain/beacon-kit)。

BeaconKit是一个创新框架，它使[CometBFT](https://docs.cometbft.com/v0.38/)共识算法适用于任何EVM执行环境。换句话说，BeaconKit是一个模块化的共识层，适用于基于以太坊开发的区块链。

通过利用Engine API接口，BeaconKit可以与任何EVM执行客户端适配，使其与EVM完全等效，无需修改即可完全支持任何EVM执行客户端。

该框架在构建时考虑了模块化，可以轻松整合不同的分层架构，包括自定义区块构建器、汇总层、数据可用性层等。这种模块化框架不仅能够构建Layer 1区块链，还可以作为Layer 2解决方案的框架。

### BeaconKit优势[​](https://docs.berachain.com/learn/what-is-beaconkit#beaconkit-advantages)

* 具有[单时隙确定性](https://ethereum.org/zh/roadmap/single-slot-finality/)（以太坊最终确定约13分钟）。
* 采用Optimistic payload构建（在投票的同时执行区块提案），可将区块时间缩短40%。
* 符合`以太坊 2.0`的模块化需求。
* 完全兼容[以太坊改进提案](https://ethereum.org/zh/eips/)。<br>


# 连接到 Berachain

区块链钱包允许你，且仅允许你访问你在Berachain上的资产。钱包允许你创建和存储私钥，然后使用私钥来证明你有权访问钱包中的资产，以执行交易代币、购买NFT、玩游戏等操作。

### Berachain bArtio RPC <a href="#berachain-bartio-rpc" id="berachain-bartio-rpc"></a>

将下方信息复制并粘贴到任何支持导入RPC的钱包中。&#x20;

|          |                                                                       |
| -------- | --------------------------------------------------------------------- |
| 网络名称     | Berachain bArtio                                                      |
| RPC 链接   | [https://bartio.rpc.berachain.com](https://bartio.rpc.berachain.com/) |
| 链 ID     | 80084                                                                 |
| Gas 代币符号 | BERA                                                                  |
| 区块浏览器链接  | [https://bartio.beratrail.io](https://bartio.beratrail.io/)           |

**另外，Berachain Docs提供了一键连接，点击此页**[**一键添加网络**](https://docs.berachain.com/developers/network-configurations#add-the-network-in-one-click)**中的**<mark style="background-color:yellow;">**`Add Testnet`**</mark>**按钮即可。**

### 支持的钱包

目前，任何支持 `RPC 导入` 的 [EVM钱包](https://ethereum.org/en/wallets/find-wallet/) 均可配置Berachain网络，如下方所列钱包：

* [MetaMask](https://metamask.io/)
* [Coinbase Wallet](https://www.coinbase.com/wallet)
* [Brave Wallet](https://brave.com/wallet/)
* [Frame](https://frame.sh/)

### 在MetaMask钱包中配置Berachain网络[​](https://docs.berachain.com/learn/connect-to-berachain#how-to-setup-a-metamask-wallet-with-berachain-%F0%9F%A6%8A)

本教程将指引你创建MetaMask钱包并配置Berachain网络。

注意：建议你通过Chrome浏览器进行操作。

#### 第一步：安装MetaMask钱包

点击访问[Metamask](https://metamask.io/)钱包官网，下载适配你使用的浏览器的钱包扩展程序，务必确保扩展程序由`metamask.io`提供。

<figure><img src="/files/yo4ox0v5Pp4ehXkMJS64" alt="" width="375"><figcaption></figcaption></figure>

#### 第二步：在MetaMask中创建钱包[​](https://docs.berachain.com/learn/connect-to-berachain#step-2-create-your-wallet-in-metamask)

MetaMask作为Chrome扩展程序安装完成后，会出现初始化入门提示，中文用户建议在右上角将语言选择为`中文简体`，然后点击`创建新钱包`按钮开始创建。

<figure><img src="/files/VuSo6mNhYjFF6Ijp9Bl9" alt="" width="375"><figcaption></figcaption></figure>

你首先需要设置一个密码，这是你每次打开MetaMask扩展钱包时需要输入的密码。

<figure><img src="/files/4CQiJo5A4ivqOFC4nFeh" alt="" width="375"><figcaption></figcaption></figure>

接下来，请按照说明备份`钱包助记词短语`。这一步非常重要，因为钱包助记词是用来证明你拥有钱包中资产的唯一凭证。

<figure><img src="/files/suaBbRtg2l0moMddYpWl" alt="" width="375"><figcaption></figcaption></figure>

完成以上步骤，恭喜，你已经成功创建了MetaMask钱包！

#### 第三步：将Berachain网络添加到您的钱包[​](https://docs.berachain.com/learn/connect-to-berachain#add-berachain-network-to-your-wallet-%F0%9F%90%BB)

钱包可以连接到各种区块链网络，MetaMask将以太坊设置为默认区块链网络。为了连接到Berachain，我们需要将网络添加到MetaMask并选择它。

一键添加Berachain网络[​](https://docs.berachain.com/learn/connect-to-berachain#add-berachain-network-in-one-click)

点击链接进入[Berachain Docs](https://docs.berachain.com/learn/connect-to-berachain#add-berachain-network-in-one-click)，然后点击该页面的`Add Testnet`按钮，一键将Berachain网络添加到你的MetaMask钱包。

手动添加Berachain网络

要手动添加网络，请单击MetaMask左上角的下拉菜单。

<figure><img src="/files/GVrIep53LAmLCfgFolr4" alt="" width="375"><figcaption></figcaption></figure>

在出现的弹出窗口中点击`添加网络`。

<figure><img src="/files/rc2FtmEMCTvhdYCoDFSr" alt="" width="375"><figcaption></figcaption></figure>

下拉网络列表到最底部，点击`手动添加网络`。

<figure><img src="/files/j7Q1s679Nl4ZB8lmdhDM" alt="" width="375"><figcaption></figcaption></figure>

在MetaMask中输入下方信息，以配置网络并连接到Berachain Testnet，正确输入信息后，点击`保存`。

<figure><img src="/files/wJ7eEhpyY4WqC3TMiIsH" alt="" width="375"><figcaption></figcaption></figure>

保存网络配置后，恭喜，你已经连接到Berachain Testnet了！

<figure><img src="/files/uSW8K394IIpGqr5PajBw" alt="" width="375"><figcaption></figcaption></figure>


# 如何获得 $BERA

`$BERA`是用于在区块链上发送交易的代币，因此有时也被称为 “gas token” 。它用于支付交易gas费用。

你可以在[$BERA](/berachain-docs/learn/proof-of-liquidity/tokens/bera)中阅读更多内容。

### 水龙头[​](https://docs.berachain.com/learn/how-to-get-bera#faucet-%F0%9F%92%A7)

水龙头是一种工具，可以让开发者轻松获取Berachain Testnet的`$BERA`测试代币，且无需任何费用。

你可以在[测试网水龙头](/berachain-docs/learn/native-dapps/testnet-faucet)中阅读更多内容。

<figure><img src="/files/glxABSDL68t3XUhs6cOZ" alt="" width="563"><figcaption><p><a href="https://bartio.faucet.berachain.com">https://bartio.faucet.berachain.com</a></p></figcaption></figure>

### 桥接[​](https://docs.berachain.com/learn/how-to-get-bera#bridging-%F0%9F%A4%9D)

桥接服务允许将代币从一个区块链转移到另一个区块链。

#### LayerZero

`$BERA`可以通过LayerZero从以太坊主网和其他链进行桥接。

<figure><img src="/files/Weu8srkoZX8r1xMc2p3N" alt="" width="563"><figcaption><p><a href="https://docs.layerzero.network/v2/developers/evm/technical-reference/deployed-contracts#bartio">https://docs.layerzero.network/v2/developers/evm/technical-reference/deployed-contracts#bartio</a></p></figcaption></figure>


# Berachain 测试网

<br>


# Berachain 测试网 V1 与 V2&#x20;

2024年6月9日，Berachain正式发布了名为`bArtio`的测试网V2版本。

Berachain `bArtio`网络是对区块链的重新架构，使其更加模块化并与EVM兼容。为了实现这些目标，需要一个全新的框架，[BeaconKit](/berachain-docs/learn/introduction/what-is-beaconkit)应运而生。

V2版本是`BeaconKit`框架的初次实现，它将执行和共识分离，并专注于成为可与任何EVM执行客户端（例如Geth、Reth等）适配的共识客户端。

### 从V1到V2的技术改进[​](https://docs.berachain.com/learn/testnet/berachain-testnet-v1-vs-v2#main-changes-from-v1-to-v2-%F0%9F%90%BB)

Berachain的V1测试网（`Artio`）建立在[Polaris](https://github.com/berachain/polaris)之上，它将EVM执行与Cosmos SDK紧密耦合，并引入了一个用于构建高度优化预编译合约的单体框架。

尽管进行了优化，但Cosmos仍无法处理来自Berachain的大量交易活动，同时，预编译和支持分叉EVM执行客户端也带来了兼容性方面的挑战。

<table><thead><tr><th width="182">技术模块</th><th>Polaris (V1 Artio)</th><th>BeaconKit (V2 bArtio)</th></tr></thead><tbody><tr><td>执行客户端</td><td>EVM (基于Cosmos的预编译分叉)</td><td>EVM (Geth, Reth, Erigon, ...)</td></tr><tr><td>共识算法</td><td>CometBFT</td><td>CometBFT</td></tr><tr><td>最终确定性</td><td>单时隙确定性</td><td>单时隙确定性</td></tr><tr><td>架构类型</td><td>单体式</td><td>模块化</td></tr></tbody></table>

V2引入了将共识层和执行层分分离的模块化架构。V1的验证者只需运行单一的[Polaris](https://github.com/berachain/polaris)客户端，V2验证者需要运行两个客户端，即BeaconKit客户端（用于达成共识）和任一EVM执行客户端（如 Geth、Erigon）。这种模块化架构更加专注于技术专业化：执行层可从EVM的迭代创新中获益，而BeaconKit则提供高度可定制且性能优越的共识层。

### 从V1到V2的代币经济改进

除了BeaconKit的技术改进外，Berachain的原生代币的经济学设计也发生了变化，下表重点介绍了V1和V2之间的主要改进：

| 改进模块         | V1 版本           | V2 版本                           |
| ------------ | --------------- | ------------------------------- |
| 验证者 Bond     | BGT （低供应）       | BERA (69,420)                   |
| 罚没机制         | BGT治理代表（按比例）    | 仅验证者（激活BERA）                    |
| Weighting 奖励 | 委托的BGT          | 委托的BGT                          |
| 出块奖励         | BGT委托权重 = 区块产出率 | 所有验证者 = 区块产出率平均 + BGT委托权重 = 发行量 |
| 架构类型         | Polaris         | Beaconkit                       |
| 验证者数量        | 100             | 128（可能更多）                       |

### 值得注意的要点

* `$BERA`用于激励验证者，而不是`$BGT` 。&#x20;
* `$BGT`代表不再有被罚没的风险。&#x20;
* 现在，执行层与EVM等效。


# PoL 流动性证明


# 流动性证明概述

权益证明的主要缺点之一是缺乏激励不同生态系统的参与者进行合作。验证者几乎没有理由与运行基础设置的协议方和终端用户互动，但他们却获得了大部分经济奖励。另一方面，协议在此基础上启动，为自己保留了大部分代币。

当所有参与者都参与进区块链网络发展时，协议、验证者和链之间就能实现更健康的平衡。

流动性证明PoL涉及链上所有利益相关者的参与和影响。PoL要求不同的利益相关者协同工作，最大限度地提高链上流动性，确保他们获得最大利益。

### 流动性证明生命周期

下图从验证者和委托人的角度展示了流动性证明PoL的生命周期。

<figure><img src="/files/n7M3MZGBzAa1jBQLcZD3" alt="" width="563"><figcaption></figcaption></figure>

1. 潜在验证者（Prospective Val）将提供初始gas代币绑定`$BERA`以保护网络并获得生产区块的资格。所有主动验证者（Active Validator）都有平等的机会被选中提议区块。
2. 随机选择一个主动验证者并提议一个新区块。
3. 为了提议新区块，链会为主动验证者派发治理代币`$BGT`以进行分配。
4. 使用奖励的治理代币，主动验证者将其分发给各种奖励金库，由Berachef合约中的验证者决定不同奖励金库的地址和分配比例。
5. 流动性提供者可以执行流动性操作，例如将某个代币存入BEX池。例如：为流动性池提供`$HONEY`和`$BERA`。
6. 为了提供流动性，流动性提供者会收到一个凭证代币。例如：`$HONEY-WBERA`。
7. 流动性提供者将凭证代币质押在奖励金库中，使他们有资格根据他们的贡献获得`$BGT`。
8. 流动性提供者现在有资格领取分发到奖励金库的`$BGT` ，成为`$BGT`持有者。
9. `$BGT`持有者现在可以将他们的`$BGT`委托给主动验证者，使该验证者成为增强验证者（Boosted Validator），并增加验证者在提议区块时分配的奖励。

### 协调协议方和验证者

由于验证者负责将治理代币分发给奖励金库，当被选中提议一个区块时，它会创造一种新的活力，其中奖励基本上与生态协议方共享。

验证者将与协议建立更牢固的关系，因为他们的奖励权重由委托给他们的治理代币决定，从而建立共生关系。

协议方还可以通过提供激励，引导验证者将其`$BGT`奖励存放在自己的协议金库。

### 现有奖励金库实施情况

以下是现有奖励金库的实施情况：

1. [BEX ](/berachain-docs/learn/native-dapps/bex)- 特定的BEX流动性池
2. [Berps ](/berachain-docs/learn/native-dapps/berps)- 将`$HONEY`放入Berps Honey金库
3. [Bend ](/berachain-docs/learn/native-dapps/bend)- 借用`$HONEY`


# 流动性证明参与者

下图展示了流动性证明生态系统中不同参与者的角色细分。

<figure><img src="/files/A43bmzdbVaY3tadsGaeT" alt="" width="563"><figcaption></figcaption></figure>

### 验证者[​](https://docs.berachain.com/learn/pol/participants#validators-%E2%9C%85)

验证者相互协调，就区块链的状态达成共识。为了获得网络奖励，验证者必须抵押资产，如果行为不当，可能会受到惩罚。要成为主动验证者，必须抵押`$BERA`代币。验证者通过三种主要方式获得收益：

1. Gas费和优先费
2. 将`$BGT`奖励存入协议方，收集协议方提供的激励
3. 从产出区块所获得的`$BGT`总收入中抽取佣金

第1点很简单，与以太坊PoS机制相同。第2点涉及有趣的PoL机制。

#### 验证者激励[​](https://docs.berachain.com/learn/pol/participants#validator-incentives-%F0%9F%92%8E)

正如在[$BGT](/berachain-docs/learn/proof-of-liquidity/tokens/bgt)中讨论的那样，每个区块的`$BGT`发行量是根据提议该区块的验证者的`$BGT`委托权重来分配。每个区块的提议验证者有权将区块的`$BGT`奖励分配给他们选择的任何协议金库，并收取协议方提供的相关激励。任何验证者都有提议区块的平等机会。

验证者最初的`$BGT`委托权重为0，此时验证者不会将提议区块奖励的`$BGT`分配给任何协议金库。然而，通过证明他们正在寻找最有利可图的协议金库来分配`$BGT`，并将部分奖励返还给`$BGT`委托人，他们可以吸引到更多的委托。

#### 生态系统协调[​](https://docs.berachain.com/learn/pol/participants#ecosystem-alignment-%E2%9A%96%EF%B8%8F)

流动性证明中的验证者不仅仅是 “验证” 网络，他们还有机会与协议方合作，以繁荣其在Berachain链上的流动性。最终，他们必须赢得用户（即`$BGT`持有者和矿工）的青睐，以便更高效地将更多`$BGT`奖励分配给金库并赚取奖励。

### $BGT持有人和Farmers <a href="#bgt-holders-farmers" id="bgt-holders-farmers"></a>

`$BGT`持有人在以下方面发挥着至关重要的作用：

1. 通过参与治理影响生态系统决策
2. 影响Berachain的经济激励措施的未来方向（通过将`$BGT`委托给验证者）

{% hint style="info" %}
委托给验证者的`$BGT`不会被罚没，只有验证者质押的`$BERA`受罚没机制约束。
{% endhint %}

#### 赚取$BGT[​](https://docs.berachain.com/learn/pol/participants#earning-bgt-%E2%AC%87%EF%B8%8F)

作为寻求赚取`$BGT`的Farmer，考虑到风险和资产敞口状况，要发掘最有利可图的奖励金库来挖矿。这意味着需要从符合标准的验证者里，寻找那些能给予最多`$BGT`奖励的金库。例如，如果你只想接触稳定币，你可以选择通过向[Berps](/berachain-docs/learn/native-dapps/berps)协议提供`$HONEY`流动性来赚取`$BGT`。

#### 委托$BGT[​](https://docs.berachain.com/learn/pol/participants#delegating-bgt-%E2%AC%86%EF%B8%8F)

现在你是`$BGT`持有者，不同因素可能会影响你如何选择委托方，例如：

* 你可以委托`$BGT`给验证者，他们将`$BGT`奖励分配到你耕种的金库（以增加你的收益率）。
* 你可以委托`$BGT`给验证者，他们将奖励金库激励最大化，并将最大化的收益返还给持有者。

### Bera基金会[​](https://docs.berachain.com/learn/pol/participants#bera-foundation-%F0%9F%8F%9B%EF%B8%8F)

该基金会负责运营原生dApps（Bex、Bend、Berps），这些原生dApps赚取的协议费用将分配给`$BGT`持有者。（这样就有赚取 `$BGT` 的原生方式，独立于奖励金库激励。）

这些dApps的流动性也可作为原生奖励金库，为用户提供流动性并赚取`$BGT`，直到其他协议方的奖励金库通过治理程序与PoL连接。

### 生态协议方[​](https://docs.berachain.com/learn/pol/participants#ecosystem-projects-%F0%9F%A7%B8)

PoL是一种全新的协议启动存款的方式，与通过流动性挖矿激励流动性的传统方法不同。连接PoL，协议可以通过将来自验证者的`$BGT`奖励引导到协议奖励金库来促进流动性。

由于所有奖励都围绕`$BGT`，因此所有链上的参与者都致力于提高网络的总体价值。如果`$BGT`奖励的价值上升，项目代币（作为奖励保存在奖励金库中）的价值也会随着存款的增加而相应增加。

最后，新加入的生态协议项目方必须成为积极参与者，赢得`$BGT`持有者和代表的青睐，才能将其奖励金库列入PoL系统白名单。


# 奖励金库

奖励金库是一种智能合约，用户可以将符合流动性证明PoL要求的资产质押到奖励金库，以获得`$BGT`奖励。奖励金库是所有用户赚取`$BGT`的唯一途径，因此它具有控制进入PoL生态系统的重要功能。

奖励金库是基础设施的关键部分，它允许协议利用PoL，使协议团队能够激励用户的行为以换取`$BGT`。一个协议可以有多个金库，每个金库都有各自的PoL合规资产。例如，BEX可以有多个赚取`$BGT`的池，每个池都有自己的奖励金库和各自的PoL合规资产。

{% hint style="info" %}
每个PoL合规资产都有唯一的奖励金库合约。
{% endhint %}

### 用户交互[​](https://docs.berachain.com/learn/pol/rewardvaults#user-interactions)

#### 在奖励金库中质押

<figure><img src="/files/1Xwkb0p87aCrDsG5VzxT" alt="" width="563"><figcaption></figcaption></figure>

为了获得`$BGT`，用户必须在奖励金库中质押符合PoL标准的资产。部署奖励金库的协议方能够决定用户如何获取符合PoL标准的资产进行质押。协议方可以利用这一点来吸引流动性或刺激链上活动，并以此奖励用户，让用户在自己的协议金库中质押资产。流程如下：

1. 用户从协议获得符合PoL标准的资产，通常称为凭证代币。
2. 用户将符合PoL标准的资产存入相应的金库。
3. 用户将获得该金库赚取的`$BGT`的一部分。

#### 赚取$BGT

<figure><img src="/files/h1HGadu9X8F86ixUu7GH" alt="" width="375"><figcaption></figcaption></figure>

用户从奖励金库中获得的`$BGT`奖励数额取决于以下因素：

1. 用户在奖励金库中质押的总资产价值。
2. 奖励金库中发放的`$BGT`奖励份额。

在奖励金库中质押资产后，用户可以随时领取奖励、增加存款或提取资产。

奖励金库中的`$BGT`挖矿类似于常见的DeFi，为普通用户提供了较低的交互门槛。

### 奖励金库中的$BGT来源

<figure><img src="/files/j0CkCy4F3FF3HwUxbshO" alt="" width="563"><figcaption></figcaption></figure>

验证者将其出块奖励的一部分`$BGT`资产存入他们选择的特定金库中。

要了解验证者为何选择将`$BGT`存入特定金库而不是其他金库，请参阅[PoL](/berachain-docs/learn/introduction/what-is-proof-of-liquidity)中的激励措施，其中讨论了协议如何通过经济激励来影响验证者的行为。

### 创建新的奖励金库[​](https://docs.berachain.com/learn/pol/rewardvaults#creation-of-new-reward-vaults)

新的奖励金库可以无需许可的创建，但必须通过奖励金库白名单流程，该流程由`$BGT`治理机构执行，以便协议有资格从验证者处获得`$BGT`。开发者或协议方可以提交提案，为符合PoL标准的资产申请新的奖励金库白名单。如果提案通过，则将该金库合约地址添加到验证者`$BGT`存放白名单金库列表中。

你可以在此处了解[奖励金库白名单](/berachain-docs/learn/governance/reward-vault-whitelisting)流程。


# 激励系统

PoL中的激励措施可以定义为验证者`$BGT`分配的一个创新且可定制的市场。

这是一种简化整个激励系统的途径，验证者可以从奖励金库中选择与其`$BGT`分配动机相符的激励措施，验证者的这些`$BGT`是通过提议区块获得的。

### 激励验证者[​](https://docs.berachain.com/learn/pol/incentives#incentives-for-validators-%F0%9F%92%B0)

`$BGT`分配通过奖励金库派发给流动性提供者。以下是奖励金库的部分流程说明，其中展示了向奖励金库提供激励的协议。

<figure><img src="/files/6tf4yyhZDdZTR9JjMJfE" alt="" width="563"><figcaption></figcaption></figure>

一旦主动验证者产出区块并被奖励`$BGT`，其就可以决定将`$BGT`奖励分配给哪个奖励金库。协议为奖励金库提供的激励，根据每个验证者的`$BGT`质押数额，按比例分配给验证者。

{% hint style="warning" %}
上图仅为了阐述资产进出奖励金库的概念，并非基于金库合约的真实反映。
{% endhint %}

综上所述，奖励金库中的资产和用户操作流程可以描述如下：

1. 用户将预先选定的资产存入指定的奖励金库。
2. 协议提供激励措施，以吸引将`$BGT`存入其奖励金库。
3. 验证者将`$BGT`奖励存入奖励金库。
4. 协议奖励金库允许用户提取`$BGT`。
5. 协议奖励金库向验证者分配激励收益。

### 激励资产

每个奖励金库最多可以有3个用作激励的资产，以赚取`$BGT`奖励。这也意味着每个奖励金库一次最多可以有3个有效的激励方案。例如：如果用作激励的资产是`$USDC`，该资产只能有唯一的激励方案，直到达到存款上限。

#### 金库激励资产示例[​](https://docs.berachain.com/learn/pol/incentives#reward-vault-incentive-example-%F0%9F%92%A1)

以`$USDC`为例：

```
- User X creates Incentive: 100 `$USDC` for 1 `$BGT` (100:1 Ratio)
- User Y adds 10 `$USDC` Incentive: 110 `$USDC` (100 + 10) for 1.1 `$BGT` (100:1 Ratio)
- Validator Z distributes 1.1 `$BGT` to Reward Vault to fulfill Incentive and receives 110 `$USDC`
- User N create new Incentive: 300 `$USDC` for 1 `$BGT` (300:1 Ratio)
```

### 将激励资产列入白名单[​](https://docs.berachain.com/learn/pol/incentives#how-to-whitelist-incentive-assets-%F0%9F%93%9D)

协议要创建激励方案，需提交提案，仅且提案通过后才能创建。生态协议、用户和基金会根据各自的尽职调查来决定提案是否通过。

激励资产可以作为新的奖励金库提出，也可以作为单独的治理提案进行修改。


# 原生代币系统


# $BERA

`$WBERA`合约：[0x7507c1dc16935B82698e4C63f2746A2fCf994dF8](https://bartio.beratrail.io//address/0x7507c1dc16935B82698e4C63f2746A2fCf994dF8)

### $BERA用途

`$BERA`代币在Berachain网络上主要有以下两个用途：

1. 支付区块链上的交易费用，因此`$BERA`也称为 “gas代币” 。
2. 用于激活验证者节点的质押代币。所有质押的 `$BERA` 代币经济价值相加，构成了基础层，用于保障链的安全性，在其上构建的[`$BGT`](https://docs.berachain.com/learn/pol/tokens/bgt)代币提供了额外的安全性。

### 如何获得$BERA <a href="#how-to-get-bera" id="how-to-get-bera"></a>

测试网`$BERA`代币通过各种[Berachain测试网水龙头](/berachain-docs/learn/native-dapps/testnet-faucet)提供。

{% hint style="danger" %}
`$BERA`主网代币尚未上线，测试网`$BERA`代币无任何经济价值，仅用于测试。任何关于`$BERA`发行的宣传行为均为骗局。
{% endhint %}


# $BGT

`$BGT`代币合约：[0xbDa130737BDd9618301681329bF2e46A016ff9Ad](https://bartio.beratrail.io//address/0xbDa130737BDd9618301681329bF2e46A016ff9Ad)

权益证明区块链有一个治理代币，通过验证者质押来保护网络。通常情况下，这是主要的网络原生代币，用于支付手续费、质押、治理和经济激励。

Berachain开创了三种原生代币的流动性证明模型，治理和经济激励的功能被分离给相应的代币，这个代币是`$BGT`。

`$BGT`不可转让，只能通过提供PoL合规资产流动性（例如[Bex](/berachain-docs/learn/native-dapps/bex)中的流动性）来获得。

### 赚取$BGT

`$BGT`可以通过在白名单dApps中执行某些操作来累积。协议将Berachain上的某类资产的流动性矿池预设为奖励金库，并在这些矿池被列入POL白名单后创建奖励金库。用户可以将该类资产流动性存入奖励金库以赚取`$BGT`。一些示例包括：

* 将流动性存入原生协议[Bex](/berachain-docs/learn/native-dapps/bex)，以赚取流动性LP的`$BGT`奖励。
* 在[Bend](/berachain-docs/learn/native-dapps/bend)上借出`$HONEY`。
* 在[Berps](/berachain-docs/learn/native-dapps/berps)`bHONEY`金库中供应`$HONEY`。

### $BGT用途[​](https://docs.berachain.com/learn/pol/tokens/bgt#what-can-you-do-with-bgt)

#### 协议治理[​](https://docs.berachain.com/learn/pol/tokens/bgt#governance)

`$BGT`可用于对治理提案进行投票。`$BGT`持有者负责生态中的各种决策，这些决策在治理提案中进行讨论。`$BGT`持有者可以对提案进行投票，也可以将`$BGT`投票权委托给任一用户。用户的投票权委托和验证者委托（以获取`$BGT`奖励）两者是相互独立的。

#### 赚取奖励[​](https://docs.berachain.com/learn/pol/tokens/bgt#earning-incentives)

协议可以提供[激励措施](/berachain-docs/learn/proof-of-liquidity/incentives)，吸引验证者向协议供应`$BGT`。验证者通过协议激励措施获得的奖励份额，取决于委托给他们的`$BGT`数量。因此，向`$BGT`持有人返还最大收益的验证者可能会获得最多的`$BGT`委托。

#### 燃烧$BERA[​](https://docs.berachain.com/learn/pol/tokens/bgt#burning-for-bera)

`$BGT`可以1 : 1兑换成`$BERA`。这是一个单向功能，`$BERA`不能兑换成`$BGT`，这保障了仅且只有`$BGT`持有人能够赚取链上经济激励。


# $HONEY

`$HONEY`代币合约：[0x0E4aaF1351de4c0264C5c7056Ef3777b41BD8e03](https://bartio.beratrail.io//address/0x0E4aaF1351de4c0264C5c7056Ef3777b41BD8e03)

在价格激烈波动的加密资产交易中，稳定性是交易资产的必备属性。`$HONEY`是Berachain的稳定币，旨在为Berachain生态内外提供稳定可靠的交易媒介。`$HONEY`的汇率目标是锚定 1 美元。

### 什么是$HONEY[​](https://docs.berachain.com/learn/pol/tokens/honey#what-is-honey)

`$HONEY`是一种完全抵押稳定币（提供1:1抵押品价值)，与美元软锚定。`$HONEY`支持各种加密货币作为抵押品进行铸造，支持多种抵押品能增强`$HONEY`经济模型的稳定性和弹性。

### 如何获得$HONEY[​](https://docs.berachain.com/learn/pol/tokens/honey#how-to-get-honey)

用户可通过将列入白名单的抵押品资产存入金库铸造`$HONEY`。符合`$HONEY`抵押品条件的不同资产存储在不同的金库合约中。`$HONEY`的铸造率可由`$BGT`治理机构针对每种不同的抵押品性质进行设置。

此外，用户可以通过在[Bex](/berachain-docs/learn/native-dapps/bex)上交易其他资产来兑换`$HONEY`。

### 哪些资产可以铸造$HONEY[​](https://docs.berachain.com/learn/pol/tokens/honey#what-determines-which-assets-collateralize-honey)

`$BGT`治理机构决定了哪些资产可以用来铸造`$HONEY`。

### 如何使用$HONEY[​](https://docs.berachain.com/learn/pol/tokens/honey#how-is-honey-used)

`$HONEY`与其他稳定币的用途相似，例如用于支付/汇款以及对冲市场波动。不同的是，`$HONEY`在Berachain生态中有许多独特的用例，包括：

#### Bend：供应[​](https://docs.berachain.com/learn/pol/tokens/honey#lending-bend)

在[Bend](/berachain-docs/learn/native-dapps/bend)使用`$HONEY`，用户向Bend协议的`$HONEY`流动性池中供应资产，赚取收益。

对于供应`$HONEY`的用户，将获得一个与`$HONEY`等值的代币[`$aHONEY`](https://docs.bend.berachain.com//learn/lending-protocol/tokens#atokens)，作为存款凭证。

`$HONEY`是Bend接受的唯一可以赚取收益的资产。

#### Bend：借贷[​](https://docs.berachain.com/learn/pol/tokens/honey#borrowing-bend)

Bend还使用`$HONEY`作为基础代币，用户可以存入其他资产作为抵押进行借贷。

#### Berps：永续合约[​](https://docs.berachain.com/learn/pol/tokens/honey#perpetual-futures-berps)

[Berps](/berachain-docs/learn/native-dapps/berps)使用`$HONEY`作为抵押、支付和存款等所有交易的基础代币。例如，用户要在ETH上创建杠杆看多头寸，首先他们必须存入适当数量的`$HONEY`。

此外，`$HONEY`持有者可以通过在`$bHONEY`金库中提供流动性，赚取被动收益。`$bHONEY`金库的存款人可以赚取Berps的交易费用，并成为交易者头寸的对手方。例如，如果交易者被清算，该头寸的`$HONEY`抵押品将分配给`$bHONEY`金库中的存款人。

### 铸造$HONEY <a href="#minting-honey" id="minting-honey"></a>

`$HONEY`铸造流程示例：

<figure><img src="/files/DSeeTAvt9Hsr7mQRTiZd" alt="" width="563"><figcaption></figcaption></figure>

#### $HONEY金库[​](https://docs.berachain.com/learn/pol/tokens/honey#honey-vaults)

`$HONEY` 通过将合规抵押品存入名为`$HONEY`的专用合约来铸造。每个金库都对应特定的抵押品种类，并具有各自的铸造率和赎回率。

上方示例中，用户存入`$USDC`来铸造`$HONEY`，只有`$USDC`金库与之交互，而`$USDT`金库则不会。

#### 金库路由[​](https://docs.berachain.com/learn/pol/tokens/honey#vault-router)

`$HONEY`铸造的核心组件是金库路由（Vault Router）合约。该合约作为中心枢纽，连接所有`$HONEY`金库，并负责铸造新的`$HONEY`稳定币。

上方示例中，用户的存款通过Vault Router合约被路由到相应金库。Vault Router合约保障金库铸造的`$HONEY`稳定币与用户存入资产对应，然后向用户铸造`$HONEY`代币。

#### 铸造费用[​](https://docs.berachain.com/learn/pol/tokens/honey#fees)

`$HONEY`铸造和赎回中收取的用户费用将分配给`$BGT`持有人，费用由每个金库的铸造率和赎回率决定。例如，如果`$USDC`金库的铸造率为0.995（1`$USDC`兑换0.995`$HONEY`），则每铸造1`$USDC`，收取0.005或0.5%的费用。

### 铸造示例

#### 参数设置：

* 用户希望铸造价值1000`$USDC`的`$HONEY`稳定币
* `$USDC`的铸造率设置为0.995，即99.5%

#### 铸造流程：

1. 用户将1000`$USDC`存入Vault Router合约
2. Vault Router将1000`$USDC`转入`$USDC`金库，并收到1000份铸造凭证
3. Vault Router计算要铸造的`$HONEY`数量：

* 要铸造的`$HONEY`数量=铸造凭证数量×铸造率
* 即，要铸造的`$HONEY`=1000×0.995=995`$HONEY`

4. Vault Router向用户地址铸造995 `$HONEY`
5. Vault Router计算并分发铸造费用：

* 费用数额=铸造凭证数量-铸造的`$HONEY`数量
* 即，费用数额=1000-995=5
* Vault Router将这5个铸造凭证分发给`$BGT`持有人。


# 治理模型


# 治理模型概述

Berachain在治理中采用`$BGT`，允许`$BGT`持有人对PoL系统和核心dApps的关键功能提供重要的决策表决。以下是治理中的一些示例：

* PoL合规资产白名单（例如，新的抵押资产、激励资产）
* `$HONEY`铸造参数（例如，符合条件的抵押资产、铸造率）
* 原生dApps治理（例如，Bend利率模型的迭代）
  * Berps
  * Bend
  * Bex
* 白名单奖励金库的`$BGT`分配

### 治理流程[​](https://docs.berachain.com/learn/governance/#governance-process)

Berachain的治理流程分为以下阶段：

1. **创建提案**：任何满足投票权数量要求的用户都可以创建治理提案。
2. **提案待定**：提案创建后，进入等待期，然后才能进行投票。
3. **提案投票**：在投票期间，`$BGT`持有人进行提案投票。
4. **投票结果**：投票结束后，投票结果显示为“成功”或“失败”，提案需要达到`$BGT`法定数才能通过。
5. **提案锁定**：如果提案通过，提案将被锁定，进入待执行队列。
6. **提案执行**：锁定期满，提案将被执行，实施所提议的更改。

<figure><img src="/files/YwFAXjJxB7cD3qDkTjpl" alt="" width="563"><figcaption></figcaption></figure>

### 创建提案[​](https://docs.berachain.com/learn/governance/#creating-a-governance-proposal)

Berachain的治理提案创建分为以下步骤：

1. **拥有足够投票权**：你需要拥有足够的`$BGT`投票权，可以是直接持有`$BGT`或由其他持有人委托。
2. **委托`$BGT`**：将你的`$BGT`委托给自己获得投票权，或由其他持有人委托给你。
3. **撰写提案**：明确说明你希望实施的更改。例如：希望在BeraChef合约中添加奖励金库，你需要列出奖励金库合约地址和函数调用，来更新“friends of the chef”。
4. **提交提案**：使用治理合约在链上提交提案。这需要调用`propose`函数，并附上必要参数。
5. **跟踪提案**：提案提交后，跟踪提案进展。鼓励`$BGT`持有人参与提案讨论，并对提案投票。
6. **提案通过：**&#x5982;果提案通过且锁定期满，提案将被执行，提议的更改将被实施。

有关创建治理提案的详细演练，包括代码示例和分步说明，请参阅[Berachain Github](https://github.com/berachain/guides/tree/main/apps/berachain-governance-proposal)。

### 测试网治理体系

以下参数标准适用于测试网：

{% hint style="danger" %}
以下参数仅适用于测试网，主网上线时可能会发生变化。务必联系Berachain团队才能将你的提案列入测试网白名单。
{% endhint %}

| 阶段状态 | 参数标准               |
| ---- | ------------------ |
| 创建提案 | 至少持有1000`$BGT`     |
| 提案待定 | 3小时等待期             |
| 提案投票 | 3小时投票期             |
| 投票结果 | 需要20亿`$BGT`达到通过法定数 |
| 提案锁定 | 3小时锁定期             |


# 奖励金库白名单

Berachain的流动性证明PoL共识机制允许协议方通过接收来自验证者的`$BGT`来启动协议流动性。此过程由奖励金库实现，奖励金库在Berachain生态的治理和激励中发挥着至关重要的作用。

{% hint style="info" %}
有关如何创建奖励金库的详细指南，请参阅博文：\
[Creating a Governance Proposal for Berachain Reward Vaults](https://blog.berachain.com/blog/creating-a-governance-proposal-for-berachain-reward-vaults)
{% endhint %}

### 了解PoL奖励金库[​](https://docs.berachain.com/learn/governance/rewardvault#understanding-reward-vaults-in-pol)

奖励金库是一种智能合约，使验证者能够与协议分享`$BGT`奖励。当验证者产出区块时，他们获得的`$BGT`奖励与其质押数额成正比。验证者可以：

1. 使用`$BGT`参与治理
2. 将`$BGT`兑换为`$BERA`（原生gas代币）
3. 通过奖励金库与协议分享`$BGT`奖励

该机制是Berachain[奖励金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)系统的核心。

### 治理和奖励金库[​](https://docs.berachain.com/learn/governance/rewardvault#governance-and-reward-vaults)

虽创建奖励金库无需许可，但为了接收来自验证者的`$BGT`，金库必须通过治理提案，被列入白名单。此过程确保了社区监督与PoL系统的目标保持一致。

#### 白名单治理流程 <a href="#governance-process-for-whitelisting" id="governance-process-for-whitelisting"></a>

1. **满足`$BGT`持有要求**
   * 创建提案所需的最低`$BGT`数额
   * `$BGT`可通过向原生dApps提供流动性获得
2. **创建并提交提案**
   * 提案在链上提交
   * 投票开始前有一个等待期
3. **提案投票**
   * 开启投票窗口
   * `$BGT`持有人投票（需达到法定数）
4. **提案结果**
   * 如果通过：进入锁定期，待执行
   * 如果未通过：标记为失败，允许在解决相关问题后重新提交

{% hint style="info" %}
测试网提案详细标准（如所需`$BGT`数额、投票期和法定数要求等），请参阅[治理模型概述](/berachain-docs/learn/governance/overview)。
{% endhint %}

<figure><img src="/files/jeGQxGA9rZfmrMP1iwcI" alt="" width="563"><figcaption></figcaption></figure>

### 对PoL系统的影响[​](https://docs.berachain.com/learn/governance/rewardvault#impact-on-the-pol-ecosystem)

通过治理将奖励金库列入白名单具有重大意义：

1. **流动性激励**：经批准的金库可以接收`$BGT`奖励，激励用户向其提供流动性。
2. **协议增长**：协议可以使用积累的`$BGT`来吸引流动性或参与治理。
3. **生态系统协调**：白名单治理能确保金库与生态社区利益保持一致。

有关奖励金库的更多信息，请参阅[奖励金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)。

有关Berachain治理的更多信息，请参阅[治理模型概述](/berachain-docs/learn/governance/overview)。

有关为Berachain奖励金库创建治理提案的更多信息，请参阅博文：

[Creating a Governance Proposal for Berachain Reward Vaults](https://blog.berachain.com/blog/creating-a-governance-proposal-for-berachain-reward-vaults)


# 指南


# 流动性证明常见问题

#### 没有代币的dApps可以参与PoL吗？[​](https://docs.berachain.com/learn/pol/faqs#can-dapps-that-don-t-have-a-token-still-participate-in-pol)

然也。PoL流动性证明的基础之一是启用白名单奖励金库。协议只需要发行一个凭证代币，该凭证代币可以质押在协议自身的白名单奖励金库。凭证代币与原生代币不同，可以被视为是原生代币的证明。例如，当用户向Bex提供流动性时，他们会收到LP代币形式的凭证代币。

#### 哪些类型的dApps可以拥有白名单奖励金库？[​](https://docs.berachain.com/learn/pol/faqs#are-there-restrictions-on-what-kinds-of-dapps-can-have-whitelisted-reward-vaults)

任何dApps都可以部署奖励金库并将其作为治理提案提交，以将金库列入白名单。

#### Bex流动性池的APY由什么决定？[​](https://docs.berachain.com/learn/pol/faqs#what-determines-the-apy-for-pools-in-bex)

APY奖励由以下方面决定：

1. **流动性池产生的协议费用**：由流动性池中产生的交易和设定的费用系数决定。产生的交易越多，协议费用就越多。费用系数越高，单次交易产生的协议费用越高。但是，协议费用系数应设定在一个合理范围，以确保用户不会因协议费用过高而放弃交易。
2. **流动性池中$BGT分配数额**：这是每个周期中Berachain验证者的投票决定的。每个验证者可以选择他们希望接收其`$BGT`奖励的池，以及每个池应获得的`$BGT`分配数额。验证者`$BGT`奖励是根据所有`$BGT`持有人委托给该验证者的`$BGT`权重确定的。分配给某流动性池的`$BGT`数额越多，则该池的PRR越高。
3. **用户在奖励金库中的质押数额**：分配给流动性池的`$BGT`会按比例派发给所有为该池投入`$BGT`的用户。

#### 奖励金库&#x7684;**$**&#x42;GT奖励是否与该金库的流动性（例如TVL）成比例？[​](https://docs.berachain.com/learn/pol/faqs#is-the-amount-of-bgt-rewarded-to-a-rewards-vault-proportional-at-all-to-the-amount-of-liquidity-e-g-tvl-of-that-rewards-vault)

非也。随着时间推移，可能会出现一定的比例关系，但这不是决定性因素。

#### **$**&#x42;GT奖励分配是否与委托给验证者&#x7684;**$**&#x42;GT数量成线性关系？[​](https://docs.berachain.com/learn/pol/faqs#is-the-size-of-the-bgt-emission-linear-to-the-amount-of-bgt-delegated-to-a-validator)

然也。对于无人委托的验证者，有一个基准`$BGT`分配参数，除此之外，`$BGT`分配根据委托的BGT数量呈线性变化。

#### 任何人都可以质&#x62BC;**$**&#x42;ERA成为验证者吗？[​](https://docs.berachain.com/learn/pol/faqs#can-anyone-stake-bera-to-become-a-validator)

目前，成为验证者需要获得许可，但预计未来会开放。

#### 原生dApps（BEX、Bend Berps）和外部dApp参与PoL是否有区别？[​](https://docs.berachain.com/learn/pol/faqs#is-there-any-difference-between-the-ability-for-native-dapps-bex-bend-berps-and-external-dapps-to-participate-in-pol)

非也。所有奖励金库都必须通过治理批准，才有资格接收BGT奖励分配。例如，并非所有BEX池都能获得`$BGT`奖励（因为它们不在白名单中）。

#### “流动性池”和“奖励金库”有什么区别？[​](https://docs.berachain.com/learn/pol/faqs#what-is-the-difference-between-a-pool-and-a-rewards-vault)

一般来说，流动性池是指Berachain上DeFi协议中的存款，可以是Dex上的LP，借贷协议中的凭证代币。奖励金库（在PoL白名单中）是单独的智能合约，允许用户将这些流动性凭证代币质押以赚取`$BGT`奖励。

#### 奖励金库是否只能通过白名单治理提案创建？[​](https://docs.berachain.com/learn/pol/faqs#are-rewards-vaults-created-only-by-whitelisting-governance-proposals)

从技术上讲，奖励金库的创建无需许可，但验证者要想将`$BGT`存入奖励金库，则该奖励金库必须是已被列入白名单。

#### 能否举例说明$BGT投票权与$BGT分配的关系？[​](https://docs.berachain.com/learn/pol/faqs#can-you-give-me-an-example-of-bgt-voting-power-in-relation-to-bgt-emissions)

验证者的$BGT奖励与其投票权成正比。在Bartio测试网上，每个区块的通膨率固定为1500`$BGT`左右。如果一个拥有25%`$BGT`投票权的验证者产出一个区块，其将获得约375`$BGT`的奖励，并转入奖励金库，这些奖励金库根据收到的`$BGT`数量支付奖励。因此，验证者奖励与其拥有的`$BGT`委托量有关，如果一个拥有10%`$BGT`投票权的验证者产出区块，其只能获得150`$BGT`。

#### 担心$BGT会出现恶性通货膨胀，Berachain计划如何解决这个问题？[​](https://docs.berachain.com/learn/pol/faqs#i-have-concerns-about-hyperinflation-of-bgt-how-does-berachain-manage-this)

传统的PoS系统每年都会有一定比例的通胀，Berachain只是将PoS通胀分成了以下两部分：

1. 仅有`$BERA`质押，未有`$BGT`委托权益的验证者产出区块获得的优先费用。
2. 基于委托给验证者的`$BGT`数量的权益权重系数。

PoS通胀等于以上两条相加，基本上第2条是所有验证者`$BGT`委托的加权平均值，它与平均通胀率吻合。

最终结果是，Berachain通胀与传统PoS相差无几，只是分配方式不同。

#### 如何为LP代币定价，以$BGT的LP为例？为安全起见，Berachain是否会限制$BGT流动性池质量？[​](https://docs.berachain.com/learn/pol/faqs#how-do-you-manage-to-price-the-lp-token-which-in-this-case-bgt-does-berachain-limit-the-number-of-pools-receiving-bgt-to-blue-chips-for-security-right)

`$BGT`没有定价，也不是LP代币，它是一种不可转移的灵魂绑定代币，通过在Berachain上提供DeFi流动性来赚取。在`$BGT`治理白名单中，由市场自由决定`$BGT`流动性池的数量。因此，在同等条件下，绩优的`$BGT`流动性池可能会获得更多的`$BGT`奖励（因为流动性聚集在此），而长尾资产在没有过多激励的情况下获得的`$BGT`较少。

#### 为什么激励措施以每$BGT为单位，而不是以流动性池为单位？[​](https://docs.berachain.com/learn/pol/faqs#why-are-incentives-emission-defined-per-bgt-instead-of-being-pool-based)

激励措施以`$BGT`为单位，因为用户最终希望能够计算出，委托一个`$BGT`和质押一个`$BGT`，两者能获得的奖励差异。因此，这更像是用户体验的不同选择，以方便理解`$BGT`的不同价值驱动。

#### 只有验证者才能投票或创建提案吗？[​](https://docs.berachain.com/learn/pol/faqs#can-only-validators-vote-on-or-create-proposals)

非也。任何拥有一定数量的`$BGT`用户都可以创建提案或投票。

#### 如果验证人想降低权重，验证人质押是否可以提取？验证人是否能够从其初始$BERA质押中获得收益？[​](https://docs.berachain.com/learn/pol/faqs#can-validator-deposits-ever-be-withdrawn-ie-if-someone-wants-to-spin-down-their-validator-do-depositors-earn-yield-tips-on-their-initial-deposit-of-bera)

在启用EIP-7002之前，验证人质押不能提取。请等待下一次硬分叉，这样节省了大量工程时间和代码复杂性。质押只是为了验证人激活，质押本身不会产生收益。

#### 没有$BGT委托的验证者可以产出区块吗？这些验证者在产出区块时会获得什么奖励？[​](https://docs.berachain.com/learn/pol/faqs#can-validators-with-no-bgt-delegated-to-them-build-blocks-what-kind-of-rewards-will-those-validators-earn-when-they-build-a-block)

然也。他们可以产出区块，这些验证者只能获得交易的优先费用，而不会获得任何`$BGT`奖励。

#### 奖励金库是将奖励派发到dApp中的单个池，还是整个dApp？[​](https://docs.berachain.com/learn/pol/faqs#can-rewards-vaults-route-emissions-to-a-single-pool-within-a-dapp-or-only-the-whole-dapp)

dApp可以为任何协议封装资产申请PoL金库白名单，该封装资产只需部署一个ERC-20凭证代币，用户就可以将其质押到金库中。

#### Berachain是否限制了主动验证者的数量（例如256个），如何才能成为主动验证者？[​](https://docs.berachain.com/learn/pol/faqs#do-we-cap-the-number-of-active-validators-e-g-at-256-is-there-a-queue-for-entering-the-active-set)

我们将建立一种机制，将主动验证者的数量限制在一个安全水平。

#### 验证者节点需要持有69420个$BERA才能开启质押，这是准确数字吗？[​](https://docs.berachain.com/learn/pol/faqs#it-claims-that-a-validator-node-needs-69-420-bera-to-stake-is-this-accurate)

69420个`$BERA`只是暂时的占位符设置，我们将在接近主网时确定最终值。

#### 验证者节点有质押数额上限吗？[​](https://docs.berachain.com/learn/pol/faqs#is-there-a-maximum-staking-amount-with-a-validator-node)

没有硬性上限，但多余的`$BERA`质押不会获得额外的提议新区块的权重。

#### 验证者的哪些资产有可能被罚没？[​](https://docs.berachain.com/learn/pol/faqs#what-asset-is-at-risk-to-be-slashed-for-validators)

`$BERA`属于担保资产，有可能被罚没。


# 原生 dApps


# 测试网水龙头

### 官方水龙头

Berachain测试网水龙头是一款工具，开发者和用户可以轻松获取`$BERA`测试网代币（有时也称为`$tBERA`），用于免费访问Berachain测试网。为了防止水龙头被滥用，用户钱包地址的以太坊主网中至少拥有0.001`$ETH`代币，才能使用该水龙头。

{% embed url="<https://bartio.faucet.berachain.com/>" %}

### 第三方水龙头

{% embed url="<https://faucet.quicknode.com/berachain/bartio>" %}

{% embed url="<https://www.faucet.kodiak.finance/>" %}

{% embed url="<https://beta2.honeypotfinance.xyz/faucet>" %}

{% embed url="<https://faucet.0xhoneyjar.xyz/>" %}

{% embed url="<https://learnweb3.io/faucets/berachain_artio/>" %}


# 区块浏览器

Beratrail是Berachain的规范区块浏览器，可以轻松查看交易、合约、钱包、代码、合约交互和验证合约。

{% embed url="<https://bartio.beratrail.io/>" %}


# BEX

[BEX](https://bartio.bex.berachain.com/)是Berachain的原生去中心化交易所（DEX），它允许通过交换和向流动性池提供流动性来交易任意一对加密资产。

此外，BEX中的流动性池可以通过治理升级到[流动性证明奖励金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)，以获得`$BGT`奖励分配。

了解更多信息，请查看[Berachain BEX 文档](https://docs.bex.berachain.com/)。

{% embed url="<https://bartio.bex.berachain.com/>" %}


# Bend

[Bend](https://bartio.bend.berachain.com/)是Berachain的原生去中心化借贷协议。出借人存入稳定币，当其他用户借入其稳定币时，出借人获得交易费用。另外借款人可以存入加密货币抵押品（例如wBTC）来获得稳定币，同时需要维护其抵押资产的风险敞口。

目前，Berachain的原生稳定币[`$HONEY`](/berachain-docs/learn/proof-of-liquidity/tokens/honey)，是Bend可供借用的主要和唯一稳定币。

此外，Bend是[PoL奖励白名单金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)，借款人有资格获得`$BGT`奖励分配，Bend展现了PoL如何激励用户在dApp上操作不同的流动性策略。

了解更多信息，请查看[Berachain Bend 文档](https://docs.berachain.com/learn/dapps/Berachain%20Bend%20Docs)。

{% embed url="<https://bartio.bend.berachain.com/>" %}


# Berps

[Berps](https://bartio.berps.berachain.com/)是Berachain原生的去中心化杠杆交易平台，允许进行永续合约交易。

Berachain的原生稳定币[`$HONEY`](https://docs.berachain.com/learn/pol/tokens/honey)是Berps平台抵押、支付和存款等交易的基础代币。用户可以通过在Berps的[`$HONEY`](https://docs.berps.berachain.com//learn/vault/)金库中提供流动性来赚取被动收益。作为交易用户头寸的对手方，金库存款人可以赚取Berps的协议费用。

此外，Berps中的金库是[PoL奖励白名单金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)，金库存款人有资格获得`$BGT`奖励分配，Berps展现了PoL如何激励用户在dApp上操作不同的流动性策略。

了解更多信息，请查看[Berachain Berps文档](https://docs.berachain.com/learn/dapps/Berachain%20Berps%20Docs)。<br>

{% embed url="<https://bartio.berps.berachain.com/>" %}


# BGT Station

[BGT Station](https://bartio.station.berachain.com/)是管理`$BGT`所有事务的仪表盘，用户可以实现如下操作：

1. 查看活跃的[奖励金库](https://bartio.station.berachain.com/gauge)
2. 查看活跃的[验证器](https://bartio.station.berachain.com//validators)集
3. [委托或取消](https://bartio.station.berachain.com//delegate)`$BGT`委托
4. [兑换`$BGT`为`$BERA`](https://bartio.station.berachain.com//redeem)
5. [领取已获得的`$BGT`奖励](https://bartio.station.berachain.com//rewards)

{% embed url="<https://bartio.station.berachain.com/>" %}


# Honey Swap

Honey Swap旨在将已获批准的稳定币和加密资产铸造成`$HONEY`。

了解`$HONEY`的更多用途，请访问[$HONEY相关文档](/berachain-docs/learn/proof-of-liquidity/tokens/honey)。

{% embed url="<https://bartio.honey.berachain.com/>" %}


# 帮助中心


# 常见问题

#### Berachain的性能指标如何？[​](https://docs.berachain.com/learn/help/faqs#what-do-berachain-s-performance-metrics-look-like)

Berachain具有以下属性：

* 区块时间：区块时间各不相同，最新信息请查看[Beratrail区块浏览器](https://bartio.beratrail.io/)。
* 每秒交易笔数（TPS）：可能会有变化，下方公式可用于计算TPS：

$$
TPS=区块gas限制(30m) / 每笔交易平均gas限制 / 区块时间(2s)
$$

* 最终确定性：单时隙确定性。

#### 什么是DEX？[​](https://docs.berachain.com/learn/help/faqs#what-is-a-dex)

DEX全称去中心化交易所，其不由任何中心化服务商运行。用户可以使用钱包连接DEX，直接从钱包买卖、兑换各种链上资产，而无需将资产存入第三方托管账户。这意味着所有资产的流动性都可以直接在链上看到，并且可以验证由智能合约部署，DEX还允许任何人推出自己的代币并提供流动性。

#### 什么是兑换(Swap)？[​](https://docs.berachain.com/learn/help/faqs#what-is-a-swap)

Swap是指将一种代币兑换成另一种代币的过程，可以看作是买入或出售加密资产。例如，如果你想用`$ETH`购买`$BERA`，你需要将`$ETH`swap成`$BERA`，这本质上就是卖出`$ETH`，同时买入`$BERA`。

#### 兑换(swap)需要多少交易手续费？[​](https://docs.berachain.com/learn/help/faqs#how-much-does-it-cost-to-swap)

每次swap都需要支付交易手续费，具体取决于创建池时设定的协议费用，常见的协议费用为0.05%、0.1%、0.3%或1%，用户在swap时应始终检查，以确保对该池的协议费用满意。

#### 什么是流动性(liquidity)？[​](https://docs.berachain.com/learn/help/faqs#what-is-liquidity)

流动性是指可用于swap的代币数量。代币的流动性越高，swap成功率越高。

#### 什么是流动性池(liquidity pool / LP)？[​](https://docs.berachain.com/learn/help/faqs#what-is-a-liquidity-pool)

流动性池是流动性提供者将两种不同代币进行成对存款的地方，从而DEX用户可以在任意两种代币之间进行swap。

#### 什么是流动性提供者？[​](https://docs.berachain.com/learn/help/faqs#what-is-a-liquidity-provider)

流动性提供者是指将代币存入流动性池的用户，流动性提供者可以获得该池一定比例的协议费用奖励。

#### 什么是APY？[​](https://docs.berachain.com/learn/help/faqs#what-is-apy)

APY指年化收益率。在BEX池中，它指的是特定池的当前APY。

#### 什么是$HONEY？[​](https://docs.berachain.com/learn/help/faqs#what-is-honey)

`$HONEY`是Berachain生态系统的原生稳定币。它是一种由`$USDC`支持的稳定币，应用于整个Berachain生态系统。

#### 铸造或销毁$HONEY需要支付手续费吗？[​](https://docs.berachain.com/learn/help/faqs#does-it-cost-anything-to-mint-or-burn-honey)

为了确保稳定性，每次铸造和销毁`$HONEY`时都会收取少量费用。目前，该费用设置为铸造或销毁金额的0.5%，费用设置可通过治理提案进行更改。

此外，由于铸造和销毁需要交易，因此需要小额gas费用`$BERA`。

#### 测试网期间，哪些稳定币可以铸造$HONEY？[​](https://docs.berachain.com/learn/help/faqs#what-stablecoins-can-i-mint-honey-with-during-testnet)

有多种与美元挂钩的稳定币可用于铸造`$HONEY`。目前，测试网支持以下稳定币铸造`$HONEY`，也可能会根据治理情况添加更多代币：

* stgUSDC

#### 什么是$BGT？[​](https://docs.berachain.com/learn/help/faqs#what-is-bgt)

`$BGT`是Berachain的质押和治理代币，用于保障区块链安全，并是流动性证明的奖励代币，还可以在治理提案中拥有投票权。

#### 什么是验证者？[​](https://docs.berachain.com/learn/help/faqs#what-is-a-validator)

验证者包括以下角色：

1. 运行区块链节点以验证交易、生成区块并与网络中的其他验证者达成共识。
2. 拥有并运行验证者节点的实体。
3. 第1点和第2点的结合，管理部分流动性证明和进行治理投票。

[BGT Station](https://bartio.station.berachain.com/)属于上述第3种，BGT Station为用户提供参考，以决定委托给哪些验证者。

#### 为什么要委托$BGT？[​](https://docs.berachain.com/learn/help/faqs#why-should-i-delegate-my-bgt)

委托`$BGT`可以参与流动性证明，同时帮助保护区块链安全。

#### 为什么要委托$BGT而不是将其销毁以获得$BERA？

`$BGT`可以获得额外奖励是主要原因。有了流动性证明机制，`$BGT`持有人可以获得比任何其他链都多的奖励，如下：

* `$BGT` 通胀
* 链上价值捕获
  * DEX协议费用
  * $HONEY协议费用
  * Perps协议费用
* Gas费用

#### 如何获得$BGT？[​](https://docs.berachain.com/learn/help/faqs#how-do-i-get-bgt)

当验证者将`$BGT`存入奖励金库时，用户即可通过流动性证明获得奖励金库的`$BGT`。参阅[`$BGT`](/berachain-docs/learn/proof-of-liquidity/tokens/bgt)以了解更多信息。

#### 什么是治理？[​](https://docs.berachain.com/learn/help/faqs#what-is-governance)

治理是指社区决定对Berachain生态系统进行改进的过程。包括如何升级节点以及为链上的各个组件设置哪些参数。

#### BEX中的PoL白名单池的流动性提供者如何获得$BGT奖励？$BGT是否自动发送给流动性提供者？[​](https://docs.berachain.com/learn/help/faqs#once-you-ve-provided-liquidity-into-an-eligible-pool-in-bex-or-some-other-bgt-generating-action-like-bend-etc-how-do-you-get-bgt-is-bgt-automatically-sent-to-recipients)

BEX上每个合格的白名单流动性池都有一个关联的LP代币，用户将流动性存入合格的BEX池，协议将根据用户在该池的份额发放LP代币，随后用户必须将该LP代币质押进对应的奖励金库中，才有资格获得`$BGT`奖励。

同时当验证者将`$BGT`分发到奖励金库时，用户便可以申领积累的`$BGT`奖励，用户必须采取额外操作才能申领`$BGT`奖励，奖励不会自动发送给用户。

#### 只有验证者可以投票或创建提案吗？[​](https://docs.berachain.com/learn/help/faqs#can-only-validators-vote-on-or-create-proposals)

非也。任何拥有一定数量的`$BGT`持有人都可以创建提案，以及对提案投票。

#### Berachain中的实际质押代币是$BERA还是$BGT？[​](https://docs.berachain.com/learn/help/faqs#what-is-the-actual-staking-token-of-the-network-bera-or-bgt)

权益质押->`$BERA`，PoL奖励->`$BGT`

#### 仅拥有$BERA的验证者可以产出区块吗？奖励是什么？[​](https://docs.berachain.com/learn/help/faqs#can-validators-with-bera-alone-build-blocks-and-what-are-the-rewards)

然也。此类验证者可以获得交易优先费用，以及发送到其验证者地址的`$BGT`gas基本費用。

#### 只有拥有$BGT委托权益的验证者才能获得奖励吗？[​](https://docs.berachain.com/learn/help/faqs#do-incentives-only-go-to-the-validators-with-bgt-delegated-to-them)

验证者获得的奖励取决于其拥有的`$BGT`委托权重。

#### 奖励金库是将奖励派发到dApp中的单个池，还是整个dApp？[​](https://docs.berachain.com/learn/pol/faqs#can-rewards-vaults-route-emissions-to-a-single-pool-within-a-dapp-or-only-the-whole-dapp)[​](https://docs.berachain.com/learn/help/faqs#can-reward-vaults-route-emissions-to-a-single-pool-within-a-dapp-or-only-the-whole-dapp)

dApp可以为任何协议封装资产申请PoL金库白名单，该封装资产只需部署一个ERC-20凭证代币，用户就可以将其质押到金库中。


# 名词解释

### BERA代币[​](https://docs.berachain.com/learn/help/glossary#bera-token)

`$BERA`是Berachain生态的原生gas代币[​](https://docs.berachain.com/learn/help/glossary#bera-token)，用于支付交易费用，也是用于保护网络安全的初始验证者权益质押代币。更多信息请参阅[$BERA](/berachain-docs/learn/proof-of-liquidity/tokens/bera)。

### BGT代币

`$BGT`是Berachain的质押和治理代币，且不可转让，通过参与[流动性证明](#liu-dong-xing-zheng-ming)获得，也可以通过烧毁`$BGT`获得`$BERA`。该代币用于创建治理提案和对提案进行投票，还可以将其委托给验证者，增加验证者权重以被选中产出区块。更多信息请参阅[$BGT](/berachain-docs/learn/proof-of-liquidity/tokens/bgt)。

### BeaconKit[​](https://docs.berachain.com/learn/help/glossary#beaconkit)

BeaconKit是一个模块化和可定制的共识层框架，利用CometBFT共识算法构建，且与基于以太坊构架的区块链兼容。更多信息请参阅[BeaconKit](/berachain-docs/learn/introduction/what-is-beaconkit)。[​](https://docs.berachain.com/learn/help/glossary#beaconkit)

### Block / 区块[​](https://docs.berachain.com/learn/help/glossary#block)

包含交易列表的数据单元，将交易顺序打包，并添加到区块链。

### Bend[​](https://docs.berachain.com/learn/help/glossary#bend)

Berachain的原生借贷协议，从借贷(Lend)一词演化而来。更多信息请参阅[原生dApps > Bend](#bend)。

### BEX[​](https://docs.berachain.com/learn/help/glossary#bex)

Berachain的原生去中心化交易所，从去中心化交易所(DE&#x58;*)*&#x4E00;词演化而来。更多信息请参阅[原生dApps > BEX](/berachain-docs/learn/native-dapps/bex)。

### Berps[​](https://docs.berachain.com/learn/help/glossary#berps)

Berachain的原生永续合约交易所，从永续合约(Perp&#x73;*)*&#x4E00;词演化而来。更多信息请参阅[原生dApps > Berps](/berachain-docs/learn/native-dapps/berps)。

### Block Time[​](https://docs.berachain.com/learn/help/glossary#block-time) / 区块时间

区块链上产出新区块所需的时间。Berachain的平均区块时间为：<3秒。请注意，如果网络拥堵，区块时间可能会增加。

### CometBFT[​](https://docs.berachain.com/learn/help/glossary#cometbft)

Berachain正在采用的一种通用区块链共识引擎，用于实现高吞吐量和交易快速确认。更多信息请参阅[Cometbft](https://cometbft.com/)。

### Consensus Client / 共识客户端[​](https://docs.berachain.com/learn/help/glossary#consensus-client)

共识客户端是一款软件，负责在网络节点之间就区块链的当前状态达成一致。它负责处理交易和区块的验证流程，确保它们符合网络规范，并决定将哪些区块添加到区块链中。共识客户端专注于网络全局的规范和交易顺序的监督。它通常与执行客户端协作使用。

### Consensus Mechanism / 共识机制[​](https://docs.berachain.com/learn/help/glossary#consensus-mechanism)

Berachain网络中的节点根据共识机制就区块链的状态达成一致。Berachain的PoL共识机制根据验证者提供的流动性权重来选择验证者。

### Delegation / 委托[​](https://docs.berachain.com/learn/help/glossary#delegation)

代币持有人向网络中的其他参与者授予投票或验证权力的过程。

### DEX / 去中心化交易所[​](https://docs.berachain.com/learn/help/glossary#dex-decentralized-exchange)

一个无需第三方提供交易中介服务，直接在区块链上买卖代币的平台，所有流动性均通过智能合约实现。

### Engine API[​](https://docs.berachain.com/learn/help/glossary#engine-api)

Engine API是一个接口，允许EVM节点的执行层和共识层之间进行通信。[BeaconKit](/berachain-docs/learn/introduction/what-is-beaconkit)作为共识层，利用Engine API可以实现与任何执行客户端适配。

### Execution Client / 执行客户端[​](https://docs.berachain.com/learn/help/glossary#execution-client)

执行客户端（有时称为执行层）是一个软件应用程序，负责区块内交易的实际计算。EVM执行客户端使用EVM解析和执行智能合约代码，管理状态更改并执行交易逻辑。EVM客户端确保所有操作均根据智能合约的代码和EVM协议正确执行。

以下是常用的EVM执行客户端：

* Geth：由以太坊协议的官方Go语言实现。
* Erigon：从go-ethereum分叉出来的性能更高、功能更丰富的客户端。
* Nethermind：基于.NET框架的客户端，完全支持以太坊协议。
* Besu：企业级客户端，采用Java语言编写，获得Apache 2.0许可。
* Reth：基于Rust语言的客户端，注重性能和可靠性。
* Ethereumjs：以太坊基金会管理的基于Javascript的客户端。

### Finality / 最终确定性[​](https://docs.berachain.com/learn/help/glossary#finality)

确保交易一旦在区块链上确认，就无法篡改或撤销。Berachain为交易提供[单时隙最终性](https://ethereum.org/zh/roadmap/single-slot-finality/#what-is-finality)。

### Governance / 治理[​](https://docs.berachain.com/learn/help/glossary#governance)

Berachain生态的决策管理系统。治理涉及提案、投票和变更的实施，通常使用`$BGT`代币参与治理。

### HONEY[​](https://docs.berachain.com/learn/help/glossary#honey)

`$HONEY`是Berachain生态的原生稳定币，与`$USDC`锚定。它应用于整个Berachain生态，有铸造和销毁费用。更多信息请参阅[原生代币系统>$HONEY](/berachain-docs/learn/proof-of-liquidity/tokens/honey)。

### IBC[​](https://docs.berachain.com/learn/help/glossary#ibc)

一种跨链通信协议，提供基于Cosmos开发的区块链间的数据传输和互操作性服务。

### Liquidity / 流动性[​](https://docs.berachain.com/learn/help/glossary#liquidity)

体现两种不同加密资产之间稳定兑换的难易程度，流动性通常由用户通过流动性池提供。

### Liquidity Pool / 流动性池[​](https://docs.berachain.com/learn/help/glossary#liquidity-pool)

锁定在智能合约中的资金池，用于为去中心化交易所和其他DeFi服务提供流动性。Berachain上的流动性池可以容纳2种代币。

### Liquidity Provider / 流动性提供者[​](https://docs.berachain.com/learn/help/glossary#liquidity-provider)

将代币资产存入流动性池的用户，可从池中产生的swaps费用中获得部分收益。

### Mainnet / 主网[​](https://docs.berachain.com/learn/help/glossary#mainnet)

在Berachain中，主网指发生真实交易的区块链网络，主网代币资产具有实际价值，与用于提供开发环境的测试网对应。

### Polaris EVM[​](https://docs.berachain.com/learn/help/glossary#polaris-evm)

以太坊虚拟机的整体实现，构建在Cosmos SDK之上。在测试网V1版本中，Berachain采用Polaris以实现与以太坊智能合约的兼容性。在测试网V2版本中，Polaris已被弃用，取而代之的是模块化架构BeaconKit。

### 流动性证明[​](https://docs.berachain.com/learn/help/glossary#proof-of-liquidity)

Berachain所开创的共识机制，验证者具有公平的提议区块的机会，验证者奖励与用户委托给验证者的`$BGT`数量成比例关系。

### Single Slot Finality / 单时隙确定性[​](https://docs.berachain.com/learn/help/glossary#single-slot-finality)

指区块可以在同一Slot内提议并最终确定，无需等待，有时也称为*即时最终性*。

### Staking / 质押[​](https://docs.berachain.com/learn/help/glossary#staking)

锁定代币资产以支持区块链网络运行的过程。在Berachain中，质押用于保护网络安全和参与治理。

### Swap / 兑换[​](https://docs.berachain.com/learn/help/glossary#swap)

Swap是指在去中心化交易所中，将一种代币兑换成另一种代币的过程，可以看作是买入或出售加密资产。例如，如果你想用`$ETH`购买`$BERA`，你需要将`$ETH`swap成`$BERA`，这本质上就是卖出`$ETH`，同时买入`$BERA`。

每次swap都需要支付交易手续费，具体取决于创建池时设定的协议费用，常见的协议费用为0.05%、0.1%、0.3%或1%，用户在swap时应始终检查，以确保对该池的协议费用满意。


# 面向开发者的 Berachain


# 流动性证明架构

<figure><img src="/files/6MbPM6lyUTR8LpcKtu4K" alt="" width="563"><figcaption><p>此图概述了流动性证明（PoL）关键合约之间的相互作用</p></figcaption></figure>

### BeraChef.sol[​](https://docs.berachain.com/developers/#berachef-sol)

BeraChef合约负责存储验证者的偏好，以便将`$BGT`分配到奖励金库。

#### 关键术语

* **Cutting Board**：每个验证者都有自己的Cutting Board，用于存储他们对奖励金库的偏好和权重。当验证者被选中提议区块时，`$BGT`将分配到这些奖励金库。
* **Friends Of The Chef**：这些地址在验证者Cutting Board名单中有一席之地。换句话说，这是白名单[奖励金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)的合集。

#### 关键函数

`queueNewCuttingBoard`：此函数允许验证者设置未来区块的Cutting Board分配，此函数只能由验证者调用。

`activateQueuedCuttingBoard`：此函数由`Distributor`合约在验证者被选中提议区块时调用，并被激活。

`getActiveCuttingBoard` / `getQueuedCuttingBoard`：这些函数用于return既定验证者（被选中提议区块）活跃/队列中的cutting board数据。

`updateFriendsOfTheChef`：此函数用于更新`$BGT`接收者/奖励金库是否被列入白名单的状态。此函数只能由治理模块调用，这就是为什么需要治理提案来将新的奖励金库列入白名单，或对现有奖励金库进行更改。

### Distributor.sol[​](https://docs.berachain.com/developers/#distributor-sol)

Distributor合约负责分配来自奖励控制器的区块奖励。每个代币库都有自己的Cutting Board，如果不存在，则使用默认Cutting Board。如果治理(Governance)没有设置默认Cutting Board，则不会铸造和分发奖励。

#### 关键函数[​](https://docs.berachain.com/developers/#key-functions-1)

`distributeFor`：用于向既定验证者（被选中提议区块）的Cutting Board中列出的奖励金库分发`$BGT`奖励。证明者(Prover)的作用是证明既定验证者确实向`Distributor`合约提交了指定区块，以便相应地分发奖励。

### BerachainRewardsVault.sol[​](https://docs.berachain.com/developers/#berachainrewardsvault-sol)

俗称奖励金库(Reward Vaults)，奖励金库是一种合约，用户可以在其中质押符合PoL流动性证明要求的资产，以获得`$BGT`奖励。奖励金库还存储协议提供的奖励，在收到`$BGT`后分配给验证者。

#### 关键函数[​](https://docs.berachain.com/developers/#key-functions-2)

`addIncentive`：此函数控制奖励代币`$BGT`的产出，确保以既定的产出率分配`$BGT`发行。奖励代币必须首先通过`whitelistIncentiveToken`治理，列入白名单，并确定该代币的最低奖励率。

`stake`：此函数允许用户质押符合PoL要求的资产，以获得`$BGT`奖励。

`withdraw`：此函数允许用户从奖励金库提取质押资产。

### BGT.sol[​](https://docs.berachain.com/developers/#bgt-sol)

BGT合约负责处理与`$BGT`相关的所有事务，由治理模块控制，`$BGT`只能由`BlockRewardController`合约铸造。

#### 关键术语

* **Boosts**：`$BGT`持有人可以通过Boosts提高验证者出块奖励，从而验证者在提议区块后可以获得更多`$BGT`奖励。助力(boosts)也称为“委托”，`$BGT`持有人可以将boosts应用于多个验证者。
* **Sender Whitelist**：`$BGT`不可转让，只能向白名单地址发送（例如`$BGT` -> `$BERA`销毁器合约）。这是为了确保`$BGT`只分配给PoL参与者。

#### 关键函数[​](https://docs.berachain.com/developers/#key-functions-3)

`queueBoost`：此函数允许`$BGT`持有者帮助验证者加入Boosts队列，此函数只能由`$BGT`持有人调用。

`activateBoost`：此函数用于激活既定验证者的所有队列和Boosts，同一验证者的Boosts激活间隔时间是`8191`个区块，这是为了避免过度重新授权。

### BlockRewardController.sol[​](https://docs.berachain.com/developers/#blockrewardcontroller-sol)

BlockRewardController合约的主要功能是管理`$BGT`(Bera Governance Token)的奖励率，并处理`$BGT`奖励的铸造和分配。

#### 关键函数[​](https://docs.berachain.com/developers/#key-functions-4)

`processRewards`：此函数负责处理既定区块的奖励计算和分配。它根据基本费率、奖励费率以及验证者获得的Boosts来计算奖励，然后铸造并分配相应数量的`$BGT`代币。此函数由`Distributor`合约调用。


# 网络配置

### 一键添加网络

**Berachain Docs提供了一键连接，点击此页**[**一键添加网络**](https://docs.berachain.com/developers/network-configurations#add-the-network-in-one-click)**中的**<mark style="background-color:yellow;">**`Add Testnet`**</mark>**按钮即可。**

### 手动添加网络 <a href="#add-the-network-manually" id="add-the-network-manually"></a>

需要手动添加网络，请将下方参数添加进钱包自定义网络中：

|          |                                                                       |
| -------- | --------------------------------------------------------------------- |
| 网络名称     | Berachain bArtio                                                      |
| RPC 链接   | [https://bartio.rpc.berachain.com](https://bartio.rpc.berachain.com/) |
| 链 ID     | 80084                                                                 |
| Gas 代币符号 | BERA                                                                  |
| 区块浏览器链接  | [https://bartio.beratrail.io](https://bartio.beratrail.io/)           |

### RPC提供商 <a href="#rpc-providers" id="rpc-providers"></a>

* [Chainlist RPC列表](https://chainlist.org/chain/80084)
* [QuickNode](https://quicknode.notion.site/QuickNode-Benefits-for-Berachain-Developers-175d54ec5d644f598fde797633add2c1)
* [Nirvana Labs](https://nirvanalabs.io/nodes/berachain)
* [Alchemy](https://www.alchemy.com/)
* [Envio](https://docs.envio.dev/docs/HyperSync/hyperrpc-supported-networks) (optimized read-only)

{% hint style="info" %}
Berachain WebSocket连接可通过[RPC 合作伙伴](https://docs.berachain.com/developers/developer-tools#rpc-providers)获得。
{% endhint %}

### 什么是测试网 <a href="#what-is-a-testnet" id="what-is-a-testnet"></a>

测试网是主网的先行网络，它与主网独立运行，提供一个测试环境，测试网中的代币没有经济价值。

### 测试网有什么用 <a href="#what-is-a-testnet-used-for" id="what-is-a-testnet-used-for"></a>

* 创建测试地址并获取测试代币。
* 对开发的应用程序进行测试，确保程序在部署到主网时正常运行。
* 在应用程序主网部署前，先在Berachain测试网运行，排除故障和风险。

### 主网

Berachain主网目前尚未上线，正式上线日期待定。


# 已部署合约

下表是目前可供读取或写入的合约列表，另外Berachain Github提供了完整的合约ABI列表：

{% embed url="<https://github.com/berachain/doc-abis>" %}

<table><thead><tr><th width="157">合约名称</th><th width="467">合约地址</th><th>ABI文件</th></tr></thead><tbody><tr><td><a href="https://docs.berachain.com/developers/contracts/berachef">Berachef</a></td><td><a href="https://bartio.beratrail.io/address/0xfb81E39E3970076ab2693fA5C45A07Cc724C93c2">0xfb81E39E3970076ab2693fA5C45A07Cc724C93c2</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/BeraChef.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/bgt-token">BGT Token</a></td><td><a href="https://bartio.beratrail.io/address/0xbDa130737BDd9618301681329bF2e46A016ff9Ad">0xbDa130737BDd9618301681329bF2e46A016ff9Ad</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/BGT.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/bgt-staker">BGT Staker</a></td><td><a href="https://bartio.beratrail.io/address/0x791fb53432eED7e2fbE4cf8526ab6feeA604Eb6d">0x791fb53432eED7e2fbE4cf8526ab6feeA604Eb6d</a></td><td></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/block-rewards-controller">Block Rewards Controller</a></td><td><a href="https://bartio.beratrail.io/address/0x696C296D320beF7b3148420bf2Ff4a378c0a209B">0x696C296D320beF7b3148420bf2Ff4a378c0a209B</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/BlockRewardController.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/create2">CREATE2</a></td><td><a href="https://bartio.beratrail.io/address/0x4e59b44847b379578588920cA78FbF26c0B4956C">0x4e59b44847b379578588920cA78FbF26c0B4956C</a></td><td></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/distributor">Distributor</a></td><td><a href="https://bartio.beratrail.io/address/0x2C1F148Ee973a4cdA4aBEce2241DF3D3337b7319">0x2C1F148Ee973a4cdA4aBEce2241DF3D3337b7319</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/Distributor.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/fee-collector">Fee Collector</a></td><td><a href="https://bartio.beratrail.io/address/0x9B6F83a371Db1d6eB2eA9B33E84f3b6CB4cDe1bE">0x9B6F83a371Db1d6eB2eA9B33E84f3b6CB4cDe1bE</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/FeeCollector.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/governance">Governance</a></td><td><a href="https://bartio.beratrail.io/address/0xE3EDa03401Cf32010a9A9967DaBAEe47ed0E1a0b">0xE3EDa03401Cf32010a9A9967DaBAEe47ed0E1a0b</a></td><td></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/honey-factory">Honey Factory</a></td><td><a href="https://bartio.beratrail.io/address/0xAd1782b2a7020631249031618fB1Bd09CD926b31">0xAd1782b2a7020631249031618fB1Bd09CD926b31</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/HoneyFactory.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/honey-token">Honey Token</a></td><td><a href="https://bartio.beratrail.io/address/0x0E4aaF1351de4c0264C5c7056Ef3777b41BD8e03">0x0E4aaF1351de4c0264C5c7056Ef3777b41BD8e03</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/HONEY.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/multicall3">Multicall3</a></td><td><a href="https://bartio.beratrail.io/address/0xcA11bde05977b3631167028862bE2a173976CA11">0xcA11bde05977b3631167028862bE2a173976CA11</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/Multicall3.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/permit2">Permit2</a></td><td><a href="https://bartio.beratrail.io/address/0xA4Bf80b2CFBd80C00cB0Cc3d74C8762Ff4762770">0xA4Bf80b2CFBd80C00cB0Cc3d74C8762Ff4762770</a></td><td></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/rewards-vault">Rewards Vault</a></td><td></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/BerachainRewardsVault.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/rewards-vault-factory">Rewards Vault Factory</a></td><td><a href="https://bartio.beratrail.io/address/0x2B6e40f65D82A0cB98795bC7587a71bfa49fBB2B">0x2B6e40f65D82A0cB98795bC7587a71bfa49fBB2B</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/BerachainRewardsVaultFactory.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/timelock">Timelock</a></td><td><a href="https://bartio.beratrail.io/address/0xcB364028856f2328148Bb32f9D6E7a1F86451b1c">0xcB364028856f2328148Bb32f9D6E7a1F86451b1c</a></td><td><a href="http://localhost:5173/developers/deployed-contracts#TimeLock">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/usdc-token">USDC Token</a></td><td><a href="https://bartio.beratrail.io/address/0xd6D83aF58a19Cd14eF3CF6fe848C9A4d21e5727c">0xd6D83aF58a19Cd14eF3CF6fe848C9A4d21e5727c</a></td><td></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/wbera-token">WBERA Token</a></td><td><a href="https://bartio.beratrail.io/address/0x7507c1dc16935B82698e4C63f2746A2fCf994dF8">0x7507c1dc16935B82698e4C63f2746A2fCf994dF8</a></td><td><a href="https://github.com/berachain/doc-abis/blob/main/core/WBERA.json">ABI File</a></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/wbtc-token">WBTC Token</a></td><td><a href="https://bartio.beratrail.io/address/0x2577D24a26f8FA19c1058a8b0106E2c7303454a4">0x2577D24a26f8FA19c1058a8b0106E2c7303454a4</a></td><td></td></tr><tr><td><a href="https://docs.berachain.com/developers/contracts/weth-token">WETH Token</a></td><td><a href="https://bartio.beratrail.io/address/0xE28AfD8c634946833e89ee3F122C06d7C537E8A8">0xE28AfD8c634946833e89ee3F122C06d7C537E8A8</a></td><td></td></tr></tbody></table>


# 开发者工具

本节概述了Berachain网络上可用的开发者工具。由于Berachain与EVM兼容，如果你熟悉在其他EVM链上部署dApp，那么在Berachain上你会得心应手。

<table><thead><tr><th width="233">工具类型</th><th>提供商</th></tr></thead><tbody><tr><td>合约编程语言</td><td><a href="https://docs.soliditylang.org/en/v0.8.20/">Solidity</a>, <a href="https://docs.vyperlang.org/en/stable/">Vyper</a></td></tr><tr><td>开发环境</td><td><a href="https://github.com/foundry-rs/foundry">Foundry</a>, <a href="https://hardhat.org/">Hardhat</a>, <a href="https://remix.ethereum.org/">Remix</a></td></tr><tr><td>前端库</td><td><a href="https://viem.sh/">Viem</a>, <a href="https://docs.ethers.org/v5/">Ethers.js</a>, <a href="https://web3js.readthedocs.io/en/v1.10.0/">Web3.js</a></td></tr><tr><td>RPC提供商</td><td><a href="https://quicknode.notion.site/QuickNode-Benefits-for-Berachain-Developers-175d54ec5d644f598fde797633add2c1?pvs=4">QuickNode RPC</a>, <a href="https://nirvanalabs.io/nodes/berachain">Nirvana</a>, <a href="https://www.alchemy.com/">Alchemy</a>, <a href="https://envio.dev/">Envio</a> (optimized read-only)</td></tr><tr><td>钱包</td><td><a href="https://metamask.io/">Metamask</a>, <a href="https://frame.sh/">Frame</a>, <a href="https://rabby.io/">Rabby</a><br><a href="https://geth.ethereum.org/docs/interacting-with-geth/rpc">Geth JSON-RPC</a> 接口，用于调用链</td></tr><tr><td>Subgraphs和数据索引器</td><td><a href="https://goldsky.com/">Goldsky</a>, <a href="https://ghostgraph.xyz/">Ghost Graph</a>, <a href="https://goldrush.dev/docs/networks/berachain-testnet/">GoldRush</a> (powered by Covalent), <a href="https://envio.dev/">Envio</a></td></tr><tr><td>预言机</td><td><a href="https://api3.org/">API3</a>, <a href="https://chroniclelabs.org/">Chronicle</a>, <a href="https://pyth.network/">Pyth</a>, <a href="https://docs.redstone.finance/docs/introduction">Redstone</a>, <a href="https://www.stork.network/">Stork</a>, <a href="https://supra.com/">Supra</a></td></tr><tr><td>自动化执行</td><td><a href="https://www.gelato.network/web3-functions">Gelato</a></td></tr><tr><td>可验证随机性</td><td><a href="https://app.gelato.network/vrf">Gelato</a>, <a href="https://docs.pyth.network/entropy">Pyth</a></td></tr></tbody></table>


# 开发者快速入门


# 智能合约部署

[ERC-20代币标准](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)为Berachain网络代币部署提供了通用接口。ERC-20遵循标准接口，因此其他应用程序可以轻松地在链上与它们交互，并且可以扩展更多功能。该标准为用户提供从简单代币转移到复杂DeFi交互的全方位支持。

本节中，我们将介绍如何使用Solidity创建ERC-20代币，并将其部署到Berachain测试网。

### 先决条件[​](https://docs.berachain.com/developers/quickstart/#pre-requisites)

在开始之前，请确保您已准备好以下内容：

* Foundry工具包
* 你选择的文本编辑器

### 初始化Repository[​](https://docs.berachain.com/developers/quickstart/#initialize-repository)

首先，我们将使用Forge的`init`命令创建一个新项目：

```bash
forge init my_token;
```

这将创建一个名为`my_token`的新目录，其中包含基本的Forge项目结构和示例合约。如果使用VS Code作为文本编辑器，您可以添加`--vscode` flag，以初始化一些额外的默认设置。

```bash
forge init my_token --vscode;
```

现在您可以`cd`进入该目录，以便稍后运行代码：

```bash
cd my_token;
```

使用Foundry Forge格式化编写合约和测试合约，你可以随意删除下方生成的文件，因为本节不需要。

* `src/Counter.sol`
* `test/Counter.t.sol`
* `script/Counter.s.sol`

```bash
# FROM: ./my_token

rm src/Counter.sol test/Counter.t.sol script/Counter.s.sol;
```

### 安装依赖项[​](https://docs.berachain.com/developers/quickstart/#install-dependencies)

#### OpenZeppelin ERC-20[​](https://docs.berachain.com/developers/quickstart/#openzeppelin-erc-20)

OpenZeppelin提供了各种ERC代币标准（包括ERC-20）的常用接口和示例，这些代币经过审计和测试，因此可以使用他们的ERC-20标准接口来创建代币。这可以让我们更轻松地快速上手，而无需从头开始。

#### **Foundry**

如使用Foundry，请使用下方代码安装OpenZeppelin库：

```bash
# FROM: ./my_token

forge install openzeppelin/openzeppelin-contracts --no-commit;
```

上方代码将拉取`OpenZeppelin`请求，以暂存`.gitmodules`文件，并提交一条消息"Installed openzeppelin-contracts"。

要使用该库，请在项目的根目录下编辑 `remappings.txt`文件。

**文件位置**：`./remappings.txt`，运行以下代码：

```
ds-test/=lib/forge-std/lib/ds-test/src/
forge-std/=lib/forge-std/src/
@openzeppelin/=lib/openzeppelin-contracts/ // [!code++]
```

以上为了指引Foundry在编译合约时能正确调用`@openzeppelin`。

### 创建代币合约[​](https://docs.berachain.com/developers/quickstart/#create-the-token-contract)

现在你可以开始创建代币合约了，首先在`src/`文件夹中创建一个名为`MyToken.sol`的新文件。

```bash
# FROM: ./my_token

touch src/MyToken.sol;
```

然后，导入OpenZeppelin的ERC-20代币合约。

**文件位置：** `./src/MyToken.sol`，运行以下代码：

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import “@openzeppelin/contracts/token/ERC20/ERC20.sol”;
```

这将从OpenZeppelin中导入`ERC20`代币合约，其中包含ERC-20代币标准中所有函数的基本功能实现，可以以此作为代币合约的基础。

接下来，将创建可供实际使用的代币合约，该合约在导入的ERC-20合约基础上扩展。

* 代币名称设置为“MyToken”
* 代币符号设置为“MT”
* 代币初始供应设置为1,000,000

**文件位置**：`./src/MyToken.sol`，运行以下代码：

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import “@openzeppelin/contracts/token/ERC20/ERC20.sol”; 
import {ERC20} from “@openzeppelin/contracts/token/ERC20/ERC20.sol”; 

contract MyToken is ERC20 {
    uint256 public constant INITIAL_SUPPLY = 1_000_000 * 1 ether;

    constructor() ERC20(“MyToken”, “MT”){
        _mint(msg.sender, INITIAL_SUPPLY);
    }
}
```

{% hint style="info" %}
ERC-20代币标准的默认`小数位数`为18位，例如，`1ETH`只是以太坊代币的基本单位，还可以是`0.00000001ETH`。了解更多信息，请查看[OpenZeppelin Docs](https://docs.openzeppelin.com/contracts/3.x/erc20#a-note-on-decimals)\
上方合约部署可以解释为：创建了一个名为MyToken，代币符号为MT，代币初始供应量为100万，代币最小交易单位为小数点后18位的代币。
{% endhint %}

从技术上讲，完成以上操作，你已经成功创建代币！如果满意，你可以部署此合约，它会将100万个`$MT`代币发送到你部署合约的钱包(`msg.sender`)。接下来你可以随意处理这些代币，例如在Berachain BEX中将`$MT`与另一种代币创建流动性，以便其他用户可以交换获得`$MT`。

然而，我们通常希望代币的用途更广，以便脱颖而出。接下来，让我们为`$MT`代币添加更多功能。

### 设置转账销毁机制

通过重写OpenZeppelin `ERC20.sol`中的默认`_update`函数，添加一些常量。

**文件位置**：`ERC20.sol`，运行以下代码：

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyToken is ERC20 {
    uint256 public constant INITIAL_SUPPLY = 1_000_000 * 1 ether;
    uint256 public constant BURN_PERCENTAGE = 1; // 1%
    address public constant BURN_ADDRESS = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF; 

    constructor() ERC20("MyToken", "MT"){
        _mint(msg.sender, INITIAL_SUPPLY);
    }

    function _update(address sender, address recipient, uint256 amount) internal override { 
        uint256 burnAmount = (amount * BURN_PERCENTAGE) / 100;
        super._update(sender, recipient, amount - burnAmount);
        super._update(sender, BURN_ADDRESS, burnAmount);
    }
}
```

我们通过在`$MT`代币合约中使用`override` 修饰符重写了父合约 `_transfer`函数。我们仍然可以使用`super._transfer`调用父合约的默认`_transfer`函数，以在计算完销毁金额后运行实际的代币转账逻辑。

{% hint style="info" %}
上方合约部署可以解释为：每次转账时，合约会自动计算并销毁 1% 的代币，同时将剩余的 99% 转给接收者。
{% endhint %}

### 部署代币合约[​](https://docs.berachain.com/developers/quickstart/#deploy-token-contract)到Berachain

使用forge脚本将`$MT`代币合约部署到Berachain测试网。

```bash
# FROM: ./my_token

forge create --rpc-url https://bartio.rpc.berachain.com/ --private-key <YOUR_PRIVATE_KEY> src/MyToken.sol:MyToken --legacy;

# [Expected Output]:
# Deployer: 0x852Fc561Fd842ef1Af923ABfc64acC8A5624fe80
# Deployed to: 0x53E365fE5fDF332dD475E90bA8383B7F9853a49F
# Transaction hash: 0x59254ddcbb8dc1da89c7a1c7e300d8c6bd2f906b816b4497d046c717102d5725
```

### 验证代币合约[​](https://docs.berachain.com/developers/quickstart/#verifying-contract)

验证Berachain测试网上的`$MT`代币合约是否成功部署。

```bash
forge verify-contract 0x53E365fE5fDF332dD475E90bA8383B7F9853a49F src/MyToken.sol:MyToken --verifier-url 'https://api.routescan.io/v2/network/testnet/evm/80084/etherscan/api/' --etherscan-api-key "verifyContract" --num-of-optimizations 200

# [Expected Output]:
# Start verifying contract `0x53E365fE5fDF332dD475E90bA8383B7F9853a49F` deployed on mainnet
#
# Submitting verification for [src/MyToken.sol:MyToken] 0x53E365fE5fDF332dD475E90bA8383B7F9853a49F.
# Submitted contract for verification:
# Response: `OK`
# GUID: `321091ec-e529-5a11-a75c-cf1ffc6987d7`
# URL: https://etherscan.io/address/0x53e365fe5fdf332dd475e90ba8383b7f9853a49f
#
# !NOTE: Should be https://bartio.beratrail.io//address/0x53e365fe5fdf332dd475e90ba8383b7f9853a49f
```

### 后续步骤[​](https://docs.berachain.com/developers/quickstart/#next-steps)

现在，你已经掌握了如何使用Foundry将`ERC20`代币合约部署到Berachain测试网，请查看[开发者指南](/berachain-docs/developers/developer-guides)，学习部署其他合约或构建dApp。


# 前端部署

本节将展示如何构建一个前端，使其能够连接钱包并向Berachain发送RPC请求，以获取由[JSON-RPC endpoints](https://geth.ethereum.org/docs/interacting-with-geth/rpc)规范的当前测试网区块号。

首先，请检查你的浏览器钱包配置是否正确，并通过[BEX](https://bartio.bex.berachain.com/)能否顺利连接到Berachain测试网。

本节目标是使用Vanilla JavaScript与Berachain进行交互，以理解JSON-RPC请求的基本知识。

### 先决条件

开始之前，请确保你的本地设备上满足以下条件：

* VSCode IDE（推荐）
* NVM或Node `v18.18.2`
* `pnpm`, `yarn`或`npm`

### 代码设置 <a href="#code-setup" id="code-setup"></a>

创建文件夹：

```bash
mkdir frontend-berachain;
cd frontend-berachain;
```

实例化依赖项，用于启动一个HTTP服务器，在网页中查看HTML和JavaScript。

```bash
# FROM: ./frontend-berachain;

pnpm init;

# [Expected Output]:
# {
#   "name": "frontend-berachain",
#   "version": "1.0.0",
#   "description": "",
#   "main": "index.js",
#   "scripts": {
#     "test": "echo \"Error: no test specified\" && exit 1"
#   },
#   "keywords": [],
#   "author": "",
#   "license": "ISC"
# }
```

安装依赖项，用于实时刷新页面并创建一个新的HTTP服务器。

```bash
# FROM: ./frontend-berachain;

pnpm add -D live-server;
```

创建一个名为`app`的新文件夹，并在该文件夹中创建两个文件：`index.html`和`scripts.js` 。

```bash
# FROM: ./frontend-berachain;

mkdir app;
touch app/index.html;
touch app/scripts.js;
echo "node_modules" > .gitignore;
git init;
```

修改`index.html`文件。

**文件位置**：`./app/index.html`，运行以下代码：

```bash
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Berachain Frontend</title>
  </head>
  <body>
    <h1>Berachain Frontend</h1>
  </body>
</html>
```

通过向`package.json`添加 run 命令来查看更改。

**文件位置**：`./package.json`，运行以下代码：

```bash
{
  "name": "frontend-berachain",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "./node_modules/.bin/live-server --port=3001 --watch=app --mount=/:./app",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "live-server": "^1.2.2"
  }
}
```

运行以下代码启动服务器：

```bash
# FROM: ./frontend-berachain;

pnpm dev;

# [Expected Output]:
# Mapping / to "/path/to/frontend-berachain/app"
# Serving "/path/to/frontend-berachain" at http://127.0.0.1:3001
# Ready for changes
```

如下所示，服务器启动成功：

<figure><img src="/files/PQfuhKPMPVvjOw2gAwYy" alt="" width="563"><figcaption></figcaption></figure>

### 创建前端UI

方便起见，可以参考CDN中的[Tailwind](https://tailwindcss.com/)采用Tailwind HTML的classes。

通过添加一个指向Tailwind CDN `<script>`的标签文件和一个本地`scripts.js`文件，来修改`index.html`文件。

{% hint style="info" %}
下方操作是可选项，会使整个前端页面更好看，直男可忽略。
{% endhint %}

**文件位置**：`./app/index.html`，运行以下代码：

```bash
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="scripts.js"></script>
    <title>Berachain Frontend</title>
  </head>
  <body class="bg-zinc-900 pt-24 lg:pt-0">
    <main class="p-8">
      <h1 class="text-2xl text-white mb-4">Berachain Frontend</h1>

      <p class="text-zinc-400 mb-4">Must use MetaMask for wallet connection.</p>

      <!-- START: Main interaction to connect our wallet -->
      <div class="mb-6">
        <button
          type="button"
          disabled
          id="button-connect"
          class="h-10 bg-zinc-200 text-zinc-800 px-5 rounded-full font-medium disabled:bg-opacity-30"
        >
          Connect Wallet (Unsupported)
        </button>
        <div
          id="div-error-connect"
          class="mt-4 bg-red-300 rounded p-6 text-red-800 hidden"
        ></div>
      </div>
      <!-- END -->

      <hr class="border-zinc-700 mb-8" />

      <!-- START: Main section that will appear when our wallet is connected -->
      <section id="section-connected" class="hidden">
        <h2 id="wallet-connection" class="text-xl text-zinc-200 mb-4">
          Wallet Connection
        </h2>

        <p class="text-zinc-400 mb-4">
          If you're seeing this then your wallet is connected.
        </p>

        <div class="mb-4">
          <button
            type="button"
            id="button-disconnect"
            class="h-10 mb-2 bg-zinc-200 text-zinc-800 px-5 rounded-full font-medium disabled:bg-opacity-30"
          >
            Disconnect*
          </button>
          <p class="text-sm text-zinc-300">
            <small
              >*Remember you're not really disconnecting unless the wallet
              removes the website from Connected Sites.</small
            >
          </p>
        </div>
        <div class="mb-4">
          <label class="block mb-2 text-zinc-600">Wallet Connected</label>
          <code class="block bg-zinc-500 p-6 rounded bg-zinc-800 text-zinc-200">
            <pre id="pre-wallet-address"></pre>
          </code>
        </div>
        <div class="mb-6">
          <label class="block mb-2 text-zinc-600">Network</label>
          <code class="block bg-zinc-500 p-6 rounded bg-zinc-800 text-zinc-200">
            <pre id="pre-wallet-network"></pre>
          </code>
        </div>

        <hr class="border-zinc-700 mb-8" />

        <h2 id="eth-blocknumber" class="text-xl text-zinc-100 mb-4">
          Get Berachain Block Number
        </h2>

        <p class="text-zinc-400 mb-4">
          Will make a JSON-RPC request to Berachain to retrieve the current
          block number with
          <span class="bg-zinc-700 text-zinc-200 py-1 px-1.5 rounded"
            >eth_blockNumber</span
          >.
        </p>

        <form id="form-eth-blocknumber">
          <div class="mb-4">
            <button
              type="submit"
              class="h-10 mb-2 bg-zinc-200 text-zinc-800 px-5 rounded-full font-medium disabled:bg-opacity-30"
            >
              Get Block Number
            </button>
          </div>

          <!-- Where the results are displayed -->
          <div class="mb-4">
            <label class="block mb-2 text-zinc-600">Response</label>
            <code
              class="block bg-zinc-500 p-6 rounded bg-zinc-800 text-zinc-200"
            >
              <pre id="pre-eth-blocknumber"></pre>
            </code>
          </div>
        </form>
      </section>
      <!-- END -->
    </main>
  </body>
</html>
```

如下所示，UI美化成功：

<figure><img src="/files/Fp8TtP6TXUXO4jogVpjm" alt="" width="563"><figcaption></figcaption></figure>

### 添加JavaScript <a href="#javascript-functionality" id="javascript-functionality"></a>

设置好HTML结构，现在添加允许将钱包连接到浏览器的JavaScript功能。这一步需要使用相当多的代码，请仔细查看注释以便了解所有功能。

**文件位置**：`./app/scripts.js`，运行以下代码：

```bash
// Main Function
// ========================================================
/**
 * Main wallet connection interaction
 */
const connect = async () => {
  console.group("connect");

  // Hide errors when trying to connect
  const devErrorConnect = document.getElementById("div-error-connect");
  devErrorConnect.innerHTML = "";
  devErrorConnect.classList = devErrorConnect.classList.value.includes("hidden")
    ? devErrorConnect.classList.value
    : `${devErrorConnect.classList.value} hidden`;

  // Attempt to connect to wallet with JSON-RPC request
  try {
    const accounts = await window.ethereum.request({
      method: "eth_requestAccounts",
    });
    const chainId = await ethereum.request({ method: "eth_chainId" });

    // Disable connect button
    const buttonConnect = document.getElementById("button-connect");
    buttonConnect.setAttribute("disabled", true);
    buttonConnect.innerHTML = "Connected";

    // Show connected section
    const sectionConnected = document.getElementById("section-connected");
    sectionConnected.classList = "";

    // Display wallet connected
    const preWalletAddress = document.getElementById("pre-wallet-address");
    preWalletAddress.innerHTML = accounts[0];

    // Display current network connected
    const preWalletNetwork = document.getElementById("pre-wallet-network");
    preWalletNetwork.innerHTML = `${chainId}`;
  } catch (error) {
    console.log({ error });
    devErrorConnect.innerHTML =
      error?.message ?? "Unknown wallet connection error.";
    devErrorConnect.classList = devErrorConnect.classList.value.replaceAll(
      "hidden",
      ""
    );
  }
  console.groupEnd();
};

/**
 * Main function that disconnects from the browser
 */
const disconnect = () => {
  console.group("disconnect");

  // Hide connected section
  const sectionConnected = document.getElementById("section-connected");
  sectionConnected.classList = "hidden";

  // Enabled connect button
  const buttonConnect = document.getElementById("button-connect");
  buttonConnect.removeAttribute("disabled");
  buttonConnect.innerHTML = "Connect Wallet";

  console.groupEnd();
};

/**
 * Main function that handles the form request for a read JSON-RPC request
 * @param {*} event
 */
const onSubmitEthBlockNumber = async (event) => {
  event.preventDefault();
  console.group("onSubmitEthBlockNumber");

  // Reset & Set Loading State
  const preEthBlockNumber = document.getElementById("pre-eth-blocknumber");
  const button = document.querySelector(`#${event.currentTarget.id} button`);
  button.setAttribute("disabled", true);
  button.innerHTML = `${button.innerHTML} (Loading...)`;

  // Attempt request for block number
  try {
    const result = await window.ethereum.request({
      method: "eth_blockNumber",
    });

    console.log({ result });

    preEthBlockNumber.innerHTML = `${result}\n\n// Block Number:\n// ${parseInt(
      result,
      16
    )}`;
  } catch (error) {
    console.log({ error });
    preEthBlockNumber.innerHTML = error?.message ?? "Unknown JSON-RPC error.";
  }

  button.removeAttribute("disabled");
  button.innerHTML = "Get Block Number";
};

// Initial Script Loaded On Window Loaded
// ========================================================
/**
 * Init
 */
window.onload = async () => {
  console.log("WINDOW ONLOAD!");

  // Get All Elements
  const buttonConnect = document.getElementById("button-connect");
  const buttonDisconnect = document.getElementById("button-disconnect");
  const formEthBlockNumber = document.getElementById("form-eth-blocknumber");

  // Add Interactions
  buttonConnect.addEventListener("click", connect);
  buttonDisconnect.addEventListener("click", disconnect);
  formEthBlockNumber.addEventListener("submit", onSubmitEthBlockNumber);

  // Check if browser has wallet integration
  if (typeof window?.ethereum !== "undefined") {
    // Activate elements
    buttonConnect.removeAttribute("disabled");
    buttonConnect.innerHTML = "Connect Wallet";
  }
};
```

现在，如果连接到安装了MetaMask钱包的浏览器，且你的钱包已设置为Berachain测试网，便可以看到如图所示的交互信息。另外，你可以连接到该站点以查看当前钱包地址和正在使用的链 ID。

<figure><img src="/files/pn6j2gqgG3bFA8HAUsre" alt="" width="563"><figcaption></figcaption></figure>

现在，你可以通过前端UI，提交表单执行RPC请求，并可以看到显示的结果。

<figure><img src="/files/MyARQCs62GCb3pxrkwNU" alt="" width="563"><figcaption></figcaption></figure>

### 后续步骤 <a href="#next-steps" id="next-steps"></a>

有很多库和框架(libraries/frameworks)可以帮助开发者快速构建dApp，例如React、NextJS、Svelte、Wagmi、Ethers、Viem、WalletConnect和RainbowKit等。请参阅[开发者工具](/berachain-docs/developers/for-developers/developer-tools)以了解更多。

现在，你已经掌握了如何通过前端与Berachain进行交互，请查看[开发者指南](/berachain-docs/developers/developer-guides)，学习构建合约或其他前端应用程序。


# 开发者指南


# 使用 Hardhat 部署 HelloWorld 合约

{% hint style="info" %}
请在GitHub参阅完整的[hardhat-viem-helloworld](https://github.com/berachain/guides/tree/main/apps/hardhat-viem-helloworld)代码库。
{% endhint %}

本节将展示如何使用[Hardhat](https://hardhat.org/)创建新的Solidity合约，配置Berachain网络详细信息，将合约部署到Berachain，以及验证合约。

### 先决条件

开始之前，请确保你的本地设备上满足以下条件：

* 持有`$BERA`代币的钱包（合约部署费用，参阅[Berachain测试网水龙头](/berachain-docs/learn/native-dapps/testnet-faucet)文档）
* NVM或Node `v18.18.2`
* `pnpm`, `yarn` 或 `npm`

### 创建HelloWorld代码设置 <a href="#creating-helloworld-project-code-setup" id="creating-helloworld-project-code-setup"></a>

首先，为HelloWorld创建一个新的文件夹：

```bash
mkdir create-helloworld-contract-using-hardhat;
cd create-helloworld-contract-using-hardhat;
```

然后，启动`Hardhat`，并创建`viem`模板：

```bash
# FROM ./create-helloworld-contract-using-hardhat;

npx hardhat init;

# [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.18.3 👷‍
#
# ✔ What do you want to do? · Create a TypeScript project (with Viem)
# ✔ Hardhat project root: · /path/to/create-helloworld-contract-using-hardhat
# ✔ Do you want to add a .gitignore? (Y/n) · y
# ✔ Do you want to install this sample project's dependencies with npm (hardhat @nomicfoundation/#  hardhat-toolbox-viem)? (Y/n) · y
```

安装`dotenv`依赖项，以便使用环境变量。

```bash
# FROM ./create-helloworld-contract-using-hardhat;

pnpm add -D dotenv;
```

### 创建HelloWorld合约 <a href="#creating-the-helloworld-contract" id="creating-the-helloworld-contract"></a>

上述操作，Hardhat创建了需要的文件。现在，已经准备好一切，可以创建一个新的Solidity合约了。

首先，将Hardhat创建的文件重命名为`HelloWorld.sol`：

```bash
# FROM ./create-helloworld-contract-using-hardhat;

# Renames `Lock.sol` to `HelloWorld.sol`
mv contracts/Lock.sol contracts/HelloWorld.sol;
```

然后，替换重命名的`HelloWorld.sol`文件中的现有代码。

**文件位置**：`./contract/HelloWorld.sol`，运行以下代码：

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

contract HelloWorld {
    // Events that allows for emitting a message
    event NewGreeting(address sender, string message);

    // Variables
    string greeting;

    // Main constructor run at deployment
    constructor(string memory _greeting) {
        greeting = _greeting;
        emit NewGreeting(msg.sender, _greeting);
    }

    // Get function
    function getGreeting() public view returns (string memory) {
        return greeting;
    }

    // Set function
    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
        emit NewGreeting(msg.sender, _greeting);
    }
}
```

我们已经创建了一个新的Solidity合约，接下来测试合约能否成功编译：

```bash
# FROM ./create-helloworld-contract-using-hardhat;

npx hardhat compile;

# [Expected Output]:
# Compiled 1 Solidity file successfully (evm target: paris).
```

你还可以通过对`package.json`文件进行一些修改，简化编译步骤。

**文件位置**：`./package.json`，运行以下代码：

```json
{
  "name": "create-helloworld-contract-using-hardhat",
  "scripts": {

    "compile": "./node_modules/.bin/hardhat compile"
  }, 
  "devDependencies": {
    "@nomicfoundation/hardhat-toolbox-viem": "^1.0.0",
    "dotenv": "^16.3.1",
    "hardhat": "^2.18.3"
  }
}
```

现在，可以使用下方代码编译合约：

```bash
# FROM ./create-helloworld-contract-using-hardhat;

pnpm compile; # npm run compile or yarn run compil;

# [Expected Output]:
# Nothing to compile
```

### 测试HelloWorld合约 <a href="#testing-the-helloworld-contract" id="testing-the-helloworld-contract"></a>

合约成功创建后，需要通过编写一些测试程序来确保合约能正常运行。

首先，重命名Hardhat在`/test`目录中创建的测试文件：

```bash
# FROM ./create-helloworld-contract-using-hardhat;

# Renames `Lock.ts` to `HelloWorld.test.ts`
mv test/Lock.ts test/HellWorld.test.ts;
```

然后，替换重命名的`HelloWorld.test.ts`文件中的现有代码。

**文件位置**：`./test/HelloWorld.test.ts`，运行以下代码：

```tsconfig
// Imports
// ========================================================
import { loadFixture } from "@nomicfoundation/hardhat-toolbox-viem/network-helpers";
import { expect } from "chai";
import hre from "hardhat";

// Tests
// ========================================================
describe("HelloWorld", 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 deployFixture() {
    // Contracts are deployed using the first signer/account by default
    const [owner, otherAccount] = await hre.viem.getWalletClients();

    const contract = await hre.viem.deployContract("HelloWorld", [
      "Test Message",
    ]);
    const publicClient = await hre.viem.getPublicClient();

    return {
      owner,
      otherAccount,
      publicClient,
      contract,
    };
  }

  /**
   *
   */
  describe("Deployment", function () {
    /**
     *
     */
    it("Should deploy with original message", async function () {
      // Setup
      const { contract } = await loadFixture(deployFixture);

      // Init + Expectations
      expect(await contract.read.getGreeting()).to.equal("Test Message");
    });

    /**
     *
     */
    it("Should set a new message", async function () {
      // Setup
      const { contract, owner } = await loadFixture(deployFixture);

      // Init
      await contract.write.setGreeting(["Hello There"]);

      // Expectations
      expect(await contract.read.getGreeting()).to.equal("Hello There");
    });
  });
});
```

接下来，运行下方代码以运行测试程序：

```bash
# FROM ./create-helloworld-contract-using-hardhat;

npx hardhat test;

# [Expected Output]:
#   HelloWorld
#     Deployment
#       ✔ Should deploy with original message (2723ms)
#       ✔ Should set a new message
#
#
#   2 passing (3s)
```

你还可以通过对`package.json`文件进行一些修改，以便更轻松地运行`pnpm test`测试程序。

**文件位置**：`./package.json`，运行以下代码：

```json
{
  "name": "create-helloworld-contract-using-hardhat",
  "scripts": {
    "compile": "./node_modules/.bin/hardhat compile",
    "test": "./node_modules/.bin/hardhat test"
  },
  "devDependencies": {
    "@nomicfoundation/hardhat-toolbox-viem": "^1.0.0",
    "dotenv": "^16.3.1",
    "hardhat": "^2.18.3"
  }
}
```

### 为Berachain合约部署配置Hardhat

{% hint style="info" %}
通过Hardhat创建viem模板的方式部署的合约，目前尚未完全支持开箱即用的自定义链，但在 Berachain主网启动后将会支持。
{% endhint %}

首先，为了正确设置`hardhat.config.ts`，需要使用`dotenv`安装包创建一个`.env`文件，用于声明环境变量，供配置读取。

```bash
# FROM ./create-helloworld-contract-using-hardhat;

touch .env;
```

然后，在新建的`.env`文件中，运行以下代码，**文件位置**：`./.env`。

```bash
# Chain Configurations
CHAIN_ID=80084
NETWORK_NAME="berachainbArtio"
CURRENCY_DECIMALS=18
CURRENCY_NAME="BERA Token"
CURRENCY_SYMBOL="BERA"

# API key for Beratrail Block Explorer, can be any value for now
BLOCK_EXPLORER_NAME=Beratrail Block Explorer
BLOCK_EXPLORER_API_KEY=xxxxx
BLOCK_EXPLORER_API_URL=https://api.routescan.io/v2/network/testnet/evm/80084/etherscan/api/
BLOCK_EXPLORER_URL=https://bartio.beratrail.io/

# Wallet + RPC configurations
RPC_URL=https://bartio.rpc.berachain.com/
# Private key generated from Hardhat local - replace with Berachain
# NEVER SHARE THIS WITH ANYONE AND AVOID COMMITTING THIS WITH YOUR GIT REPOSITORY
WALLET_PRIVATE_KEY=0xYOUR_WALLET_PRIVATE_KEY
```

{% hint style="info" %}
代币合约参数支持自定义，总体配置步骤是相同的。
{% endhint %}

设置好环境变量后，需要将它们加载到`hardhat.config.ts`文件。

**文件位置**：`./hardhat.config.ts`，运行以下代码：

```tsconfig
// Imports
// ========================================================
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox-viem";
import dotenv from "dotenv";

// Load Environment Variables
// ========================================================
dotenv.config();

// Main Hardhat Config
// ========================================================
const config: HardhatUserConfig = {
  solidity: "0.8.19",
  networks: {
    // For localhost network
    hardhat: {
      chainId: 1337,
    },
    // NOTE: hardhat viem currently doesn't yet support this method for custom chains through Hardhat config ↴
    berachainTestnet: {
      chainId: parseInt(`${process.env.CHAIN_ID}`),
      url: `${process.env.RPC_URL || ""}`,
      accounts: process.env.WALLET_PRIVATE_KEY
        ? [`${process.env.WALLET_PRIVATE_KEY}`]
        : [],
    },
  },
};

// Exports
// ========================================================
export default config;
```

### 在Berachain部署HelloWorld合约 <a href="#deploying-helloworld-contract" id="deploying-helloworld-contract"></a>

我们已经完成了所有配置设置，现在尝试运行一个本地节点，并将其部署到本地环境。

首先，通过对`package.json`文件进行一些修改，让部署运行更轻松。

**文件位置**： `./package.json`，运行以下代码：

```json
{
  "name": "create-helloworld-contract-using-hardhat",
  "scripts": {
    "compile": "./node_modules/.bin/hardhat compile",
    "node": "./node_modules/.bin/hardhat node", 
    "deploy:localhost": "./node_modules/.bin/hardhat run scripts/deploy.ts --network localhost", 
    "deploy:berachain": "./node_modules/.bin/hardhat run scripts/deploy.ts --network berachainTestnet", 
    "test": "./node_modules/.bin/hardhat test"
  },
  "devDependencies": {
    "@nomicfoundation/hardhat-toolbox-viem": "^1.0.0",
    "dotenv": "^16.3.1",
    "hardhat": "^2.18.3"
  }
}
```

接下来，配置`./scripts/deploy.ts`脚本，以确保合约正确部署。

**文件位置**： `./scripts/deploy.ts`，运行以下代码：

```tsconfig
// Imports
// ========================================================
import hre from "hardhat";

// Main Deployment Script
// ========================================================
async function main() {
  const contract = await hre.viem.deployContract("HelloWorld", [
    "Hello from the contract!",
  ]);
  console.log(`HelloWorld 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;
});
```

部署脚本配置好后，我们可以在一个终端运行本地节点，并在另一个终端部署合约。

#### 终端 1：部署合约

```bash
# FROM ./create-helloworld-contract-using-hardhat;

pnpm 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.
#
# Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
# Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80bash
```

使用上方代码中提供的私钥`Private Key`，替换`.env` 文件中的`WALLET_PRIVATE_KEY`。

**文件位置**：`./.env`，运行以下代码：

```bash
WALLET_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
```

#### 终端 2：运行本地节点

```bash
# FROM ./create-helloworld-contract-using-hardhat;

pnpm deploy:localhost;
# [Expected Similar Output]:
# HelloWorld deployed to 0x5fbdb2315678afecb367f032d93f642f64180aa3
```

现在，合约已成功部署到本地节点，接下来配置部署脚本，以便合约直接部署到Berachain网络。

{% hint style="info" %}
要使viem支持自定义链，需要进行额外配置，下方代码展示了如何为Berachain设置额外配置。当Berachain主网上线时，这些额外配置可能不再需要。
{% endhint %}

**文件位置**：`./scripts/deploy.ts`，运行以下代码：

```tsconfig
// Imports
// ========================================================
import hre from "hardhat";
import fs from "fs"; 
import { defineChain } from "viem"; 
import { privateKeyToAccount } from "viem/accounts"; 

// Config Needed For Custom Chain
// ========================================================
const chainConfiguration = defineChain({

  id: parseInt(`${process.env.CHAIN_ID}`), 
  name: `${process.env.NETWORK_NAME}`, 
  network: `${process.env.NETWORK_NAME}`, 
  nativeCurrency: {

    decimals: parseInt(`${process.env.CURRENCY_DECIMALS}`), 
    name: `${process.env.CURRENCY_NAME}`, 
    symbol: `${process.env.CURRENCY_SYMBOL}`, 
  }, 
  rpcUrls: {

    default: {

      http: [`${process.env.RPC_URL}`], 
    }, 
    public: {

      http: [`${process.env.RPC_URL}`], 
    }, 
  }, 
  blockExplorers: {

    default: {
      name: `${process.env.BLOCK_EXPLORER_NAME}`,
      url: `${process.env.BLOCK_EXPLORER_URL}`,
    }, 
  }, 
}); 

// Main Deployment Script
// ========================================================
async function main() {
  // NOTE: hardhat with viem currently doesn't support custom chains so there needs to be some custom functionality ↴
  if (hre.network.name === "berachainTestnet") {

    // Retrieve contract artifact ABI & Bytecode
    const contractName = "HelloWorld"; 
    const artifactFile = fs.readFileSync(
      `${hre.artifacts._artifactsPath}/contracts/${contractName}.sol/${contractName}.json`
    ); 
    const artifactJSON = JSON.parse(artifactFile.toString()) as any; 

    // Configure wallet client
    const walletClient = await hre.viem.getWalletClient(

      // wallet account
      privateKeyToAccount(hre.network.config.accounts?.[0] as `0x${string}`), 
      // configured chain
      {

        chain: chainConfiguration, 
      } 
    ); 

    // Deploy contract
    const hash = await walletClient.deployContract({

      abi: artifactJSON.abi, 
      bytecode: artifactJSON.bytecode, 
      args: ["Hello From Deployed Contract"], 
    }); 
    console.log({ hash }); 

    // Retrieve deployed contract address
    const publicClient = await hre.viem.getPublicClient({

      chain: chainConfiguration, 
    }); 
    const receipt = await publicClient.waitForTransactionReceipt({ hash }); 
    console.log(`${contractName} deployed to ${receipt?.contractAddress}`); 
  } else {

    const contract = await hre.viem.deployContract("HelloWorld", [
      "Hello from the contract!",
    ]);
    console.log(`HelloWorld 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;
});
```

接下来，将`WALLET_PRIVATE_KEY`替换为一个拥有`$BERA`代币的钱包，可以从[Berachain测试网水龙头](/berachain-docs/learn/native-dapps/testnet-faucet)获取测试网`$BERA`代币。

**文件位置**：`./.env`，运行以下代码：

```bash
WALLET_PRIVATE_KEY=0xYOUR_WALLET_PRIVATE_KEY
```

现在，可以直接将合约部署到Berachain了。

```bash
# FROM ./create-helloworld-contract-using-hardhat;

pnpm deploy:berachain;

# [Expected Similar Output]:
# {
#   hash: '0x3ff0120c126b20d9f286657521c9d2d1edbb38f60dcd5fc6b95638a192588182'
# }
# HelloWorld deployed to 0x38f8423cc4390938c01616d7a9f761972e7f116a
```

你可以运行下方代码，在Berachain Beratrail区块浏览器中查看部署的合约：

```bash
open https://bartio.beratrail.io/address/0x38f8423cc4390938c01616d7a9f761972e7f116a

# [Expected Result Should Open Your Browser]
```

你会看到合约已经成功部署，但未被验证，因为它仍显示合约字节码，接下来需要验证合约。

### 验证HelloWorld合约 <a href="#verifying-helloworld-contract" id="verifying-helloworld-contract"></a>

为了验证合约，需要在`hardhat.config.ts`文件中添加一个额外配置。

**文件位置**：`./hardhat.config.ts`，运行以下代码：

```tsconfig
// Imports
// ========================================================
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox-viem";
import dotenv from "dotenv";

// Load Environment Variables
// ========================================================
dotenv.config();

// Main Hardhat Config
// ========================================================
const config: HardhatUserConfig = {
  solidity: "0.8.19",
  networks: {
    hardhat: {
      chainId: 1337,
    },
    // NOTE: hardhat viem currently doesn't yet support this method for custom chains through Hardhat config ↴
    berachainTestnet: {
      chainId: parseInt(`${process.env.CHAIN_ID}`),
      url: `${process.env.RPC_URL || ""}`,
      accounts: process.env.WALLET_PRIVATE_KEY
        ? [`${process.env.WALLET_PRIVATE_KEY}`]
        : [],
    },
  }, 
  // For Contract Verification
  etherscan: {

    apiKey: `${process.env.BLOCK_EXPLORER_API_KEY}`, 
    customChains: [

      {

        network: "Berachain Testnet", 
        chainId: parseInt(`${process.env.CHAIN_ID}`), 
        urls: {

          apiURL: `${process.env.BLOCK_EXPLORER_API_URL}`, 
          browserURL: `${process.env.BLOCK_EXPLORER_URL}`, 
        }, 
      }, 
    ], 
  }, 
};

// Exports
// ========================================================
export default config;
```

完成额外配置后，通过向`package.json`添加 run 命令来查看更改。

**文件位置**：`./package.json`，运行以下代码：

```json
{
  "name": "create-helloworld-contract-using-hardhat",
  "scripts": {
    "compile": "./node_modules/.bin/hardhat compile",
    "node": "./node_modules/.bin/hardhat node",
    "deploy:localhost": "./node_modules/.bin/hardhat run scripts/deploy.ts --network localhost",
    "deploy:berachain": "./node_modules/.bin/hardhat run scripts/deploy.ts --network berachainTestnet",
    "test": "./node_modules/.bin/hardhat test",
    "verify": "./node_modules/.bin/hardhat verify --network berachainTestnet"
  },
  "devDependencies": {
    "@nomicfoundation/hardhat-toolbox-viem": "^1.0.0",
    "dotenv": "^16.3.1",
    "hardhat": "^2.18.3"
  }
}
```

最后，使用合约部署地址和初始参数`Hello From Deployed Contract`，运行下方代码验证合约。

```bash
# FROM ./create-helloworld-contract-using-hardhat;

# Equivalent to: npx hardhat verify 0x38f8423cc4390938c01616d7a9f761972e7f116a "Hello From Deployed Contract"
pnpm verify 0x38f8423cc4390938c01616d7a9f761972e7f116a "Hello From Deployed Contract";

# [Expected Output]:
#
# Successfully submitted source code for contract
# contracts/HelloWorld.sol:HelloWorld at 0x38f8423cc4390938c01616d7a9f761972e7f116a
# for verification on the block explorer. Waiting for verification result...
#
# Successfully verified contract HelloWorld on the block explorer.
# https://bartio.beratrail.io/address/0x38f8423cc4390938c01616d7a9f761972e7f116a#code
```

在Beratail可以看到，合约已成功验证，并且可以查看到合约Solidity代码。

### 完整代码库 <a href="#full-code-repository" id="full-code-repository"></a>

本节完整代码库，可在[Github - Berachain Guides](https://github.com/berachain/guides/) - [hardhat-viem-helloworld](https://github.com/berachain/guides/tree/main/apps/hardhat-viem-helloworld)中查看。

{% embed url="<https://github.com/berachain/guides/tree/main/apps/hardhat-viem-helloworld>" %}


# 使用 Foundry 部署 ERC20 合约

{% hint style="info" %}
请在GitHub参阅完整的[foundry-erc20](https://github.com/berachain/guides/tree/main/apps/foundry-erc20)代码库。
{% endhint %}

本节将展示如何使用[Foundry](https://getfoundry.sh/)创建新的Solidity合约，配置Berachain网络详细信息，将合约部署到Berachain，以及验证合约。

### 先决条件

开始之前，请确保你的本地设备上满足以下条件：

* 参考[Foundry安装文档](https://book.getfoundry.sh/getting-started/installation)安装该软件。

### 创建ERC20合约代码设置

首先，为ERC20合约创建一个新的文件夹：

```bash
mkdir create-erc20-contract-using-foundry;
cd create-erc20-contract-using-foundry;
```

然后，运行以下代码，创建由Foundry定义的初始ERC20合约模板：

```bash
# FROM: ./create-erc20-contract-using-foundry

forge init; # forge init --force; # if there is already an existing .git repository associated

# [Expected Output]:
# ...
# Resolving deltas: 100% (129/129), done.
#     Installed forge-std v1.7.1
#     Initialized forge project
```

如果模板创建成功，会显示以下代码结构：

```bash
# FROM: ./create-erc20-contract-using-foundry
.
├── README.md
├── foundry.toml
├── lib
│   └── forge-std
├── script
│   └── Counter.s.sol
├── src
│   └── Counter.sol
└── test
    └── Counter.t.sol
```

现在，所有代码已设置完成，运行以下代码，安装来自[OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts)的ERC20合约所需的依赖项：

```bash
# FROM: ./create-erc20-contract-using-foundry

forge install OpenZeppelin/openzeppelin-contracts;
# If existing git setup run:
# forge install OpenZeppelin/openzeppelin-contracts --no-commit;

# [Expected Output]:
# ...
# Resolving deltas: 100% (129/129), done.
#     Installed openzeppelin-contracts v5.0.0
```

### 创建ERC20合约

开始之前，请将现有的`src/Counter.sol`转换为新的`BingBongToken.sol`，并将代码替换为以下 Solidity代码：

```bash
# FROM: ./create-erc20-contract-using-foundry

mv src/Counter.sol src/BingBongToken.sol;
```

**文件位置**：`./src/BingBongToken.sol`

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

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

contract BingBongToken is ERC20 {
    /**
     * @dev Init constructor for setting token name and symbol
     */
    constructor(string memory name_, string memory symbol_, uint256 mintedTokens_) ERC20(name_, symbol_) {
        _mint(msg.sender, mintedTokens_);
    }
}
```

运行以下代码，测试编译是否正确：

```bash
# FROM: ./create-erc20-contract-using-foundry

forge compile;

# [Expected Error Output]:
# [⠊] Compiling...
# [⠒] Unable to resolve imports:
#       "../src/Counter.sol" in "/path/to/create-erc20-contract-using-foundry/test/Counter.t.sol"
#  ...
```

如果出现上方显示的`Expected Error Output`，原因是引用了一个不存在的文件。为了解决这个问题，需要将其重命名为`BingBongToken.t.sol`，并替换一些占位符代码：

```bash
# FROM: ./create-erc20-contract-using-foundry

mv test/Counter.t.sol test/BingBongToken.t.sol;
```

**文件位置**：`./test/BingBongToken.t.sol`

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console2} from "forge-std/Test.sol";
import {BingBongToken} from "../src/BingBongToken.sol";

contract BingBongTokenTest is Test {

}
```

现在，运行`forge compile`时，应该显示以下结果：

```bash
# FROM: ./create-erc20-contract-using-foundry

forge compile;

# [Expected Output]:
# [⠢] Compiling...
# [⠰] Compiling 27 files with 0.8.21
# [⠃] Solc 0.8.21 finished in 6.25s
# Compiler run successful!
```

### 测试ERC20合约

使用重命名的`BingBongToken.t.sol`文件，添加以下测试代码，该代码覆盖广泛的ERC20合约测试。

请检查每项测试，以便更加了解如何应对并成功处理各种情况。

**文件位置**：`./test/BingBongToken.t.sol`

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Test, console2, stdError} from "forge-std/Test.sol";
import {BingBongToken} from "../src/BingBongToken.sol";

contract BingBongTokenTest is Test {
    // Variables
    BingBongToken public token;
    address supplyOwnerAddress = makeAddr("BerachainWalletUser"); // 0xE3284cB941608AA9E65F7EDdbb50c461D936622f
    address randomWalletAddress = makeAddr("GiveMeTokens"); // 0x187A660c372Fa04D09C1A71f2927911e62e98a89
    address anotherWalletAddress = makeAddr("AnotherAddress"); // 0x0F3B9cC98eef350B12D5b7a338D8B76c2F9a92CC
    error ERC20InvalidReceiver(address receiver);

    // Initial Read Tests
    // ========================================================
    /**
     * @dev Initial contract setup
     */
    function setUp() public {
        vm.prank(supplyOwnerAddress);
        token = new BingBongToken("BingBong Token", "BBT", 10000);
    }

    /**
     * @dev Test initiatted token name
     */
    function test_name() public {
        assertEq(token.name(), "BingBong Token");
    }

    /**
     * @dev Test initiatted token symbol
     */
    function test_symbol() public {
        assertEq(token.symbol(), "BBT");
    }

    /**
     * @dev Test default decimals
     */
    function test_decimals() public {
        assertEq(token.decimals(), 18);
    }

    /**
     * @dev Test initial total token supply
     */
    function test_totalSupply() public {
        assertEq(token.totalSupply(), 10000);
    }

    /**
     * @dev Test initial random account balance
     */
    function test_balanceOfAddress0() public {
        assertEq(token.balanceOf(address(0)), 0);
    }

    /**
     * @dev Test account balance of original deployer
     */
    function test_balanceOfAddressSupplyOwner() public {
        assertEq(token.balanceOf(supplyOwnerAddress), 10000);
    }

    /**
     * @dev Test Revert transfer to sender as 0x0
     */
    function test_transferRevertInvalidSender() public {
        vm.prank(address(0));
        vm.expectRevert(abi.encodeWithSignature("ERC20InvalidSender(address)", address(0)));
        token.transfer(randomWalletAddress, 100);
    }

    /**
     * @dev Test Revert transfer to receiver as 0x0
     */
    function test_transferRevertInvalidReceiver() public {
        vm.prank(supplyOwnerAddress);
        vm.expectRevert(abi.encodeWithSignature("ERC20InvalidReceiver(address)", address(0)));
        token.transfer(address(0), 100);
    }

    /**
     * @dev Test Revert transfer to sender with insufficient balance
     */
    function test_transferRevertInsufficientBalance() public {
        vm.prank(randomWalletAddress);
        // NOTE: Make sure to keep this string for `encodeWithSignature` free of spaces for the string (" ")
        vm.expectRevert(abi.encodeWithSignature("ERC20InsufficientBalance(address,uint256,uint256)", randomWalletAddress, 0, 100));
        token.transfer(supplyOwnerAddress, 100);
    }

    /**
     * @dev Test transfer to receiver from sender with sufficient balance
     */
    function test_transfer() public {
        vm.prank(supplyOwnerAddress);
        assertEq(token.transfer(randomWalletAddress, 100), true);
        assertEq(token.balanceOf(randomWalletAddress), 100);
        assertEq(token.balanceOf(supplyOwnerAddress), 10000 - 100);
    }

    /**
     * @dev Test allowance of random address for supplyOwner
     */
    function test_allowance() public {
        assertEq(token.allowance(supplyOwnerAddress, randomWalletAddress), 0);
    }

    /**
     * @dev Test Revert approve of owner as 0x0
     */
    function test_approveRevertInvalidApprover() public {
        vm.prank(address(0));
        vm.expectRevert(abi.encodeWithSignature("ERC20InvalidApprover(address)", address(0)));
        token.approve(randomWalletAddress, 100);
    }

    /**
     * @dev Test Revert approve of spender as 0x0
     */
    function test_approveRevertInvalidSpender() public {
        vm.prank(supplyOwnerAddress);
        vm.expectRevert(abi.encodeWithSignature("ERC20InvalidSpender(address)", address(0)));
        token.approve(address(0), 100);
    }

    /**
     * @dev Test approve of spender for 0 and 50
     */
    function test_approve() public {
        vm.prank(supplyOwnerAddress);
        assertEq(token.approve(randomWalletAddress, 0), true);
        assertEq(token.approve(randomWalletAddress, 50), true);
    }

    /**
     * @dev Test Revert transferFrom of spender with 0 approveed
     */
    function test_transferFromRevertInsufficientAllowanceFor0x0() public {
        vm.prank(supplyOwnerAddress);
        vm.expectRevert(abi.encodeWithSignature("ERC20InsufficientAllowance(address,uint256,uint256)", supplyOwnerAddress, 0, 100));
        token.transferFrom(randomWalletAddress, address(0), 100);
    }

    /**
     * @dev Test Revert transferFrom of spender transferring to 0x0
     */
    function test_transferFromRevertInvalidReceiver() public {
        // Setup
        vm.prank(supplyOwnerAddress);
        token.approve(randomWalletAddress, 30);

        // Test
        vm.prank(randomWalletAddress);
        vm.expectRevert(abi.encodeWithSignature("ERC20InvalidReceiver(address)", address(0)));
        token.transferFrom(supplyOwnerAddress, address(0), 30);
    }

    /**
     * @dev Test Revert transferFrom of spender transferring 50/30 approved
     */
    function test_transferFromRevertInsufficientAllowance() public {
        // Setup
        vm.prank(supplyOwnerAddress);
        token.approve(randomWalletAddress, 30);

        // Test
        vm.prank(randomWalletAddress);
        vm.expectRevert(abi.encodeWithSignature("ERC20InsufficientAllowance(address,uint256,uint256)", randomWalletAddress, 30, 50));
        token.transferFrom(supplyOwnerAddress, anotherWalletAddress, 50);
    }

    /**
     * @dev Test transferFrom of spender 10/30 approved
     */
    function test_transferFrom() public {
        // Setup
        vm.prank(supplyOwnerAddress);
        token.approve(randomWalletAddress, 30);

        // Test
        vm.prank(randomWalletAddress);
        assertEq(token.transferFrom(supplyOwnerAddress, anotherWalletAddress, 10), true);
        assertEq(token.balanceOf(anotherWalletAddress), 10);
        assertEq(token.balanceOf(supplyOwnerAddress), 10000 - 10);
        assertEq(token.allowance(supplyOwnerAddress, randomWalletAddress), 30 - 10);
    }
}
```

接下来，编译代码，运行测试，检查各项测试是否通过。

```bash
# FROM: ./create-erc20-contract-using-foundry

forge test -vvv; # v stands for verbose and multiple vvv allow for more details for tests

# [Expected Output]:
# [⠰] Compiling...
# No files changed, compilation skipped
#
# Running 18 tests for test/BingBongToken.t.sol:BingBongTokenTest
# [PASS] test_allowance() (gas: 12341)
# [PASS] test_approve() (gas: 42814)
# [PASS] test_approveRevertInvalidApprover() (gas: 11685)
# [PASS] test_approveRevertInvalidSpender() (gas: 11737)
# [PASS] test_balanceOfAddress0() (gas: 7810)
# [PASS] test_balanceOfAddressSupplyOwner() (gas: 9893)
# [PASS] test_decimals() (gas: 5481)
# [PASS] test_name() (gas: 9541)
# [PASS] test_symbol() (gas: 9650)
# [PASS] test_totalSupply() (gas: 7546)
# [PASS] test_transfer() (gas: 44880)
# [PASS] test_transferFrom() (gas: 75384)
# [PASS] test_transferFromRevertInsufficientAllowance() (gas: 42626)
# [PASS] test_transferFromRevertInsufficientAllowanceFor0x0() (gas: 16597)
# [PASS] test_transferFromRevertInvalidReceiver() (gas: 28334)
# [PASS] test_transferRevertInsufficientBalance() (gas: 16477)
# [PASS] test_transferRevertInvalidReceiver() (gas: 11796)
# [PASS] test_transferRevertInvalidSender() (gas: 11746)
# Test result: ok. 18 passed; 0 failed; 0 skipped; finished in 2.07ms
#
# Ran 1 test suites: 18 tests passed, 0 failed, 0 skipped (18 total tests)
```

### 为Berachain合约部署Foundry

现在，代码创建和测试都已完成，接下来创建部署`BingBongToken.sol`文件所需的脚本。为此，需要将`Course.s.sol`脚本文件重命名为`BingBongToken.s.sol`：

```bash
# FROM: ./create-erc20-contract-using-foundry

mv script/Counter.s.sol script/BingBongToken.s.sol;
```

然后，添加以下代码以替换现有代码，用于导入钱包私钥和部署合约。

**文件位置**：`./script/BingBongToken.s.sol`

```bash
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console2} from "forge-std/Script.sol";
import "../src/BingBongToken.sol";

contract BingBongTokenScript is Script {
    /**
     * @dev Relevant source part starts here and spans across multiple lines
     */
    function setUp() public {
    }

    /**
     * @dev Main deployment script
     */
    function run() public {
        // Setup
        uint256 deployerPrivateKey = vm.envUint("WALLET_PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        // Deploy
        BingBongToken bbt = new BingBongToken("BingBongToken", "BBT", 5678);

        // Verify + End
        console2.log(bbt.totalSupply());
        vm.stopBroadcast();
    }
}
```

为了验证合约是否能够正确执行，可以通过运行`anvil`在本地节点上测试。请备份并保存私钥。

#### 终端 1：

```bash
# FROM: ./create-erc20-contract-using-foundry

anvil;

# [Expected Output]:
#
#
#                              _   _
#                             (_) | |
#       __ _   _ __   __   __  _  | |
#      / _` | | '_ \  \ \ / / | | | |
#     | (_| | | | | |  \ V /  | | | |
#      \__,_| |_| |_|   \_/   |_| |_|
#
#     0.2.0 (f5b9c02 2023-10-28T00:16:04.060987000Z)
#     https://github.com/foundry-rs/foundry
#
# Available Accounts
# ==================
#
# (0) "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" (10000.000000000000000000 ETH)
# ...
#
# Private Keys
# ==================
#
# (0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
# ...
```

使用上方代码中提供的私钥`Private Key`，替换`.env` 文件中的`WALLET_PRIVATE_KEY`。

**文件位置**：`./.env`

```bash
WALLET_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
```

#### 终端 2：

在另一个终端窗口中，运行以下代码，将合约部署到本地节点RPC：

```bash
# FROM ./create-erc20-contract-using-foundry

forge script script/BingBongToken.s.sol --fork-url http://localhost:8545 --broadcast;

# [Expected Output]:
# Compiler run successful!
# Script ran successfully.
#
# == Logs ==
#   5678
# ...
# ✅  [Success]Hash: 0xc2b647051d11d8dbd88d131ff268ada417caa27e423747497b624cc3e9c75db8
# Contract Address: 0x5FbDB2315678afecb367f032d93F642f64180aa3
# Block: 1
# ...
```

显示以上结果，部署成功！最后，务必使用`ctrl + c`停止**终端 1**中的`anvil`服务。

### 部署ERC20合约

{% hint style="info" %}
部署之前，确保你的钱包里有足够的`$BERA`代币`，`以支付部署合约所需的费用，并确认已替换`.env`文件中的`WALLET_PRIVATE_KEY`。
{% endhint %}

使用本地节点配置，部署到Berachain测试网的流程均相似，但需要指定不同的RPC URL端点：

```bash
# FROM ./create-erc20-contract-using-foundry

forge script script/BingBongToken.s.sol --rpc-url https://bartio.rpc.berachain.com/ --broadcast;

# [Expected Output]:
# Compiler run successful!
# Script ran successfully.
#
# == Logs ==
#   5678
# ...
# ✅  [Success]Hash: 0x69aeb8ee5084c44cce00cae2fda3563bd10efb9c8c663ec7b6a6929d6d48a50e
# Contract Address: 0x01870EC5C7656723b31a884259537B183FE15Fa7
# Block: 68764
# ...
```

### 验证ERC20合约

{% hint style="info" %}
目前，在`v0.2.0`版本的forge中，合约验证存在一些问题，可能导致合约验证无法进行，尝试运行以下代码，应该有助于验证合约：
{% endhint %}

```bash
# FROM ./create-erc20-contract-using-foundry

forge verify-contract 0xYOUR_DEPLOYED_CONTRACT_ADDRESS BingBongToken \
    --etherscan-api-key=xxxxx \
    --watch \
    --constructor-args $(cast abi-encode "constructor(string,string,uint256)" "BingBongToken" "BBT" 5678) \
    --retries=2 \
    --verifier-url=https://api.routescan.io/v2/network/testnet/evm/80084/etherscan/api/;
```

### 完整代码库

本节完整代码库，可在[Github - Berachain Guides](https://github.com/berachain/guides/) - [foundry-erc20](https://github.com/berachain/guides/tree/main/apps/foundry-erc20)中查看。

{% embed url="<https://github.com/berachain/guides/tree/main/apps/foundry-erc20>" %}


# 使用 NextJS & WalletConnect 部署合约

{% hint style="info" %}
请在GitHub参阅完整的[walletconnect-nextjs](https://github.com/berachain/guides/tree/main/apps/walletconnect-nextjs)代码库。
{% endhint %}

本节将展示如何设置NextJS Web应用程序，配置Berachain网络详细信息，设置基本钱包连接，以及通过前端与[WalletConnect](https://docs.walletconnect.com/)部署合约。

### 先决条件

开始之前，请确保你的本地设备上满足以下条件：

* 持有`$BERA`代币的钱包（合约部署费用，参阅[Berachain测试网水龙头](/berachain-docs/learn/native-dapps/testnet-faucet)文档）
* NVM或Node `v20.11.0`
* `pnpm`, `yarn` 或 `npm`

### 创建NextJS代码设置

首先，为NextJS创建一个新的文件夹：

```bash
npx create-next-app@latest;

# [Expected Prompts & Responses]:
# ✔ What is your project named? … walletconnect-nextjs
# ✔ Would you like to use TypeScript? … No / _Yes_
# ✔ Would you like to use ESLint? … No / _Yes_
# ✔ Would you like to use Tailwind CSS? … No / _Yes_
# ✔ Would you like to use `src/` directory? … _No_ / Yes
# ✔ Would you like to use App Router? (recommended) … No / _Yes_
# ✔ Would you like to customize the default import alias (@/*)? … _No_ / Yes
# Creating a new Next.js app in /path/to/walletconnect-nextjs.
#
# Using npm.
#
# Initializing project with template: app-tw
#
# ...
#
# Success! Created walletconnect-nextjs at /path/to/walletconnect-nextjs

cd walletconnect-nextjs;
```

### 添加依赖项

```bash
# FROM: ./walletconnect-nextjs

pnpm add @web3modal/wagmi wagmi viem @tanstack/react-query;
```

### 获取WalletConnect ID

访问[WalletConnect Cloud](https://cloud.reown.com/sign-in)，注册新帐户 (如果没有账户) 并登陆到WalletConnect Cloud，接下来创建新项目以生成项目 ID。

首先，创建一个新项目：

<figure><img src="/files/OvF7lQJX0PHVyLziw7Fu" alt=""><figcaption></figcaption></figure>

然后，编辑项目详细信息：

<figure><img src="/files/yoDi1MM52Syk3Qp6O3Om" alt=""><figcaption></figcaption></figure>

最后，获取项目 ID：

<figure><img src="/files/KqZ2GtTNjuSnQ8lqPMVp" alt=""><figcaption></figcaption></figure>

### 配置WalletConnect

成功获得项目 ID后，在存储库中创建一个新的`.env`变量：

```bash
# FROM: ./walletconnect-nextjs

touch .env;
```

使用以下详细信息修改文件：

**文件位置**：**./.env**

```bash
# Get projectId at https://cloud.walletconnect.com
NEXT_PUBLIC_PROJECT_ID=YOUR-WALLETCONNECT-PROJECT-ID
```

为`web3modal`创建一个新的配置文件夹和文件：

```bash
# FROM: ./walletconnect-nextjs

mkdir config;
touch config/index.tsx;
```

在新的配置文件夹中添加以下代码：

**文件位置**：`./config/index.tsx`

```tsx
// Imports
// ========================================================
import { defaultWagmiConfig } from "@web3modal/wagmi/react/config";
import { cookieStorage, createStorage } from "wagmi";
import { berachainTestnetbArtio } from "wagmi/chains";

// Constants
// ========================================================
// Get projectId at https://cloud.walletconnect.com
export const projectId = process.env.NEXT_PUBLIC_PROJECT_ID;

const metadata = {
  name: "Berachain Web3Modal",
  description: "Berachain Web3Modal Example",
  url: "https://web3modal.com", // origin must match your domain & subdomain
  icons: ["https://avatars.githubusercontent.com/u/96059542"],
};

if (!projectId) throw new Error("Project ID is not defined");

// Config
// ========================================================
export const config = defaultWagmiConfig({
  chains: [berachainTestnetbArtio], // required
  projectId, // required
  metadata, // required
  ssr: true,
  storage: createStorage({
    storage: cookieStorage,
  }),
  enableWalletConnect: true, // Optional - true by default
  enableInjected: true, // Optional - true by default
  enableEIP6963: true, // Optional - true by default
  enableCoinbase: true, // Optional - true by default
  //   ...wagmiOptions // Optional - Override createConfig parameters
});
```

接下来，创建一个新的`context`文件夹，该文件夹通过来自[TanStack](https://tanstack.com/)和[Wagmi](https://wagmi.sh/)的必要Context Providers程序封装待部署项目。

```bash
# FROM: ./walletconnect-nextjs

mkdir context;
touch context/index.tsx;
```

**文件位置**：`./context/index.tsx`

{% hint style="info" %}
该文件顶部会出现一个`use client`，因为它需要在客户端渲染，并且需要与服务器端区分。
{% endhint %}

```tsx
"use client";

// Imports
// ========================================================
import React, { ReactNode } from "react";
import { config, projectId } from "@/config";
import { createWeb3Modal } from "@web3modal/wagmi/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { State, WagmiProvider } from "wagmi";

// Config
// ========================================================
// Setup queryClient
const queryClient = new QueryClient({
  // Prevent refetch on window refos
  defaultOptions: {
    queries: {
      refetchOnWindowFocus: false,
    },
  },
});

if (!projectId) throw new Error("Project ID is not defined");

// Create modal
createWeb3Modal({
  wagmiConfig: config,
  projectId,
  enableAnalytics: true, // Optional - defaults to your Cloud configuration
});

// Exports
// ========================================================
export default function Web3Modal({
  children,
  initialState,
}: {
  children: ReactNode;
  initialState?: State;
}) {
  return (
    <WagmiProvider config={config} initialState={initialState}>
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    </WagmiProvider>
  );
}
```

接下来，修改现有`layout.tsx`文件，以适配这些额外的Context Providers程序。

**文件位置**：`./app/layout.tsx`

```tsx
// Imports
// ========================================================
import type { Metadata } from "next";
import { headers } from "next/headers";
import "./globals.css";
import { cookieToInitialState } from "wagmi";
import { config } from "@/config";
import ContextProvider from "@/context";

// Metadata
// ========================================================
export const metadata: Metadata = {
  title: "Web3Modal Berachain",
  description: "Web3Modal Example With Berachain",
};

// Main Layout
// ========================================================
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const initialState = cookieToInitialState(config, headers().get("cookie"));
  return (
    <html lang="en">
      <body>
        <ContextProvider initialState={initialState}>
          {children}
        </ContextProvider>
      </body>
    </html>
  );
}
```

另外，还可以添加一些CSS样式，使应用程序更美观。

**文件位置**：`./app/globals.css`

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  body {
    @apply bg-zinc-900 text-zinc-300;
  }

  h1 {
    @apply font-bold text-2xl mb-6 text-white;
  }

  h2 {
    @apply font-bold text-xl mb-6 text-white;
  }

  p {
    @apply mb-6;
  }

  .dot {
    @apply inline-flex w-3 h-3 rounded-full bg-black mr-2;
  }

  .dot.green {
    @apply bg-green-500;
  }

  .dot.red {
    @apply bg-red-500;
  }

  pre {
    @apply bg-zinc-800 p-8 rounded overflow-scroll max-h-72 mb-8;
  }

  code {
    @apply overflow-scroll;
  }

  form {
    @apply mb-8;
  }

  label {
    @apply flex text-sm text-zinc-400 mb-4;
  }

  textarea,
  input {
    @apply flex w-full rounded text-zinc-700 p-6 mb-8;
  }

  button,
  button[type="submit"] {
    @apply bg-zinc-700 text-white h-12 px-12 rounded-full hover:bg-zinc-600 transition-colors ease-in-out;
  }

  button:disabled,
  input:disabled,
  textarea:disabled {
    opacity: 0.1;
  }

  a:not(.button) {
    @apply text-red-400 underline;
  }

  a.button {
    @apply inline-flex items-center bg-blue-500 text-white h-12 px-12 rounded-full hover:bg-zinc-600 transition-colors ease-in-out;
  }
}
```

### 添加Web3Modal按钮组件

现在，已成功配置Web应用程序，接下来，需要添加Web3Modal按钮组件，以允许钱包连接。

**文件位置**：`./app/page.tsx`

```tsx
// Imports
// ========================================================
// TBD

// Main Page
// ========================================================
export default function Home() {
  // Render
  return (
    <main className="p-8">
      <h1>🐻⛓️ Berachain WalletConnect Web3Modal Example</h1>
      <p>An example of Berachain being used with WalletConnect.</p>
      <div className="mb-8">
        <w3m-button />
      </div>
    </main>
  );
}
```

启动应用程序，以确认是否可以与MetaMask等网页扩展钱包连接。

```bash
# FROM: ./walletconnect-nextjs

pnpm dev;

# [Expected Output]:
# > walletconnect-nextjs@0.1.0 dev /path/to/walletconnect-nextjs
# > next dev
#
#    ▲ Next.js 14.1.0
#    - Local:        http://localhost:3000
#    - Environments: .env
#
#  ✓ Ready in 2.9s
```

演示Web3Modal按钮组件的工作原理。

<figure><img src="/files/VOoq74ggym8ukbjllRVZ" alt=""><figcaption></figcaption></figure>

通过Web3Modal连接钱包。

<figure><img src="/files/qNUqRzQtJwHOviX66LTo" alt=""><figcaption></figcaption></figure>

显示如下，钱包已成功连接。

<figure><img src="/files/oOaR3uylH2xOqKobDgEE" alt=""><figcaption></figcaption></figure>

### 帐户连接组件

设置好Web3Modal后，需要创建一个`Account`组件，通过`wagmi`现有的hooks测试账户是否成功连接。

```bash
# FROM: ./walletconnect-nextjs

mkdir components;
mkdir components/Account;
touch components/Account/index.tsx;
```

创建一个`Account`组件，检查账户是否已成功连接和当前连接状态。

**文件位置**：`./components/Account/index.tsx`

```tsx
"use client";

// Imports
// ========================================================
import { useAccount, useContractRead } from "wagmi";

// Main Page
// ========================================================
export default function Account() {
  // Hooks
  const { isConnected } = useAccount();

  // Render
  return (
    <section className="pb-6 mb-6 border-zinc-700 border-b">
      <>
        <h2>Account Connection</h2>
        {isConnected ? (
          <div>
            <span className="dot green"></span>
            Connected
          </div>
        ) : (
          <div>
            <span className="dot red"></span>
            Account NOT Connected
          </div>
        )}
      </>
    </section>
  );
}
```

然后，将其添加到主`page.tsx`文件中。

**文件位置**：`./app/page.tsx`

```tsx
// Imports
// ========================================================
import Account from "@/components/Account"; 

// Main Page
// ========================================================
export default function Home() {
  // Render
  return (
    <main className="p-8">
      <h1>🐻⛓️ Berachain WalletConnect Web3Modal Example</h1>
      <p>An example of Berachain being used with WalletConnect.</p>
      <div className="mb-8">
        <w3m-button />
      </div>
      <Account />
    </main>
  );
}
```

现在，查看应用程序，页面下方会显示用户是否已成功连接 (`Connected` or `Not`)。

<figure><img src="/files/KOosWNqh52MzcJVNmL4X" alt=""><figcaption></figcaption></figure>

### 签名消息组件

接下来，演示的另一个功能是钱包签名基本功能。首先，创建一个名为`SignMessage`的文件夹，以添加签名和消息验证功能。

```bash
# FROM: ./walletconnect-nextjs

mkdir components/SignMessage;
touch components/SignMessage/index.tsx;
```

**文件位置**：`./components/SignMessage/index.tsx`

```tsx
"use client";

// Imports
// ========================================================
import { useAccount, useSignMessage, useVerifyMessage } from "wagmi";
import { useState } from "react";
import { berachainTestnet } from "wagmi/chains";

// Main Page
// ========================================================
export default function SignMessage() {
  // Hooks
  const { isConnected, address } = useAccount();
  const [message, setMessage] = useState("");
  const [signature, setSignature] = useState<`0x${string}`>("0x");
  const [result, setResult] = useState("");
  const { signMessageAsync } = useSignMessage();
  const verification = useVerifyMessage({
    chainId: berachainTestnet.id,
    address,
    message,
    signature,
  });

  // Functions
  /**
   * @dev Handles signing messages from whatever is placed in textarea
   * @param event
   */
  const onSubmitSignMessage = async (
    event: React.FormEvent<HTMLFormElement>
  ) => {
    event.preventDefault();
    console.group("onSubmitSignMessage");

    try {
      const signature = await signMessageAsync({
        message,
      });
      setSignature(signature);
      setResult(signature);
      verification.refetch();
    } catch (error: any) {
      console.error(error?.reason);
      console.error(error);
      setResult(error?.reason ?? error?.message);
    }

    console.groupEnd();
  };

  // Render
  return (
    <section className="pb-6 mb-6 border-zinc-700 border-b">
      <>
        <h2>Sign Message</h2>

        {isConnected ? (
          <div>
            <form onSubmit={onSubmitSignMessage}>
              <div>
                <label>Message</label>
                <textarea
                  value={message}
                  onChange={(e) => setMessage(e.target.value)}
                  placeholder="Ex: My Message"
                />
              </div>
              <div>
                <button disabled={!message} type="submit">
                  Sign
                </button>
              </div>
            </form>

            {result ? (
              <div>
                <label>Signature Result</label>
                <pre>
                  <code>{result}</code>
                </pre>

                <label>Verification Result</label>
                <pre>
                  <code>
                    {verification.status === "pending"
                      ? `Status: ${verification.status}\n\nVerifying...`
                      : ""}
                    {verification.status === "error"
                      ? `Status: ${verification.status}\n\n${verification?.failureReason?.message}`
                      : ""}
                    {verification.status === "success"
                      ? `Status: ${verification.status}\n\nVerified signature and message`
                      : ""}
                  </code>
                </pre>
              </div>
            ) : null}
          </div>
        ) : (
          <div>
            <pre>
              <code>Not Connected</code>
            </pre>
          </div>
        )}
      </>
    </section>
  );
}
```

然后，将其添加到主`page.tsx`文件中。

**文件位置**：`./app/page.tsx`

```tsx
// Imports
// ========================================================
import Account from "@/components/Account";
import SignMessage from "@/components/SignMessage"; 

// Main Page
// ========================================================
export default function Home() {
  // Render
  return (
    <main className="p-8">
      <h1>🐻⛓️ Berachain WalletConnect Web3Modal Example</h1>
      <p>An example of Berachain being used with WalletConnect.</p>
      <div className="mb-8">
        <w3m-button />
      </div>
      <Account />
      <SignMessage />
    </main>
  );
}
```

现在，当钱包连接到应用程序时，钱包会出现签名消息提示。

<figure><img src="/files/EvCcldV0LFmAcOlsUhQm" alt=""><figcaption></figcaption></figure>

完成签名后，查看应用程序，页面下方会显示用户签名和验证信息。

<figure><img src="/files/QpZoSINesWVyS44eufmv" alt=""><figcaption></figcaption></figure>

### 部署合约组件

最后一步，演示如何直接从前端部署现有字节码，以提示用户钱包发起交易。

```bash
# FROM: ./walletconnect-nextjs

mkdir components/Deploy;
touch components/Deploy/index.tsx;
```

{% hint style="info" %}
如果你对**字节码**感到好奇——它是来自[使用Hardhat部署HelloWorld合约](/berachain-docs/developers/developer-guides/create-helloworld-contract-using-hardhat)的编译字节码。
{% endhint %}

**文件位置**：`./components/Deploy.tsx`

```tsx
"use client";

// Imports
// ========================================================
import { useAccount, useWaitForTransactionReceipt } from "wagmi";
import { useState } from "react";
import { encodeAbiParameters } from "viem";
import { berachainTestnet } from "wagmi/chains";

// Constants
// ========================================================
/**
 * @dev All inputs and outputs of Contract
 */
const CONTRACT_ABI = [
  {
    inputs: [
      {
        internalType: "string",
        name: "_greeting",
        type: "string",
      },
    ],
    stateMutability: "nonpayable",
    type: "constructor",
  },
  {
    anonymous: false,
    inputs: [
      {
        indexed: false,
        internalType: "address",
        name: "sender",
        type: "address",
      },
      {
        indexed: false,
        internalType: "string",
        name: "message",
        type: "string",
      },
    ],
    name: "NewGreeting",
    type: "event",
  },
  {
    inputs: [],
    name: "getGreeting",
    outputs: [
      {
        internalType: "string",
        name: "",
        type: "string",
      },
    ],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      {
        internalType: "string",
        name: "_greeting",
        type: "string",
      },
    ],
    name: "setGreeting",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
];

/**
 * @dev full contract bytecode for deployment
 */
const CONTRACT_BYTECODE =
  "0x60806040523480156200001157600080fd5b5060405162000da238038062000da283398181016040528101906200003791906200021e565b8060009081620000489190620004ba565b507fcbc299eeb7a1a982d3674880645107c4fe48c3227163794e48540a752272235433826040516200007c92919062000638565b60405180910390a1506200066c565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620000f482620000a9565b810181811067ffffffffffffffff82111715620001165762000115620000ba565b5b80604052505050565b60006200012b6200008b565b9050620001398282620000e9565b919050565b600067ffffffffffffffff8211156200015c576200015b620000ba565b5b6200016782620000a9565b9050602081019050919050565b60005b838110156200019457808201518184015260208101905062000177565b60008484015250505050565b6000620001b7620001b1846200013e565b6200011f565b905082815260208101848484011115620001d657620001d5620000a4565b5b620001e384828562000174565b509392505050565b600082601f8301126200020357620002026200009f565b5b815162000215848260208601620001a0565b91505092915050565b60006020828403121562000237576200023662000095565b5b600082015167ffffffffffffffff8111156200025857620002576200009a565b5b6200026684828501620001eb565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620002c257607f821691505b602082108103620002d857620002d76200027a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003427fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000303565b6200034e868362000303565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006200039b620003956200038f8462000366565b62000370565b62000366565b9050919050565b6000819050919050565b620003b7836200037a565b620003cf620003c682620003a2565b84845462000310565b825550505050565b600090565b620003e6620003d7565b620003f3818484620003ac565b505050565b5b818110156200041b576200040f600082620003dc565b600181019050620003f9565b5050565b601f8211156200046a576200043481620002de565b6200043f84620002f3565b810160208510156200044f578190505b620004676200045e85620002f3565b830182620003f8565b50505b505050565b600082821c905092915050565b60006200048f600019846008026200046f565b1980831691505092915050565b6000620004aa83836200047c565b9150826002028217905092915050565b620004c5826200026f565b67ffffffffffffffff811115620004e157620004e0620000ba565b5b620004ed8254620002a9565b620004fa8282856200041f565b600060209050601f8311600181146200053257600084156200051d578287015190505b6200052985826200049c565b86555062000599565b601f1984166200054286620002de565b60005b828110156200056c5784890151825560018201915060208501945060208101905062000545565b868310156200058c578489015162000588601f8916826200047c565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005ce82620005a1565b9050919050565b620005e081620005c1565b82525050565b600082825260208201905092915050565b600062000604826200026f565b620006108185620005e6565b93506200062281856020860162000174565b6200062d81620000a9565b840191505092915050565b60006040820190506200064f6000830185620005d5565b8181036020830152620006638184620005f7565b90509392505050565b610726806200067c6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063fe50cc7214610057575b600080fd5b610055600480360381019061005091906102ad565b610075565b005b61005f6100c1565b60405161006c9190610375565b60405180910390f35b806000908161008491906105ad565b507fcbc299eeb7a1a982d3674880645107c4fe48c3227163794e48540a752272235433826040516100b69291906106c0565b60405180910390a150565b6060600080546100d0906103c6565b80601f01602080910402602001604051908101604052809291908181526020018280546100fc906103c6565b80156101495780601f1061011e57610100808354040283529160200191610149565b820191906000526020600020905b81548152906001019060200180831161012c57829003601f168201915b5050505050905090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101ba82610171565b810181811067ffffffffffffffff821117156101d9576101d8610182565b5b80604052505050565b60006101ec610153565b90506101f882826101b1565b919050565b600067ffffffffffffffff82111561021857610217610182565b5b61022182610171565b9050602081019050919050565b82818337600083830152505050565b600061025061024b846101fd565b6101e2565b90508281526020810184848401111561026c5761026b61016c565b5b61027784828561022e565b509392505050565b600082601f83011261029457610293610167565b5b81356102a484826020860161023d565b91505092915050565b6000602082840312156102c3576102c261015d565b5b600082013567ffffffffffffffff8111156102e1576102e0610162565b5b6102ed8482850161027f565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610330578082015181840152602081019050610315565b60008484015250505050565b6000610347826102f6565b6103518185610301565b9350610361818560208601610312565b61036a81610171565b840191505092915050565b6000602082019050818103600083015261038f818461033c565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806103de57607f821691505b6020821081036103f1576103f0610397565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026104597fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261041c565b610463868361041c565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006104aa6104a56104a08461047b565b610485565b61047b565b9050919050565b6000819050919050565b6104c48361048f565b6104d86104d0826104b1565b848454610429565b825550505050565b600090565b6104ed6104e0565b6104f88184846104bb565b505050565b5b8181101561051c576105116000826104e5565b6001810190506104fe565b5050565b601f82111561056157610532816103f7565b61053b8461040c565b8101602085101561054a578190505b61055e6105568561040c565b8301826104fd565b50505b505050565b600082821c905092915050565b600061058460001984600802610566565b1980831691505092915050565b600061059d8383610573565b9150826002028217905092915050565b6105b6826102f6565b67ffffffffffffffff8111156105cf576105ce610182565b5b6105d982546103c6565b6105e4828285610520565b600060209050601f8311600181146106175760008415610605578287015190505b61060f8582610591565b865550610677565b601f198416610625866103f7565b60005b8281101561064d57848901518255600182019150602085019450602081019050610628565b8683101561066a5784890151610666601f891682610573565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006106aa8261067f565b9050919050565b6106ba8161069f565b82525050565b60006040820190506106d560008301856106b1565b81810360208301526106e7818461033c565b9050939250505056fea2646970667358221220b73a35f7115c3a3bd7064d103c9df452f2202170fb44b021de500dec483bb6fa64736f6c63430008130033";

/**
 * @dev Berachain testnet block explorer
 */
const BLOCK_EXPLORER = "https://brtio.beratrail.io/";

// Main Page
// ========================================================
export default function Deploy() {
  // Hooks
  const { address, isConnected, connector } = useAccount();
  const [transactionHash, setTransactionHash] = useState("");
  const [greeting, setGreeting] = useState("");
  const [isLoading, setIsloading] = useState(false);
  const [error, setError] = useState("");

  const receipt = useWaitForTransactionReceipt({
    chainId: berachainTestnet.id,
    hash: transactionHash ? (`${transactionHash}` as `0x${string}`) : undefined,
  });

  // Functions
  /**
   * @dev function that handles sending a transaction to the blockchain
   */
  const deployContract = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setTransactionHash("");
    setError("");

    console.group("deployContract");
    setIsloading(true);
    try {
      // Why not use? usePrepareTransactionRequest or useSendTransaction
      // Not enough documentation from wagmi on how to do a simple `eth_sendTransaction` with bytecode and not provide `to` param
      const provider = (await connector?.getProvider()) as any;
      console.log({ provider });
      console.log({ request: provider?.request });
      console.log({ greeting });

      // Based on constructor - constructor(string memory _greeting) {
      const encodedData = encodeAbiParameters(
        [{ name: "_greeting", type: "string" }],
        [`${greeting}`]
      );

      // Need slide(2) to remove 0x from encodedData at the beginning
      const fullByteCode = `${CONTRACT_BYTECODE}${encodedData.slice(
        2
      )}` as `0x${string}`;

      // Process trasaction
      const tx = await provider.request({
        method: "eth_sendTransaction",
        params: [
          {
            from: address,
            data: fullByteCode,
          },
        ],
      });

      // Get the transaction hash
      setTransactionHash(tx);

      // Refetch wait for receipt
      receipt.refetch();
    } catch (error: any) {
      console.error(error?.message);
      console.error(error?.reason);
      console.error(error);
      setError(error?.message);
    }
    setIsloading(false);
    console.groupEnd();
  };

  // Render
  return (
    <section className="pb-6 mb-6 border-zinc-700 border-b">
      <>
        <h2>Deploy Contract</h2>
        {isConnected ? (
          <div>
            <form onSubmit={deployContract}>
              <div>
                <label>HelloWorld.sol</label>
                <pre>
                  <code>{JSON.stringify(CONTRACT_ABI, null, "   ")}</code>
                </pre>
              </div>
              <div>
                <label htmlFor="_greeting">_greeting</label>
                <input
                  disabled={isLoading}
                  placeholder="Ex: Hello There!"
                  type="text"
                  name="_greeting"
                  id="_greetine"
                  value={greeting}
                  onChange={(e) => setGreeting(e.target.value)}
                />
              </div>
              <div>
                <label>ByteCode</label>
                <pre>
                  <code>{CONTRACT_BYTECODE}</code>
                </pre>
              </div>
              <div>
                <button
                  disabled={isLoading || greeting.length === 0}
                  type="submit"
                >
                  Deploy
                </button>
              </div>
            </form>

            <div>
              <label>Transaction Hash Result</label>
              <pre>
                <code>
                  {transactionHash}
                  {error}
                </code>
              </pre>
              {transactionHash ? (
                <p>
                  <a
                    className="button"
                    href={`${BLOCK_EXPLORER}/tx/${transactionHash}`}
                    target="_blank"
                  >
                    Beratrail Tx Link
                  </a>
                </p>
              ) : null}
            </div>

            <div>
              <label>Transaction Receipt</label>
              <pre>
                <code>
                  {receipt.status === "pending"
                    ? `Status: ${receipt.status}\n\nWaiting...`
                    : ""}
                  {receipt.status === "error"
                    ? `Status: ${receipt.status}\n\n${receipt?.failureReason?.message}`
                    : ""}
                  {receipt.status === "success"
                    ? `Status: ${receipt.status}\n\n${receipt?.data?.contractAddress}`
                    : ""}
                </code>
              </pre>

              {receipt?.data?.contractAddress ? (
                <p>
                  <a
                    className="button"
                    href={`${BLOCK_EXPLORER}/address/${receipt?.data?.contractAddress}`}
                    target="_blank"
                  >
                    Beratrail Contract Address Link
                  </a>
                </p>
              ) : null}
            </div>
          </div>
        ) : (
          <div>
            <pre>
              <code>Not Connected</code>
            </pre>
          </div>
        )}
      </>
    </section>
  );
}
```

然后，将其添加到主`page.tsx`文件中。

**文件位置**：`./app/page.tsx`

```tsx
// Imports
// ========================================================
import Account from "@/components/Account";
import SignMessage from "@/components/SignMessage";
import Deploy from "@/components/Deploy"; 

// Main Page
// ========================================================
export default function Home() {
  // Render
  return (
    <main className="p-8">
      <h1>🐻⛓️ Berachain WalletConnect Web3Modal Example</h1>
      <p>An example of Berachain being used with WalletConnect.</p>
      <div className="mb-8">
        <w3m-button />
      </div>
      <Account />
      <SignMessage />
      <Deploy />
    </main>
  );
}
```

现在，可以通过新部署的组件功能，设置初始问候语。

<figure><img src="/files/k2JKe0XVhhbyrNlHg48P" alt=""><figcaption></figcaption></figure>

确认一笔交易

<figure><img src="/files/QNcRG3qcihZYz8YuSKLD" alt=""><figcaption></figcaption></figure>

查询交易信息，点击**Berarail合约地址链接 (Beratrail Contract Address Link**)按钮。

{% hint style="info" %}
可能会出现延迟，需要一点时间才能显示在前端。
{% endhint %}

<figure><img src="/files/7VRePiqYLCroNujuKM9Z" alt=""><figcaption></figcaption></figure>

在Beratrail测试网区块浏览器中查看交易结果。

<figure><img src="/files/VU6IKdlbSdETNTpQichi" alt=""><figcaption></figcaption></figure>

现在，已成功将WalletConnect Web3Modal与Berachain集成。

### 完整代码库

本节完整代码库，可在[Github - Berachain Guides](https://github.com/berachain/guides/) - [walletconnect-nextjs](https://github.com/berachain/guides/tree/main/apps/walletconnect-nextjs)中查看。

{% embed url="<https://github.com/berachain/guides/tree/main/apps/walletconnect-nextjs>" %}


# 开发者外部资源

这些是Berachain社区开发者指南列表。

### 钱包连接 <a href="#wallet-connections" id="wallet-connections"></a>

<table><thead><tr><th width="493">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>NextJS WalletConnect WAGMI + Viem前端合约部署</td><td><a href="https://github.com/berachain/guides/tree/main/apps/walletconnect-nextjs">GitHub</a></td></tr><tr><td>ThirdWeb ConnectWallet NextJS</td><td><a href="https://github.com/berachain/guides/tree/main/apps/thirdweb-connectwallet-nextjs">GitHub</a></td></tr><tr><td>Particle Auth Core Vite</td><td><a href="https://github.com/berachain/guides/tree/main/apps/particle-auth-core-vite">GitHub</a></td></tr><tr><td>RainbowKit Vite</td><td><a href="https://github.com/berachain/guides/tree/main/apps/rainbowkit-vite">GitHub</a></td></tr><tr><td>WalletConnect Expo</td><td><a href="https://github.com/berachain/guides/tree/main/apps/walletconnect-expo">GitHub</a></td></tr><tr><td>RPC供应商指南</td><td><a href="https://blog.berachain.com/blog/your-berachain-rpc-guide">Guide</a></td></tr></tbody></table>

### 桥接[​](https://docs.berachain.com/developers/guides/community-guides#bridging) <a href="#bridging" id="bridging"></a>

<table><thead><tr><th width="495">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>使用 LayerZero V2 将 ERC20 代币桥接至 Berachain</td><td><a href="https://github.com/berachain/guides/tree/main/apps/layerzero-oft">GitHub</a></td></tr></tbody></table>

### 智能合约部署与验证 <a href="#smart-contract-deployment-verification" id="smart-contract-deployment-verification"></a>

<table><thead><tr><th width="497">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>使用 Ethers6 和 solc 部署 HelloWorld 合约</td><td><a href="https://github.com/berachain/guides/tree/main/apps/ethers6-solc-helloworld">GitHub</a></td></tr><tr><td>使用 Viem 和 solc 部署 HelloWorld 合约</td><td><a href="https://github.com/berachain/guides/tree/main/apps/viem-solc-helloworld">GitHub</a></td></tr><tr><td>使用 Hardhat 和 Viem 部署 HelloWorld 合约</td><td><a href="https://github.com/berachain/guides/tree/main/apps/hardhat-viem-helloworld">GitHub</a></td></tr><tr><td>Hardhat Ethers6 合约验证</td><td><a href="https://github.com/berachain/guides/tree/main/apps/hardhat-contract-verification">GitHub</a></td></tr><tr><td>Hardhat Ethers6 ERC1155</td><td><a href="https://github.com/berachain/guides/tree/main/apps/hardhat-ethers6-erc1155">GitHub</a></td></tr><tr><td>使用 Foundry 部署 ERC20 合约</td><td><a href="https://github.com/berachain/guides/tree/main/apps/foundry-erc20">GitHub</a></td></tr><tr><td>部署可升级合约</td><td><a href="https://github.com/berachain/guides/tree/main/apps/openzeppelin-upgrades">GitHub</a></td></tr></tbody></table>

### 交易机器人[​](https://docs.berachain.com/developers/guides/community-guides#trading-bots) <a href="#trading-bots" id="trading-bots"></a>

<table><thead><tr><th width="496">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>Berps 交易机器人</td><td><a href="https://github.com/berachain/guides/tree/main/apps/berps-bot">GitHub</a></td></tr></tbody></table>

### 索引和查询[​](https://docs.berachain.com/developers/guides/community-guides#indexing-and-querying) <a href="#indexing-and-querying" id="indexing-and-querying"></a>

<table><thead><tr><th width="498">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>使用 Goldsky 索引和查询 Berachain 数据</td><td><a href="https://github.com/berachain/guides/tree/main/apps/goldsky-subgraph">GitHub</a></td></tr><tr><td>Envio ERC20 索引器</td><td><a href="https://github.com/berachain/guides/tree/main/apps/envio-indexer-erc20">GitHub</a></td></tr></tbody></table>

### 可验证的随机性 <a href="#verifiable-randomness" id="verifiable-randomness"></a>

<table><thead><tr><th width="500">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>Gelato VRF</td><td><a href="https://github.com/berachain/guides/tree/main/apps/gelato-vrf">GitHub</a></td></tr><tr><td>Provably Fair NFTs with Pyth Entropy</td><td><a href="https://github.com/berachain/guides/tree/main/apps/pyth-entropy">GitHub</a></td></tr></tbody></table>

### 预言机[​](https://docs.berachain.com/developers/guides/community-guides#oracles) <a href="#oracles" id="oracles"></a>

<table><thead><tr><th width="501">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>Pyth 预言机<a href="https://docs.berachain.com/developers/guides/community-guides#oracles">​</a></td><td><a href="https://github.com/berachain/guides/tree/main/apps/pyth-oracle">GitHub</a></td></tr></tbody></table>

### 治理[​](https://docs.berachain.com/developers/guides/community-guides#governance) <a href="#governance" id="governance"></a>

<table><thead><tr><th width="502">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>Berachain 奖励金库治理提案</td><td><a href="https://github.com/berachain/guides/tree/main/apps/berachain-governance-proposal">GitHub</a></td></tr></tbody></table>

### 存储[​](https://docs.berachain.com/developers/guides/community-guides#storage) <a href="#storage" id="storage"></a>

<table><thead><tr><th width="503">项目用例</th><th>代码库</th></tr></thead><tbody><tr><td>使用 $BERA 代币的 Irys NodeJS 上传脚本</td><td><a href="https://github.com/berachain/guides/tree/main/apps/irys-bera-nodejs">GitHub</a></td></tr></tbody></table>

### 中继器/无 Gas 交易 <a href="#relayers-gasless-transactions" id="relayers-gasless-transactions"></a>

<table><thead><tr><th width="504">项目用例</th><th>资源</th></tr></thead><tbody><tr><td>使用 Gelato Relay</td><td><a href="https://docs.google.com/document/d/1dsSGGYZ4IIE8EAhrMH8SOQFmIygcaibRYHiar2Vj2Kw">Guide</a></td></tr></tbody></table>

### 自动化[​](https://docs.berachain.com/developers/guides/community-guides#automation) <a href="#automation" id="automation"></a>

<table><thead><tr><th width="509">Project Name</th><th>Source</th></tr></thead><tbody><tr><td>使用 Gelato Web3 Functions</td><td><a href="https://docs.google.com/document/d/1kUuvYwUH6tyLM4mNJYNu22jS6lPynvSSF_x8NDAZzRg">Guide</a></td></tr></tbody></table>


# 非 ERC20 代币流动性证明集成

### 介绍 <a href="#introduction" id="introduction"></a>

用户通常将ERC20凭证代币存入[奖励金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)来参与流动性证明，以赚取`$BGT` 。然而，这种方法并不适用于所有协议。

本节将演示如何为无法自动生成质押凭证的ERC20代币，或需要实时跟踪余额的协议集成流动性证明 (PoL) 系统。例如，永续合约交易所可能希望奖励`$BGT`开仓用户，并在平仓时停止奖励。

通过采用本节方案，上述协议仍可参与PoL系统，同等享有PoL提供的高效率激励。

{% hint style="danger" %}
请注意，本节仅提供一种将PoL与非ERC20协议集成的可行性解决方案。该解决方案并不详尽，不是所有用例都适用。
{% endhint %}

### 方案描述 <a href="#description-of-approach" id="description-of-approach"></a>

方案涉及创建一个虚拟的`StakingToken`，虚拟代币由协议代表用户质押在PoL金库中。虚拟代币用于跟踪用户的质押余额，在用户供应或提取流动性时，由协议铸造或销毁 (通过`ProtocolContract`实现)。

用户质押虚拟代币，赚取`$BGT`，如同在PoL金库中质押了ERC20凭证代币。此方案由[奖励金库](/berachain-docs/learn/proof-of-liquidity/rewardvaults)合约中的`delegateStake`和`delegateWithdraw`实现。

### 先决条件

开始之前，请确保你的本地设备上满足以下条件：

* 参考[Foundry安装文档](https://book.getfoundry.sh/getting-started/installation)安装该软件。

### Forge设置

1. 初始化Forge并安装依赖项：

```bash
forge init pol-smart-stake --no-commit --no-git;
cd pol-smart-stake;
forge install OpenZeppelin/openzeppelin-contracts --no-commit --no-git;
```

2. 创建`remappings.txt`文件，用于导入OpenZeppelin：

```bash
# FROM: ./pol-smart-stake

echo "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/" > remappings.txt;
```

### 合约执行

1. **在**`src/StakingToken.sol`**中部署虚拟代币合约：**

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

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

contract StakingToken is ERC20, Ownable {
    constructor() ERC20("StakingToken", "STK") Ownable(msg.sender) {}

    function mint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);
    }

    function burn(address from, uint256 amount) external onlyOwner {
        _burn(from, amount);
    }
}
```

该合约创建了一个虚拟的ERC20代币，用于质押在PoL金库中，只有代币所有者`ProtocolContract`可以铸造和销毁代币。

2. **在**`src/ProtocolContract.sol`**中部署虚拟协议合约：**

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./StakingToken.sol";
import {IBerachainRewardsVault, IBerachainRewardsVaultFactory} from "./interfaces/IRewardVaults.sol";

contract ProtocolContract {
    StakingToken public stakingToken;
    IBerachainRewardsVault public rewardVault;

    mapping(address => uint256) public userActivity;

    constructor(address _vaultFactory) {
        // Create new staking token
        stakingToken = new StakingToken();

        // Create vault for newly created token
        address vaultAddress = IBerachainRewardsVaultFactory(_vaultFactory)
            .createRewardsVault(address(stakingToken));

        rewardVault = IBerachainRewardsVault(vaultAddress);
    }

    function addActivity(address user, uint256 amount) external {
        // Protocol actions/logic here
        userActivity[user] += amount;

        // Mint StakingTokens
        stakingToken.mint(address(this), amount);

        // Stake tokens in RewardVault on behalf of user
        stakingToken.approve(address(rewardVault), amount);
        rewardVault.delegateStake(user, amount);
    }

    function removeActivity(address user, uint256 amount) external {
        // Protocol actions/logic here
        require(userActivity[user] >= amount, "Insufficient user activity");
        userActivity[user] -= amount;

        // Withdraw tokens from the RewardVault
        rewardVault.delegateWithdraw(user, amount);

        // Burn the withdrawn StakingTokens
        stakingToken.burn(address(this), amount);
    }
}
```

该合约是任意协议合约的简单用例：

* `userActivity`表示特定于该协议的内部核算和运作逻辑。
* `addActivity`和`removeActivity`余下功能是用于铸造和销毁虚拟代币`StakingTokens`，并与相关的奖励金库交互，以体现用户的质押/解除质押操作。

3. **在**`src/interfaces/IRewardVaults.sol`**中添加PoL接口：**

```solidity
pragma solidity ^0.8.19;

interface IBerachainRewardsVault {
    function delegateStake(address account, uint256 amount) external;

    function delegateWithdraw(address account, uint256 amount) external;

    function getTotalDelegateStaked(
        address account
    ) external view returns (uint256);

    function balanceOf(address account) external returns (uint256);
}

interface IBerachainRewardsVaultFactory {
    function createRewardsVault(
        address stakingToken
    ) external returns (address);
}
```

这些接口定义了从Factory合约中启动新的奖励金库，以及与之交互的方法。

### 测试集成

现在，对所有部署进行整体测试，以确保上述集成操作符合预期。以下是`ProtocolContract`的测试套件示例。

请检查每项测试，以便更加了解如何应对并成功处理各种情况。

```solidity

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

import "forge-std/Test.sol";
import "../src/ProtocolContract.sol";
import {IBerachainRewardsVault, IBerachainRewardsVaultFactory} from "../src/interfaces/IRewardVaults.sol";

contract ProtocolContractTest is Test {
    ProtocolContract public protocol;
    IBerachainRewardsVault public rewardVault;

    address public user1 = address(0x1);
    address public user2 = address(0x2);

    function setUp() public {
        IBerachainRewardsVaultFactory vaultFactory = IBerachainRewardsVaultFactory(
                0x2B6e40f65D82A0cB98795bC7587a71bfa49fBB2B
            );
        protocol = new ProtocolContract(address(vaultFactory));
        rewardVault = protocol.rewardVault();
    }

    function testAddActivity() public {
        protocol.addActivity(user1, 1);
        assertEq(protocol.userActivity(user1), 1);
        assertEq(rewardVault.balanceOf(user1), 1);
    }

    function testRemoveActivity() public {
        protocol.addActivity(user1, 2);
        protocol.removeActivity(user1, 1);
        assertEq(protocol.userActivity(user1), 1);
        assertEq(rewardVault.balanceOf(user1), 1);
    }

    function testMultipleUsers() public {
        protocol.addActivity(user1, 1);
        protocol.addActivity(user2, 2);
        assertEq(rewardVault.balanceOf(user1), 1);
        assertEq(rewardVault.balanceOf(user2), 2);
    }
}
```

### 运行测试 <a href="#run-the-test" id="run-the-test"></a>

最后，运行测试程序，以检查上述集成是否按预期工作：

```bash
# FROM: ./pol-smart-stake

forge test --rpc-url https://bartio.rpc.berachain.com/;

# [Expected Output]:
# [⠊] Compiling...x
# No files changed, compilation skipped

# Ran 3 tests for test/StakingToken.t.sol:ProtocolContractTest
# [PASS] testAddActivity() (gas: 252067)
# [PASS] testMultipleUsers() (gas: 371503)
# [PASS] testRemoveActivity() (gas: 272693)
# Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 1.73s (1.22ms CPU time)
```


# Berachain 节点


# 节点架构概述

Berachain网络依赖于验证节点和RPC节点。每个节点都可以配置为[全节点](https://ethereum.org/zh/developers/docs/nodes-and-clients/#full-node)或[归档节点](https://ethereum.org/zh/developers/docs/nodes-and-clients/archive-nodes/)。

这些类型的节点都由[执行客户端](https://ethereum.org/zh/developers/docs/nodes-and-clients/)和[共识客户端](https://ethereum.org/zh/developers/docs/nodes-and-clients/)组合。Berachain是一个与EVM等效的Layer 1链，这意味Berachain在执行层支持任意EVM执行客户端，这些客户端与Berachain构建的共识客户端和框架相互协作，共同组成[BeaconKit](/berachain-docs/nodes/berachain-nodes/beaconkit-consensus)。

<figure><img src="/files/SYQ8OYdBUJEGrvVzgfqc" alt=""><figcaption></figcaption></figure>


# BeaconKit 共识层

[BeaconKit](/berachain-docs/learn/introduction/what-is-beaconkit)既是共识客户端，也是构建EVM链的框架。

BeaconKit借鉴[CometBFT](https://cometbft.com/)来实现其共识算法，该算法可与任何EVM兼容的执行环境进行交互。作为共识客户端，它允许网络 (比如Berachain这样的EVM区块链) 根据执行客户端提供的数据达成协议共识。

BeaconKit遵循[Eth2](https://ethereum.org/zh/roadmap/)路线的模块化需求，将共识和执行分离，兼顾EVM执行客户端的所有优势。能够做到这一点，是因为它遵循[Ethereum Engine API](https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md)，即JSON-RPC API，允许共识和执行客户端之间通信。

### BeaconKit的优势

以下是BeaconKit的优势所在：

1. **Eth2模块化**：坚持执行与共识分离，两者通过Engine API通信。
2. **执行客户端多样性**：无缝支持EVM执行客户端的任何升级，无需另外运行和维护一个分叉EVM执行客户端。
3. **CometBFT**：利用可信的共识算法。
4. **瞬时最终性 (Instant Finality)**：实现了[单时隙最终确定性](https://ethereum.org/zh/roadmap/single-slot-finality/#single-slot-finality) (Single Slot Finality)。区块可在同一时隙内提议并最终确定，而以太坊的最终确定时间约为13分钟。
5. **EVM工具兼容性**：支持所有基于EVM开发的工具，如果某工具能在以太坊网络使用，则也能在BeaconKit使用。
6. **模块化**：BeaconKit采用模块化框架，支持自定义区块生成器，可用于Layer 2网络，可用于数据可用性层等。

| 技术组件  | 以太坊                                                                                       | BeaconKit                           |
| ----- | ----------------------------------------------------------------------------------------- | ----------------------------------- |
| 执行客户端 | EVM (Geth, Reth, Erigon, ...)                                                             | EVM (Geth, Reth, Erigon, ...)       |
| 共识算法  | 基于[Gasper](https://ethereum.org/zh/developers/docs/consensus-mechanisms/pos/gasper/)的权益证明 | 基于[CometBFT](https://cometbft.com/) |
| 最终确定性 | Gasper FFG (约13分钟)                                                                        | 单时隙最终确定性 (即时)                       |
| 架构设计  | 支持模块化                                                                                     | 支持模块化                               |


# EVM 执行层

执行层有多种实现形式，支持任意EVM执行客户端，负责处理交易、交易广播、状态管理以及支持以太坊虚拟机，但不负责出块。

以下是BeaconKit支持的，已通过测试和验证的执行客户端：

<table><thead><tr><th width="131">客户端</th><th width="103">编程语言</th><th width="242">同步策略</th><th width="104">状态修剪</th><th>维护机构</th></tr></thead><tbody><tr><td><a href="https://github.com/ethereum/go-ethereum">Geth</a></td><td>Golang</td><td>快照/全节点</td><td>存档/修剪</td><td>以太坊基金会</td></tr><tr><td><a href="https://github.com/NethermindEth/nethermind">Nethermind</a></td><td>C#, .NET</td><td>快照(无服务)/Fast模式/全节点</td><td>存档/修剪</td><td>Nethermind</td></tr><tr><td><a href="https://github.com/hyperledger/besu/">Besu</a></td><td>Java</td><td>快照/Fast模式/全节点</td><td>存档/修剪</td><td>Hyperledger</td></tr><tr><td><a href="https://github.com/ledgerwatch/erigon">Erigon</a></td><td>Golang</td><td>全节点</td><td>存档/修剪</td><td>Erigon</td></tr><tr><td><a href="https://github.com/paradigmxyz/reth">Reth</a></td><td>Rust</td><td>全节点</td><td>存档/修剪</td><td>Paradigm</td></tr><tr><td><a href="https://github.com/ethereumjs/ethereumjs-monorepo">EthereumJS</a></td><td>TypeScript</td><td>全节点</td><td>修剪</td><td>以太坊基金会</td></tr></tbody></table>


# 节点运行快速入门

本节将演示部署一个`bArtio`测试网RPC归档节点，该节点包含`beacond`共识客户端和`reth`执行客户端。

{% hint style="info" %}
注意：目前，测试网验证节点需被列入等候白名单，并在网络需要时运行。
{% endhint %}

### 先决条件

开始之前，请确保你的本地设备上满足以下条件：

* [Golang](https://go.dev/dl/) `v1.22.0`或更高版本
* 满足最低硬件要求
* 已安装[Foundry](https://book.getfoundry.sh/getting-started/installation) (用于测试)

#### 最低硬件要求

运行执行客户端和共识客户端均需要满足以下要求。建议在同一台设备运行这两个客户端，以实现两者之间的低延迟通信。

* 支持的系统：Linux / MacOS
* CPU架构：AMD64，ARM64或ARM64 Darwin
* CPU性能：8核
* 内存：48GB
* 硬盘：1TB

{% hint style="info" %}
如果以Docker容器运行，请确保每个Docker容器有足够的资源，以满足总需求。
{% endhint %}

### 源代码构建和运行

本节快速入门文档，将从源头构建共识客户端。

{% hint style="info" %}
注意：请勿在Vscode中运行执行客户端或共识客户端，容易造成崩溃，请使用专业的Shell终端。
{% endhint %}

#### 复制代码库并验证binary文件

首先，复制[BeaconKit代码库](https://github.com/berachain/beacon-kit)，创建binary文件。

```bash
git clone https://github.com/berachain/beacon-kit;
cd beacon-kit;
make build;

# [Expected Output]:
# mkdir -p /path/to/beacon-kit/build/bin/
# Variables
# Building beacond/cmd
# ...
# go: downloading github.com/berachain/cosmos-sdk v0.46.0-beta2.0.20240624014538-75ba469b1881
```

这将创建一个位于`./build/bin/beacond`的本地binary文件。

接下来，运行以下代码，测试其是否正常工作：

```bash
# FROM: ./beacon-kit

./build/bin/beacond version;

# [Expected Output]:
# v0.2.0-alpha.1-172-g071b95a5
```

### 配置共识客户端

以下将演示配置一个`BeaconKit`共识客户端。

#### 第 1 步：初始化信标节点

首先，为配置创建一个临时文件夹目录。此步骤可省略，但为了后续便利，创建临时文件夹以保存所有配置和数据库数据。

```bash
# FROM: ./beacon-kit

mkdir build/bin/config;
mkdir build/bin/config/beacond;
mkdir build/bin/config/reth;
```

接下来，使用所有标准数据初始化节点。

```bash
# FROM: ./beacon-kit

# Replace <YOUR_MONIKER_NAME> with a name of your choice.
MONIKER_NAME=<YOUR_NODE_MONIKER>; # Ex: MONIKER_NAME=BingBongNode
./build/bin/beacond init $MONIKER_NAME --chain-id bartio-beacon-80084 --consensus-key-algo bls12_381 --home ./build/bin/config/beacond;
# Ex: ./build/bin/beacond init BingBongNode --chain-id bartio-beacon-80084 --consensus-key-algo bls12_381 --home ./build/bin/config/beacond;

# [Expected Output]:
# {
#  "moniker": "BingBongNode", // <YOUR_MONIKER_NAME>
#  "chain_id": "bartio-beacon-80084",
#  "node_id": "72e2e6f9d667898d32ede54de9b9299eb567f692",
#  "gentxs_dir": "",
# ...
```

现在，应该能够在`./build/bin/config`文件夹中看到新创建的文件。

{% hint style="danger" %}
**重要提示**：运行验证器节点，务必安全备份`priv_validator_key.json`文件。该文件包含验证器的私钥，用于验证器对区块进行签名。如果丢失该文件，无人能提供帮助，你将永远无法恢复验证器及提取资产。
{% endhint %}

```bash
# FROM: ./beacon-kit

tree build/bin/config/beacond;

# [Expected Output]:
# build/bin/config/beacond
# ├── config
# │   ├── app.toml
# │   ├── client.toml
# │   ├── config.toml
# │   ├── genesis.json
# │   ├── node_key.json
# │   └── priv_validator_key.json <---- BACK THIS UP
# └── data
#     └── priv_validator_state.json
```

#### 第 2 步：添加配置文件

首先，通过下载到`config`文件夹中的文件，恢复源文件：

```bash
# FROM: ./beacon-kit

curl -o "./build/bin/config/beacond/config/genesis.json" "https://raw.githubusercontent.com/berachain/beacon-kit/main/testing/networks/80084/genesis.json";

# [Expected Output]:
# % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                  Dload  Upload   Total   Spent    Left  Speed
# 100 46860  100 46860    0     0   295k      0 --:--:-- --:--:-- --:--:--  293k
```

仔细检查源文件，确保类似于以下形式：

```bash
# FROM: ./beacon-kit

cat ./build/bin/config/beacond/config/genesis.json;

# [Expected Output]:
# {
#   "app_name": "beacond",
#   "app_version": "v0.2.0-alpha.0",
#   "genesis_time": "2024-06-05T14:00:00Z",
#   "chain_id": "bartio-beacon-80084",
#   "initial_height": 1,
#   "app_hash": null,
#   "app_state": {
# ...
```

接下来，恢复kzg可信设置：

```bash
# FROM: ./beacon-kit

curl -o "./build/bin/config/beacond/kzg-trusted-setup.json" "https://raw.githubusercontent.com/berachain/beacon-kit/main/testing/networks/80084/kzg-trusted-setup.json";

# [Expected Output]:
#   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                  Dload  Upload   Total   Spent    Left  Speed
# 100  436k  100  436k    0     0  2744k      0 --:--:-- --:--:-- --:--:-- 2747k
```

然后，从[BeaconKit testnet repo](https://github.com/berachain/beacon-kit/tree/main/testing/networks/80084)恢复`app.toml`和`config.toml`数据：

```bash
# FROM: ./beacon-kit

# app.toml
curl -o "./build/bin/config/beacond/config/app.toml" "https://raw.githubusercontent.com/berachain/beacon-kit/main/testing/networks/80084/app.toml";

# config.toml
curl -o "./build/bin/config/beacond/config/config.toml" "https://raw.githubusercontent.com/berachain/beacon-kit/main/testing/networks/80084/config.toml";
```

通过添加moniker name和peers以修改配置。

{% hint style="info" %}
如果你的设备不是MacOS系统，请将下方代码中的`-i ''`替换为`-i` 。
{% endhint %}

```bash
# FROM: ./beacon-kit

# Rename the moniker
MONIKER_NAME=<YOUR_NODE_MONIKER>; # Ex: MONIKER_NAME=BingBongNode
sed -i '' "s/^moniker = \".*\"/moniker = \"$MONIKER_NAME\"/" "$PWD/build/bin/config/beacond/config/config.toml";

# set jwt.hex path
JWT_PATH=$PWD/build/bin/config/beacond/jwt.hex; # generating in next step
sed -i '' "s|^jwt-secret-path = \".*\"|jwt-secret-path = \"$JWT_PATH\"|" "$PWD/build/bin/config/beacond/config/app.toml";

# seeds
# - Comma separated list of seeds
seeds_url="https://raw.githubusercontent.com/berachain/beacon-kit/main/testing/networks/80084/cl-seeds.txt";
seeds=$(curl -s "$seeds_url" | tail -n +2 | tr '\n' ',' | sed 's/,$//');
sed -i '' "s/^seeds = \".*\"/seeds = \"$seeds\"/" "$PWD/build/bin/config/beacond/config/config.toml";

# persistent peers
# - Comma separated list of nodes to keep persistent connections to
sed -i '' "s/^persistent_peers = \".*\"/persistent_peers = \"$seeds\"/" "$PWD/build/bin/config/beacond/config/config.toml";
```

#### 第 3 步：生成JWT令牌

这将创建一个JSON Web令牌，以允许BeaconKit共识客户端与EVM执行客户端通信。

运行以下代码，创建JWT令牌：

```bash
# FROM: ./beacon-kit

./build/bin/beacond jwt generate -o ./build/bin/config/beacond/jwt.hex;

# [Expected Output]:
# Successfully wrote new JSON-RPC authentication secret to: ./build/bin/config/jwt.hex
```

这将创建一个`jwt.hex`文件，可以使用`-o`标签指定可选路径。如果不指定输出位置，则在beacond配置目录中生成，例如`/root/.beacond/config/jwt.hex`。

#### 第 4 步：下载快照 (推荐操作)

强烈建议执行此步骤，以避免后续等待较长的同步时间。

{% hint style="danger" %}
从源资源库同步节点可能需要几小时，甚至几天，具体取决于带宽速度和peers数量。
{% endhint %}

参阅此处，获取快照链接列表：[Berachain bArtio V2 Snapshots](https://github.com/berachain/beacon-kit/blob/main/testing/networks/80084/snapshots.md)

运行以下代码，创建快照文件夹并下载快照文件：

```bash
# FROM: ./beacon-kit

mkdir snapshots;
curl -L EXAMPLE_SNAPSHOT_FILE.tar.lz4 > ./snapshots/EXAMPLE_SNAPSHOT_FILE.tar.lz4;

# [Example Output]:
#   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                  Dload  Upload   Total   Spent    Left  Speed
#   0 43.0G    0 78.1M    0     0  18.7M      0  0:39:07  0:00:04  0:39:03 18.7M
```

下载完成，解压快照文件并验证数据：

```bash
# FROM: ./beacon-kit

# make a directory and download snapshots
mkdir snapshots/tmp;
mkdir snapshots/tmp/beacond;
mkdir snapshots/tmp/reth;
# curl ...

# unzip
# - beacond
lz4 -dc < ./snapshots/EXAMPLE_SNAPSHOT_BEACOND.tar.lz4 | tar xvf - -C ./snapshots/tmp/beacond;
# [Expected Output]:
# ...
# x data/application.db/012580.sst
# x data/application.db/012780.sst
# x data/application.db/012421.sst
# x data/application.db/012420.sst

# - reth
lz4 -dc < ./snapshots/EXAMPLE_SNAPSHOT_RETH.tar.lz4 | tar xvf - -C ./snapshots/tmp/reth;
# [Expected Output]:
# ...
# x static_files/static_file_transactions_0_499999
# x static_files/static_file_receipts_1000000_1499999.off
# x static_files/static_file_headers_0_499999
```

快照文件应包含以下`beacond`和`reth`所需内容 (或相应EVM执行客户端所需内容)：

```bash
# ./snapshots/tmp/beacond - (needed folders & files)
# └── data
#     ├── application.db
#     ├── blobs
#     ├── blockstore.db
#     ├── cs.wal
#     ├── deposits.db
#     ├── evidence.db
#     ├── snapshots.db
#     ├── state.db
#     ├── tx_index.db
#     └── priv_validator_state.json
#
# ./snapshots/tmp/reth - (needed folders & files)
# ├── blobstore
# ├── db
# └── static_files
```

快照文件夹和快照文件验证完成后，将快照数据移入相应的配置文件夹。

```bash
# FROM: ./beacon-kit

# beacond
mv ./snapshots/tmp/beacond/data ./build/bin/config/beacond/data;

# reth
mv ./snapshots/tmp/reth/blobstore ./build/bin/config/reth/blobstore;
mv ./snapshots/tmp/reth/db ./build/bin/config/reth/db;
mv ./snapshots/tmp/reth/static_files ./build/bin/config/reth/static_files;
```

#### 第 5 步：运行Beacon

配置好`config.toml`和`app.toml`文件后，运行以下代码，启动Beacon：

```bash
# FROM: ./beacon-kit

./build/bin/beacond start --home ./build/bin/config/beacond;

# [Expected Output]:
# ...
# INFO Starting service type=validator-updates-broker
# INFO Starting service type=engine-client
# INFO Initializing connection to the execution client... service=engine.client dial_url=http://localhost:8551
# INFO Waiting for execution client to start... 🍺🕔 service=engine.client dial_url=http://localhost:8551
# INFO Waiting for execution client to start... 🍺🕔 service=engine.client dial_url=http://localhost:8551
```

现在，你的BeaconKit共识客户端已配置完成，接下来配置执行客户端。

### 配置执行客户端

接下来，需要将执行客户端与`beacond`配对。

{% hint style="info" %}
注意：所有基于以太坊的执行客户端均受支持！

然而，有些客户端可能需要更复杂的配置和微调，才能达到出块时间要求。因此，目前最推荐以下客户端：

* [Reth](https://github.com/paradigmxyz/reth)
* [Geth](https://github.com/ethereum/go-ethereum)
* [Erigon](https://github.com/ledgerwatch/erigon)
* [Besu](https://github.com/hyperledger/besu)
* [Nethermind](https://github.com/NethermindEth/nethermind)
* [EthereumJS](https://github.com/ethereumjs/ethereumjs-monorepo)
  {% endhint %}

下述示例中，将使用[Reth](https://reth.rs/)作为执行客户端。

首先，新建一个终端会话，下载MacOS (基于苹果电脑芯片的操作系统) 的binary文件：

{% hint style="danger" %}
**警告**：本快速入门演示了如何在MacOS系统上运行节点，仅用于测试目的，不建议真实生产环境中在MacOS系统上运行节点。
{% endhint %}

```bash
# FROM: ./beacon-kit

curl -L https://github.com/paradigmxyz/reth/releases/download/v1.0.3/reth-v1.0.3-x86_64-apple-darwin.tar.gz > reth-v1.0.3-x86_64-apple-darwin.tar.gz;
tar -xzvf reth-v1.0.3-x86_64-apple-darwin.tar.gz;

# # [Expected Output]:
#   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                  Dload  Upload   Total   Spent    Left  Speed
#   0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
# 100 20.6M  100 20.6M    0     0  47.5M      0 --:--:-- --:--:-- --:--:-- 47.5M
# x reth
```

运行以下代码，检查`reth`客户端是否正常工作：

```bash
# FROM: ./beacon-kit

./reth --version;

# [Expected Output]:
# reth Version: 1.0.0
# Commit SHA: 31e2470
# Build Timestamp: 2024-06-24T10:26:24.880668000Z
# Build Features: jemalloc
# Build Profile: maxperf
```

#### 第 1 步：配置源文件

首先，从BeaconKit代码库下载eth创世源文件。

```bash
# FROM: ./beacon-kit

curl -o "./build/bin/config/reth/eth-genesis.json" "https://raw.githubusercontent.com/berachain/beacon-kit/main/testing/networks/80084/eth-genesis.json";

# [Expected Output]:
#   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                  Dload  Upload   Total   Spent    Left  Speed
# 100  7232  100  7232    0     0  42532      0 --:--:-- --:--:-- --:--:-- 42792
```

仔细检查源文件，确保类似于以下形式：

```bash
# FROM: ./beacon-kit

cat ./build/bin/config/reth/eth-genesis.json;

# [Expected Output]:
# {
#   "config": {
#     "chainId": 80084,
#     "homesteadBlock": 0,
#     "daoForkBlock": 0,
#     "daoForkSupport": true,
# ...
```

#### 第 2 步：启动Reth

运行以下代码，完成剩余reth文件配置：

```bash
# FROM: ./beacon-kit

./reth init --datadir ./build/bin/config/reth --chain=./build/bin/config/reth/eth-genesis.json;
```

#### 第 3 步：运行Reth客户端

```bash
# retrieve bootnode
bootnodes_url="https://raw.githubusercontent.com/berachain/beacon-kit/main/testing/networks/80084/el-bootnodes.txt";
bootnodes=$(curl -s "$bootnodes_url" | grep '^enode://' | tr '\n' ',' | sed 's/,$//');

# run reth
./reth node --authrpc.jwtsecret=./build/bin/config/beacond/jwt.hex \
--chain=./build/bin/config/reth/eth-genesis.json \
--datadir=./build/bin/config/reth \
--port=30303 \
--http \
--http.addr=0.0.0.0 \
--http.api="eth,net,web3,txpool,debug" \
--http.port=8545 \
--http.corsdomain="*" \
--bootnodes=$bootnodes \
--trusted-peers=$bootnodes \
--ws \
--ws.addr=0.0.0.0 \
--ws.port=8546 \
--ws.origins="*" \
--authrpc.addr=0.0.0.0 \
--authrpc.port=8551 \
--log.file.directory=./build/bin/config/reth/logs \
--metrics=0.0.0.0:6060;

# [Expected Output]:
# INFO Initialized tracing, debug log directory: ./build/bin/config/reth/logs/80084
# INFO Starting reth version="1.0.0 (31e2470)"
# INFO Opening database path="./build/bin/config/reth/db"
# INFO Configuration loaded path="./build/bin/config/reth/reth.toml"
# INFO Adding trusted nodes
# INFO Verifying storage consistency.
# INFO Database opened
# INFO Starting metrics endpoint addr=0.0.0.0:6060
# ...
```

### 检查同步状态

新建一个终端会话，并运行以下代码：

```bash
# Don't have jq? `brew install jq`;
./build/bin/beacond --home=./build/bin/config/beacond status | jq;

# [Expected Output]:
# {
#   "node_info": {
#     "protocol_version": {
#       "p2p": "9",
#       "block": "11",
#       "app": "0"
#     },
#     "id": "3078798f76b4db03aca9c71dd3264c252e06dfbf",
#     "listen_addr": "tcp://0.0.0.0:26656",
#     "network": "bartio-beacon-80084",
#     "version": "1.0.0-rc1",
#     "channels": "40202122233038606100",
#     "moniker": "BingBongNode",
#     "other": {
#       "tx_index": "off",
#       "rpc_address": "tcp://127.0.0.1:26657"
#     }
#   },
#   "sync_info": {
#     "latest_block_hash": "A72E1C5BD31B0E14604BB6DBA5A313F5B17F78FEE482453D9ED703E49D0C059B",
#     "latest_app_hash": "FC649179895650C9B6EB4320A096F46D8882CAD3AAFEE1B0D997B338BDF31618",
#     "latest_block_height": "1126228",<---- CURRENT NETWORK BLOCK
#     "latest_block_time": "2024-07-05T03:50:15.349853738Z",
#     "earliest_block_hash": "F10DEBCEF3E370F813E93BD8BBFA3DAC0392E6C3E9A8A63871E932ACDE44EE1F",
#     "earliest_app_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
#     "earliest_block_height": "1",
#     "earliest_block_time": "2024-06-05T14:00:00Z",
#     "catching_up": false<---- IF `true` = STILL SYNCING
#   },
#   "validator_info": {
#     "address": "74F0F7AC6C37306E765487F8C43F01059EE28391",
#     "pub_key": {
#       "type": "cometbft/PubKeyBls12_381",
#       "value": "i/z8e0Fz1+EiW1YGe9wdqCuAM9sny3r8s4gpjLlDHGFQfv36Vffq/+KoCJKuGRT8"
#     },
#     "voting_power": "0"
#   }
# }
```

### 测试本地RPC节点

现在，通过以下步骤来验证当前网络是否正常运行，需要执行一些RPC请求，并部署一个合约。

{% hint style="info" %}
先决条件：在此之前，请确保节点同步已完成。
{% endhint %}

#### 获取当前区块高度

```bash
curl --location 'http://localhost:8545' \
--header 'Content-Type: application/json' \
--data '{
	"jsonrpc":"2.0",
	"method":"eth_blockNumber",
	"params":[],
	"id":83
}';

# [Expected Output]:
# {
#     "jsonrpc": "2.0",
#     "result": "0xfae90",
#     "id": 83
# }
```


# 节点指南


# 使用 Kurtosis 运行本地开发网

本节将演示部署一个Berachain开发网 (未连接到 bArtio)。

{% hint style="info" %}
Berachain开发网的原生dApp、合约等功能可能仍在开发中。
{% endhint %}

### 先决条件

开始之前，请确保你的本地设备上满足以下条件：

* [Docker](https://docs.docker.com/get-docker/)：`version 25.0.2`或更高版本
* [Kurtosis](https://docs.kurtosis.com/install)：`v0.90.1`或更高版本
* [Foundry](https://book.getfoundry.sh/getting-started/installation)：`v0.2.0`或更高版本 (用于测试)

### Kurtosis本地开发网

本步骤需要设置并运行多个服务和执行客户端。

{% hint style="danger" %}
**警告**：这可能需要相当多的资源来运行，如果遇到限制，请修改yaml配置文件以限制节点/服务的数量。
{% endhint %}

在默认的Kurtosis配置中，将运行以下内容：

* 5个验证节点
* 3个全节点
* 6项附加服务

可以通过修改[beaconkit-all.yaml](https://github.com/berachain/beacon-kit/blob/main/kurtosis/beaconkit-all.yaml)以符合你的设备配置。

#### 第 1 步：复制代码库并运行节点

运行以下代码，复制Kurtosis代码库：

```bash
git clone https://github.com/berachain/beacon-kit;
cd beacon-kit;
```

然后，运行以下代码，运行Make脚本：

{% hint style="info" %}
如果遇到问题，请参阅[故障排除](#gu-zhang-pai-chu)。
{% endhint %}

```bash
# FROM: ./beacon-kit

make start-devnet;

# [Expected Output]:
# Checking for Kurtosis installation...
# Kurtosis is already installed
# /Applications/Xcode.app/Contents/Developer/usr/bin/make build-docker VERSION=kurtosis-local start-devnet-no-build
# Build a release docker image for the Cosmos SDK chain...
# docker build \
# 	--platform linux/arm64 \
# 	--build-arg GIT_COMMIT=f3738205bcd8c91f3c262618b078eeefb48a67f3 \
# 	--build-arg GIT_VERSION=kurtosis-local \
# 	--build-arg GIT_BRANCH=main \
# 	--build-arg GOOS=linux \
# 	--build-arg GOARCH=arm64 \
# 	-f ./Dockerfile \
# 	-t beacond:kurtosis-local \
# 	.
# [+] Building 26.0s (33/41)
# ...
# Starlark code successfully run. No output was returned.
#
# ⭐ us on GitHub - https://github.com/kurtosis-tech/kurtosis
# INFO[2024-06-27T00:16:11-04:00] ========================================================
# INFO[2024-06-27T00:16:11-04:00] ||          Created enclave: my-local-devnet          ||
# INFO[2024-06-27T00:16:11-04:00] ========================================================
# Name:            my-local-devnet
# UUID:            3c23eccb8c64
# Status:          RUNNING
# Creation Time:   Thu, 27 Jun 2024 00:14:55 EDT
# Flags:
#
# ========================================= Files Artifacts =========================================
# UUID           Name
# b5aae73c6271   ancient-butterfly
# 601914df8eea   cosmos-genesis-final
# 2c8346b3df40   el_cl_genesis_data
# 38571b521297   genesis_file
# 978405cf0e0f   geth-config
# 46c4a6d9988e   jwt_file
# 39ab7b9e6b01   kzg_trusted_setup
# 0f6148946b08   multiple-premined-deposits
# c59bf8b35b60   nether_genesis_file
# 0c84ab86dd73   nethermind-config
# e965d7a7faa0   node-beacond-config-0
# 030b600e169c   node-beacond-config-1
# 8d644e614430   node-beacond-config-2
# 618d91e2218d   node-beacond-config-3
# 447d51638f49   node-beacond-config-4
# 7d656edde80a   prometheus-config
# 9d93c25b6424   reth-config
# 3e7411b9e325   vast-storm
#
# ========================================== User Services ==========================================
# UUID           Name                        Ports                                                  Status
# 79f7561b4b43   blockscout                  http: 4000/tcp -> http://127.0.0.1:53414               RUNNING
# 26c02bed0a42   blockscout-postgres         postgresql: 5432/tcp -> postgresql://127.0.0.1:53306   RUNNING
# fd16c170438f   blockscout-verif            http: 8050/tcp -> http://127.0.0.1:53345               RUNNING
# f545ea9b37d9   blutgang                    admin: 5715/tcp -> http://127.0.0.1:52505              RUNNING
#                                            http: 3000/tcp -> http://127.0.0.1:52506
# b018cf002dc9   cl-full-beaconkit-0         cometbft-grpc: 9090/tcp -> 127.0.0.1:51243             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:51245
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:51244
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:51246
#                                            metrics: 26660/tcp -> 127.0.0.1:51247
# e2e1c5b99640   cl-full-beaconkit-1         cometbft-grpc: 9090/tcp -> 127.0.0.1:51235             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:51237
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:51236
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:51233
#                                            metrics: 26660/tcp -> 127.0.0.1:51234
# 85954427d8ed   cl-full-beaconkit-2         cometbft-grpc: 9090/tcp -> 127.0.0.1:51239             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:51241
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:51240
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:51242
#                                            metrics: 26660/tcp -> 127.0.0.1:51238
# 01c06ac63cdf   cl-seed-beaconkit-0         cometbft-grpc: 9090/tcp -> 127.0.0.1:51194             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:51191
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:51195
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:51192
#                                            metrics: 26660/tcp -> 127.0.0.1:51193
# 0f4df1fc5824   cl-validator-beaconkit-0    cometbft-grpc: 9090/tcp -> 127.0.0.1:52318             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:52315
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:52314
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:52316
#                                            metrics: 26660/tcp -> 127.0.0.1:52317
# 81d2e6091425   cl-validator-beaconkit-1    cometbft-grpc: 9090/tcp -> 127.0.0.1:52321             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:52323
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:52322
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:52319
#                                            metrics: 26660/tcp -> 127.0.0.1:52320
# 31ac5a4a8367   cl-validator-beaconkit-2    cometbft-grpc: 9090/tcp -> 127.0.0.1:52342             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:52339
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:52338
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:52340
#                                            metrics: 26660/tcp -> 127.0.0.1:52341
# 16a9f7c56f2c   cl-validator-beaconkit-3    cometbft-grpc: 9090/tcp -> 127.0.0.1:52332             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:52329
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:52328
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:52330
#                                            metrics: 26660/tcp -> 127.0.0.1:52331
# 350ad296d808   cl-validator-beaconkit-4    cometbft-grpc: 9090/tcp -> 127.0.0.1:52337             RUNNING
#                                            cometbft-p2p: 26656/tcp -> 127.0.0.1:52334
#                                            cometbft-rest: 1317/tcp -> 127.0.0.1:52333
#                                            cometbft-rpc: 26657/tcp -> 127.0.0.1:52335
#                                            metrics: 26660/tcp -> 127.0.0.1:52336
# 6e118e6069ea   el-full-geth-2              engine-rpc: 8551/tcp -> 127.0.0.1:51205                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51208
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51204
#                                            metrics: 9001/tcp -> 127.0.0.1:51206
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51207
#                                            udp-discovery: 30303/udp -> 127.0.0.1:62535
# a02f6e9ffb57   el-full-reth-0              engine-rpc: 8551/tcp -> 127.0.0.1:51216                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51214
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51215
#                                            metrics: 9001/tcp -> 127.0.0.1:51217
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51218
#                                            udp-discovery: 30303/udp -> 127.0.0.1:63859
# 66ec4f86f9a8   el-full-reth-1              engine-rpc: 8551/tcp -> 127.0.0.1:51211                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51209
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51210
#                                            metrics: 9001/tcp -> 127.0.0.1:51212
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51213
#                                            udp-discovery: 30303/udp -> 127.0.0.1:52493
# 985f34bb632c   el-seed-reth-0              engine-rpc: 8551/tcp -> 127.0.0.1:51178                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51181
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51182
#                                            metrics: 9001/tcp -> 127.0.0.1:51179
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51180
#                                            udp-discovery: 30303/udp -> 127.0.0.1:64586
# ff5d4880de7e   el-validator-besu-0         engine-rpc: 8551/tcp -> 127.0.0.1:51449                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51452
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51453
#                                            metrics: 9001/tcp -> 127.0.0.1:51450
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51451
#                                            udp-discovery: 30303/udp -> 127.0.0.1:55464
# 3677d9c2ab08   el-validator-erigon-4       engine-rpc: 8551/tcp -> 127.0.0.1:51416                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51419
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51415
#                                            metrics: 9001/tcp -> 127.0.0.1:51417
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51418
#                                            udp-discovery: 30303/udp -> 127.0.0.1:52140
# 8a8d0605d110   el-validator-geth-3         engine-rpc: 8551/tcp -> 127.0.0.1:51456                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51454
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51455
#                                            metrics: 9001/tcp -> 127.0.0.1:51457
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51458
#                                            udp-discovery: 30303/udp -> 127.0.0.1:57790
# 27c61431bf07   el-validator-nethermind-1   engine-rpc: 8551/tcp -> 127.0.0.1:51440                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51443
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51444
#                                            metrics: 9001/tcp -> 127.0.0.1:51441
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51442
#                                            udp-discovery: 30303/udp -> 127.0.0.1:60619
# bb829e4f06e5   el-validator-reth-2         engine-rpc: 8551/tcp -> 127.0.0.1:51423                RUNNING
#                                            eth-json-rpc: 8545/tcp -> 127.0.0.1:51421
#                                            eth-json-rpc-ws: 8546/tcp -> 127.0.0.1:51422
#                                            metrics: 9001/tcp -> 127.0.0.1:51424
#                                            tcp-discovery: 30303/tcp -> 127.0.0.1:51420
#                                            udp-discovery: 30303/udp -> 127.0.0.1:52707
# cc6bfe221c4e   goomy-blob-spammer          <none>                                                 RUNNING
# 6e417d31c1dd   grafana                     dashboards: 3000/tcp -> http://127.0.0.1:52841         RUNNING
# 5c5b3c300c71   prometheus                  http: 9090/tcp -> http://127.0.0.1:52746               RUNNING
# e5d817a7ff20   pyroscope                   pyroscope: 4040/tcp -> http://127.0.0.1:53224          RUNNING
# fc84cfef2319   tx-fuzz-0                   <none>                                                 RUNNING
# 1dd2fece619b   tx-fuzz-1                   <none>                                                 RUNNING
# 26df503b9a05   tx-fuzz-10                  <none>                                                 RUNNING
# 9e979dffa8f3   tx-fuzz-11                  <none>                                                 RUNNING
# e6bf3df68ab5   tx-fuzz-12                  <none>                                                 RUNNING
# caf8e90eb636   tx-fuzz-13                  <none>                                                 RUNNING
# b37cfe191eba   tx-fuzz-14                  <none>                                                 RUNNING
# ac0a401c2e31   tx-fuzz-15                  <none>                                                 RUNNING
# c7877a3e9efa   tx-fuzz-2                   <none>                                                 RUNNING
# c13b0dd16da6   tx-fuzz-3                   <none>                                                 RUNNING
# f92b5661000c   tx-fuzz-4                   <none>                                                 RUNNING
# 6afbb7c0a215   tx-fuzz-5                   <none>                                                 RUNNING
# d6cc564bf8fd   tx-fuzz-6                   <none>                                                 RUNNING
# d6f6ac4fcba1   tx-fuzz-7                   <none>                                                 RUNNING
# 00dc8cdbb379   tx-fuzz-8                   <none>                                                 RUNNING
# 78f3100e7ce8   tx-fuzz-9                   <none>                                                 RUNNING
```

#### 第 2 步：测试本地开发网

测试本地开发网是否正常工作，只需运行本地区块浏览器：

```bash
open http://127.0.0.1:53414; # 注意: 端口(53414)是随机的, 不同部署环境有所不同
```

<figure><img src="/files/WaYD323kmwHiwuCxhKBX" alt=""><figcaption></figcaption></figure>

#### 第 3 步：配置钱包

查看现有的示例钱包地址和私钥列表，请参阅[Constants.star](https://github.com/berachain/beacon-kit/blob/main/kurtosis/src/constants.star)

首先，将开发网网络参数添加到MetaMask钱包。

{% hint style="info" %}
区块浏览器端口(53414)是随机的，不同部署环境有所不同，请检查操作日志。
{% endhint %}

| 参数      | 值                        |
| ------- | ------------------------ |
| 网络名称    | Berachain Local Devnet   |
| RPC地址   | <http://127.0.0.1:51208> |
| 链 ID    | 80087                    |
| Gas代币符号 | BERA                     |
| 区块浏览器   | <http://127.0.0.1:53414> |

接下来，导入一个[Constants.star](https://github.com/berachain/beacon-kit/blob/main/kurtosis/src/constants.star)中示例钱包地址和私钥。

**文件位置**：`./kurtosis/src/constants.star`

```python
# ...

PRE_FUNDED_ACCOUNTS = [
    new_prefunded_account(
        "0x20f33ce90a13a4b5e7697e3544c3083b8f8a51d4",
        # Import this ↓
        "fffdbb37105441e14b0ee6330d855d8504ff39e705c3afa8f859ac9865f99306", #
    ),

# ...
```

成功导入，会在MetaMask钱包显示帐户`0x20f33ce90a13a4b5e7697e3544c3083b8f8a51d4`：

<figure><img src="/files/Lr7Iw9cEUEa8fyVBYcBp" alt=""><figcaption></figcaption></figure>

#### 第 4 步：部署合约 <a href="#step-4-deploy-contract" id="step-4-deploy-contract"></a>

接下来，运行[Berachain Guides HelloWorld.sol](https://github.com/berachain/guides/blob/main/apps/hardhat-viem-helloworld/contracts/HelloWorld.sol)将`HelloWorld`合约部署到本地开发网。

```bash
# FROM: ./beacon-kit;

mkdir tmp;
touch tmp/HelloWorld.sol;
```

**文件位置：**`./tmp/HelloWorld.sol`

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

contract HelloWorld {
    // Events that allows for emitting a message
    event NewGreeting(address sender, string message);

    // Variables
    string greeting;

    // Main constructor run at deployment
    constructor(string memory _greeting) {
        greeting = _greeting;
        emit NewGreeting(msg.sender, _greeting);
    }

    // Get function
    function getGreeting() public view returns (string memory) {
        return greeting;
    }

    // Set function
    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
        emit NewGreeting(msg.sender, _greeting);
    }
}
```

然后，运行`cast`请求，部署字节码。

```bash
# FROM: ./

forge create --rpc-url http://127.0.0.1:51208 --private-key fffdbb37105441e14b0ee6330d855d8504ff39e705c3afa8f859ac9865f99306 tmp/HelloWorld.sol:HelloWorld --constructor-args "Initial greeting message" --legacy;

# [Expected Output]:
# [⠊] Compiling...
# No files changed, compilation skipped
# Deployer: 0x20f33CE90A13a4b5E7697E3544c3083B8F8A51D4
# Deployed to: 0x4d31F9761DEe0132A17794018143360113575cFE
# Transaction hash: 0xf18d36b5aeb9b5acc6711b65944a392fd659f34966156e475c5d15cb733677d9
```

接下来，你应该能在区块浏览器中，看到如下内容：

```bash
# NOTE: The block explorer will take time to index everything so it might not show up right away
open http://127.0.0.1:53414/tx/0xf18d36b5aeb9b5acc6711b65944a392fd659f34966156e475c5d15cb733677d9;
```

#### 第 5 步：读取合约

读取合约，以验证合约是否成功部署，以及初始消息是否已设置。

```bash
cast call 0x4d31F9761DEe0132A17794018143360113575cFE "getGreeting()" --rpc-url http://127.0.0.1:51208 | xxd -r -p;

# [Expected Output]:
# Initial greeting message
```

#### 第 6 步：写入合约

接下来，写入合约，并再次读取更新后的合约消息：

```bash
cast send 0x4d31F9761DEe0132A17794018143360113575cFE "setGreeting(string)" "Hello From Devnet" --rpc-url http://127.0.0.1:51208 --private-key fffdbb37105441e14b0ee6330d855d8504ff39e705c3afa8f859ac9865f99306 --legacy;

# [Expected Output]:
# blockHash               0xa47a10872a0b162d7f95f2339a246b3be2fa0b5df262bc0ccb9ebd50bcc20269
# blockNumber             1783
# contractAddress
# cumulativeGasUsed       29746
# effectiveGasPrice       258831769
# from                    0x20f33CE90A13a4b5E7697E3544c3083B8F8A51D4
# gasUsed                 29746
# logs                    [{"address":"0x4d31f9761dee0132a17794018143360113575cfe","topics":["0xcbc299eeb7a1a982d3674880645107c4fe48c3227163794e48540a7522722354"],"data":"0x00000000000000000000000020f33ce90a13a4b5e7697e3544c3083b8f8a51d40000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001148656c6c6f2046726f6d204465766e6574000000000000000000000000000000","blockHash":"0xa47a10872a0b162d7f95f2339a246b3be2fa0b5df262bc0ccb9ebd50bcc20269","blockNumber":"0x6f7","transactionHash":"0xc7ef2bbd80866be88cbd83abddeeaeab10af5263bc1ef86ce683cafbd52d8a16","transactionIndex":"0x0","logIndex":"0x0","removed":false}]
# logsBloom               0x00000000000000000000000000000000008000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000080000000100040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
# root
# status                  1 (success)
# transactionHash         0xc7ef2bbd80866be88cbd83abddeeaeab10af5263bc1ef86ce683cafbd52d8a16
# transactionIndex        0
# type                    0
# blobGasPrice
# blobGasUsed
# to                      0x4d31F9761DEe0132A17794018143360113575cFE
```

读取更新后的合约消息：

```bash
cast call 0x4d31F9761DEe0132A17794018143360113575cFE "getGreeting()" --rpc-url http://127.0.0.1:51208 | xxd -r -p;

# [Expected Output]:
# Hello From Devnet
```

#### 第 7 步：重置

运行以下代码，可以删除所有服务和清理数据：

```bash
# FROM: ./beacon-kit

# NOTE: These may get stuck - in that case see Debugging Issues below
make stop-devnet;
make rm-devnet;

# [Expected Output]:
# kurtosis enclave stop my-local-devnet
# ...
```

### 故障排除

在MacOS系统中，Docker可能会停止运行。如出现此情况，请尝试运行`kurtosis clean -a`。如问题仍然存在，请尝试删除所有容器，并重启Docker。

```bash
# To remove all docker instances quickly
docker rm -f $(docker ps -aq);

# [Expected Output]:
# 7c1dce7eebfb
# 91bb1725781b
# 41691876aeda
# ...
```




---

[Next Page](/llms-full.txt/1)

