# NEON开发者文档中文版

By [白开水](https://paragraph.com/@baikaishui) · 2022-04-12

---

入门准备
====

_本指南的目的是让您熟悉 Neon EVM 的结构，并提供设置本地 Neon EVM 开发环境的分步说明。_

**设置开发环境**

作为开发人员，您应该首先探索 Neon EVM 框架并设置您的本地开发环境。根据您的目的，有几种方法可以做到：

[🔘 选择 Neon 代理](https://docs.neon-labs.org/docs/developing/dev_environment/choosing_proxy)— 描述如何连接到现有的 Neon 代理。 [🔘 连接到 Neon 代理](https://docs.neon-labs.org/docs/developing/dev_environment/connect_to_solana_via_proxy)— 描述如何通过本地或远程代理服务器连接到 Solana 集群。 [🔘 设置本地 Solana 集群](https://docs.neon-labs.org/docs/developing/dev_environment/solana_cluster/cluster_installation)— 描述如何使用板载 Neon EVM 安装、配置和测试本地 Solana 集群。

**部署dApp**

[🔘 Using Remix](https://docs.neon-labs.org/docs/developing/deploy_facilities/using_remix) — 使用 Remix 部署智能合约的示例。 [🔘 Using Truffle](https://docs.neon-labs.org/docs/developing/deploy_facilities/using_truffle) — 使用 Truffle 部署智能合约的示例。 [🔘 使用 Hardhat](https://docs.neon-labs.org/docs/developing/deploy_facilities/using_hardhat) — 使用 Hardhat 部署智能合约的示例。

**霓虹灯 EVM架构**

[🔘 单一解决方案中的以太坊和 Solana 功能](https://docs.neon-labs.org/docs/architecture/eth_sol_solution)— 描述一个独特的解决方案，允许以太坊用户使用 Solana 的关键功能，反之亦然。 [🔘 Neon EVM 架构概述](https://docs.neon-labs.org/docs/architecture/neon_evm_arch)— 描述 Neon EVM 内置的架构解决方案，可为以太坊用户实现快速交易处理。

**基本主题**

如果您不熟悉 Neon EVM 开发，我们建议您从头开始，然后按顺序学习每个主题。

[🔘 Web2 与 Web3](https://docs.neon-labs.org/docs/architecture/core_aspects/web3) — 描述 Web2 和 Web3 之间的根本区别。 [🔘 以太坊账户](https://docs.neon-labs.org/docs/architecture/core_aspects/account)——一个拥有 ETH 余额的实体，可以在以太坊上发送交易。 [🔘 以太坊交易](https://docs.neon-labs.org/docs/architecture/core_aspects/transaction)——来自账户的加密签名指令。 [🔘 Block](https://docs.neon-labs.org/docs/architecture/core_aspects/block) — 一种用于在区块链系统中记录一组交易的特殊结构。 [🔘 Gas](https://docs.neon-labs.org/docs/architecture/core_aspects/gas) — 以代币表示的计算能力。需要处理交易。

设置开发环境
======

选择霓虹灯代理

_本指南介绍如何选择 Neon 代理向 Solana 发送交易。_

在向 Neon EVM 发送交易之前，用户可以选择最适合他们的运营商来执行交易。运营商不是直接选择的，而是通过他们服务的代理来选择的。

Neon EVM 为用户提供了一个包含所有可用代理的[RPC URL 的](https://docs.neon-labs.org/docs/about/terminology#remote-procedure-call-rpc)[表](https://docs.neon-labs.org/docs/clusters/neon_proxy_rpc_endpoints)，每个代理由一个单独的操作员提供服务。每个 URL 对应于运营商的公钥，他们用它来签署交易并将其发送到 Neon EVM。

代理与一个 EVM 加载器交互，该加载器可以部署在不同的 Solana 链中。这种交互允许代理在不同的网络（Testnet、Devnet、Mainnet Beta）上使用。

> **注意：** 目前，该表仅包含在主网上使用[MVP](https://docs.neon-labs.org/docs/about/terminology#minimum-viable-product-mvp)的代理 URL 列表。随着 Neon EVM 的发展，该表将补充统计指标，评估运营商的服务及其代理的能力。用户将根据这些指标选择运营商。根据运营商提供的资源（代理能力），每个运营商的“gas 价格”会有所不同。因此，交易成本也会有所不同，并取决于从[表中](https://docs.neon-labs.org/docs/clusters/neon_proxy_rpc_endpoints)选择的 RPC URL 。
> 
> \*例如，\*如果交易不需要大量资源，用户可以选择“gas price”最低的 URL，即选择资源有限的代理。用户在进行重要操作时，选择“gas price”较高的 URL 是有意义的，即选择提供最高质量服务的运营商。
> 
> 表格数据将实时提供给用户。

要使用 MetaMask/Truffle 连接到代理，请按照以下说明操作。

**使用MetaMask**

要使用 MetaMask 连接到代理，请按照[安装和设置 MetaMask](https://docs.neon-labs.org/docs/wallet/metamask_setup)的说明进行操作。您需要指定`New RPC URL`从[表](https://docs.neon-labs.org/docs/clusters/neon_proxy_rpc_endpoints)中选择的字段，还需要指定`Chain ID`.

**使用Truffle**

要使用 Truffle 连接到代理，请按照[使用 Truffle](https://docs.neon-labs.org/docs/developing/deploy_facilities/using_truffle)的说明进行操作。您需要`truffle-config.js`通过将 HDWalletProvider 库设置为从[表中](https://docs.neon-labs.org/docs/clusters/neon_proxy_rpc_endpoints)选择的 RPC URL 来进行配置。

**使用安全帽**

要使用 Hardhat 连接到代理，请按照[使用 Hardhat](https://docs.neon-labs.org/docs/developing/deploy_facilities/using_hardhat)的说明进行操作。您需要`hardhat.config.js`通过将 URL、network\_id/chainId 设置为从[table 中](https://docs.neon-labs.org/docs/clusters/neon_proxy_rpc_endpoints)选择的 RPC URL 来进行配置。

连接到 Neon 代理
===========

目标_通过代理服务器连接到 Solana 集群。_

根据要解决的任务以及代理和[Solana](https://docs.solana.com/introduction)的位置，您可以使用以下三个选项之一来配置网络：

*   [选项 1：](https://docs.neon-labs.org/docs/developing/dev_environment/connect_to_solana_via_proxy#option-1-interaction-with-the-solana-cluster-via-a-proxy-hosted-on-a-remote-virtual-server)代理托管在远程虚拟服务器上。使用Solana[测试网](https://docs.solana.com/clusters#testnet)/开[发网](https://docs.solana.com/clusters#devnet)/[主网](https://docs.solana.com/clusters#mainnet-beta)。
    
*   [选项 2：](https://docs.neon-labs.org/docs/developing/dev_environment/connect_to_solana_via_proxy#option-2-running-solana-cluster-via-a-proxy-hosted-locally)代理在本地托管。使用Solana[测试网](https://docs.solana.com/clusters#testnet)/开[发网](https://docs.solana.com/clusters#devnet)/[主网](https://docs.solana.com/clusters#mainnet-beta)。
    
*   [选项 3：](https://docs.neon-labs.org/docs/developing/dev_environment/connect_to_solana_via_proxy#option-3-running-solana-via-a-proxy-when-both-are-hosted-locally)代理和 Solana 都在本地托管。（调试模式，允许您在本地配置节点。）
    

[Testnet](https://docs.solana.com/clusters#testnet)与[Devnet](https://docs.solana.com/clusters#devnet)一样，是专门为开发人员提供的替代加密货币链。它允许开发人员在测试区块链中运行他们的节点并进行实验，而不会损失真实货币。 Mainnet、Testnet 和 Devnet 硬币彼此不兼容。Testnet 和 evnet 币没有价值，开发者不能将 Mainnet 币转移到 Testnet/Devnet。同样，Testnet/Devnet 硬币也不能转移到主网。

**设备要求**

MetaMask 钱包必须安装在您的设备上。

> 虽然本教程使用的是_Ubuntu_平台，但这些说明可以应用于其他 Linux 平台。

**选项 1：通过托管在远程虚拟服务器**

网络配置

*   通过托管在远程虚拟服务器上的代理访问[Solana 集群。](https://docs.solana.com/cluster/overview)
    
*   Solana 在测试模式下工作（推荐），代理通过 Neon EVM 与其交互。
    

**第一步**

打开您的 MetaMask 钱包，然后在右上角单击相同的。 单击`Create Account`下拉菜单并添加一个帐户以与配置的网络进行交互。

**第二步**

在新帐户下打开您的钱包，然后单击`Settings`下拉菜单。 应打开用于选择网络的设置菜单窗口。

**第三步**

单击`Add Network`右上角的 。 要连接到 Solana [Devnet](https://docs.solana.com/clusters#devnet)集群，请填写打开窗口中的字段。例如：

*   `Network Name`：“远程代理 — solana devnet”
    
*   `New RPC URL`：`https://proxy.devnet.neonlabs.org/solana`
    
*   `Chain ID`: 245022926
    
*   `Currency Symbol`: 霓虹灯
    

要连接到 Solana[测试网](https://docs.solana.com/clusters#testnet)集群，请填写必填字段。例如：

*   `Network Name`：“远程代理 — solana 测试网”
    
*   `New RPC URL`：`https://proxy.testnet.neonlabs.org/solana`
    
*   `Chain ID`: 245022940
    
*   `Currency Symbol`: 霓虹灯
    

> \*\*注意：\*\*我们建议您使用 Devnet 而不是 Testnet，因为 Devnet 更稳定可靠。

要连接到 Solana[主网](https://docs.solana.com/clusters#mainnet-beta)集群，请填写以下示例中的字段：

*   `Network Name`：“远程代理 — solana mainnet-beta”
    
*   `New RPC URL`：（将在主网上MVP之后发布）
    
*   `Chain ID`: 245022934
    
*   `Currency Symbol`: 霓虹灯
    

> 只有获得授权的运营商才能将代理连接到主网，因为只有使用运营商的私钥才能通过 Neon EVM 访问任何 Solana 节点。

第四步

填写完字段后，单击`Save`。您现在可以访问[Solana 集群](https://docs.solana.com/clusters)并执行交易。

**选项 2：通过本地**

网络配置

*   通过本地托管的代理访问 Solana 集群。
    
*   使用Solana [Testnet](https://docs.solana.com/clusters#testnet) / [Devnet](https://docs.solana.com/clusters#devnet) / [Mainnet](https://docs.solana.com/clusters#mainnet-beta)，代理通过 Neon EVM 与其交互。
    

**第一步**

Docker 映像本身永远不会“启动”，也永远不会“运行”。Docker 运行命令将 Docker 映像作为模板并从中生成一个容器。在启动代理容器之前，您需要启动服务容器。

确保您有一个守护程序正在运行。如果你看到类似的东西：

    $ docker info
    
    Cannot connect to the Docker daemon at <docker.sock>. Is the docker daemon running?
    

你需要先运行守护进程：

    $ sudo systemctl start docker
    

目前，Neon EVM 代理被硬编码以与 PostgreSQL 一起使用。要将代理连接到数据库，您还需要先启动 PostgreSQL 容器。为了快速启动 PostgreSQL，大部分可配置参数都可以默认保留，除了必须显式设置的密码。要启动 PostgreSQL 容器，可以使用以下命令：

    $ sudo docker run --rm -ti --network=host -e POSTGRES_HOST=localhost -e POSTGRES_DB=neon-db -e POSTGRES_USER=neon-proxy -e POSTGRES_PASSWORD=neon-proxy-pass --name=postgres postgres:14.0
    

如果您想将代理与其他设置一起使用，您需要注册为操作员，以便 Neon EVM 可以识别您的密钥。

> 只有经过授权的操作员才能更改这些参数的设置。

**第二步**

启动代理并将其连接到 Docker 网络：

    $ sudo docker run --rm -ti --network=host -e CONFIG=<network> -e POSTGRES_DB=neon-db -e POSTGRES_USER=neon-proxy -e POSTGRES_PASSWORD=neon-proxy-pass neonlabsorg/proxy:v0.5.1
    

**命令行参数：**

*   `CONFIG=<network>`— 指定 Solana 网络配置；`CONFIG=devnet`被推荐。
    
*   `neonlabsorg/proxy:v0.5.1`— 特定的 Neon EVM 代理。
    

Neon EVM 地址在内部注册`neonlabsorg/proxy:v0.5.1`，因此代理知道 Solana 集群中运行的是哪个 Neon EVM。

执行此命令后，代理将在`http://localhost:9090/solana`. 该地址是默认设置的。

代理根据_SOLANA\_URL_值集连接到公共[Solana 集群 RPC endoint 。](https://docs.solana.com/cluster/rpc-endpoints)下表显示了在指定_CONFIG时自动设置的端点_值。

配置RPC 端点开发网`https://api.devnet.solana.com`测试网`https://api.testnet.solana.com`主网`https://api.mainnet-beta.solana.com`

要使用不同的端点，您需要`-e SOLANA_URL='http://<Solana-node RPC endpoint>'`在命令行上指定变量。

部署代理时，它会生成一个包含密钥对的钱包。如果您不需要新钱包并想使用已有的密钥，则需要在命令行中指定钱包的路径。在这种情况下，代理不会创建新的密钥对。命令行将如下所示：

    $ sudo docker run --rm -ti --network=host -e CONFIG=<network> -e POSTGRES_DB=neon-db -e POSTGRES_USER=neon-proxy -e POSTGRES_PASSWORD=neon-proxy-pass -v ~/.config/solana/id.json:/root/.config/solana/id.json --name proxy neonlabsorg/proxy:v0.5.1
    

**命令行选项：**

*   `~/.config/solana/id.json`— 密钥对的路径。
    
*   `--name proxy`— 指定代理名称。
    

如果您没有注册为操作员，则只能使用测试公钥。（表中给出了可用公钥的[列表](https://docs.neon-labs.org/docs/clusters/neon_proxy_rpc_endpoints)。）您不需要通过 -v 标志指定密钥，因为它已经在 Devnet/Testnet 容器中进行了硬编码。使用以下命令：

    sudo docker run --rm -ti --network=host -e CONFIG=<network> -e POSTGRES_DB=neon-db -e POSTGRES_USER=neon-proxy -e POSTGRES_PASSWORD=neon-proxy-pass neonlabsorg/proxy:v0.5.1
    

选项 3：当两者都在本地
------------

此选项对于希望通过在本地托管代理和 Solana 节点来调试其 Solidity 合约的开发人员非常有用。

网络配置

*   Solana 节点和代理都在本地托管。
    
*   代理通过 Neon EVM 与 Solana 节点交互。
    

使用以下命令将 docker-compose-test.yml 文件上传到您当前的目录：

    $ wget https://raw.githubusercontent.com/neonlabsorg/proxy-model.py/master/proxy/docker-compose-test.yml
    

执行命令：

    $ sudo REVISION=stable docker-compose -f docker-compose-test.yml up -d
    

最新命令完成后，代理将开始在本地 Solana 节点中部署 Neon EVM。之后，代理和 Solana 将分别在 URL`http://localhost:9090/solana`和上可用`http://localhost:8899`。

* * *

> **注意：** 作为代理，您可以使用专用的 Neon 服务器，或需要部署和登录的单独服务器。
> 
> 作为 Solana 端点，您可以使用托管在 Devnet 或 Testnet 上的单独节点。
> 
> 您还可以使用未托管在任何网络上的 Solana 节点。在这种情况下，您需要配置此节点并将其与 Devnet 或 Testnet 网络同步。然后，您将需要部署本地代理并将其配置为与该节点一起使用。您还需要连接到部署在 Devnet 或 Testnet 中的 EVM 加载程序。

设置本地 Neon EVM 环境
================

_本分步指南介绍了如何使用板载 Neon EVM 安装、配置和测试本地 Solana 集群。它将帮助新开发人员创建自己的环境并运行封装在 Neon EVM 中的以太坊程序。_

[Neon EVM](https://neon-labs.org/)是一种在第1 层之外执行事务执行的解决方案。开发过程可以在任何现代 Linux 或 Mac 系统上运行，尽管本文档基于 Ubuntu 20.04 体验。

docker-compose 配置文件中提供的所有服务`Neon EVM environment`都可以替换为它们的实验版本，以便独立开发和测试每个服务。为了解决问题，Neon 工程师必须能够根据当前要求将任何服务替换为定制服务。欢迎您根据需要更改以下`docker-compose`配置文件。此外，您可以将它们完全放在一个 docker-compose 文件中，根据以下顺序提供依赖项很重要。

在开始构建本地环境之前，请确保您具备所有[先决条件](https://docs.neon-labs.org/docs/developing/dev_environment/solana_cluster/cluster_installation#prerequisites)。

在开始构建本地环境之前，请确保您具备所有[先决条件](https://docs.neon-labs.org/docs/developing/dev_environment/solana_cluster/cluster_installation#prerequisites)。

**先决条件**

*   **Docker** — 对于 docker 安装，请按照以下说明操作：[https ://docs.docker.com/engine/install/ubuntu/](https://docs.docker.com/engine/install/ubuntu/)
    
*   **Docker Compose** — Docker Compose 需要在以下位置启动容器：[https ://docs.docker.com/compose/install/](https://docs.docker.com/compose/install/)
    
*   **Solana Tool Suite** — 为了与 Solana 交互，我们需要安装 Solana CLI Tools：[https ://docs.solana.com/ru/cli/install-solana-cli-tools](https://docs.solana.com/ru/cli/install-solana-cli-tools)
    
*   基于 Chromium 的**浏览器**——用于[MetaMask](https://metamask.io/)和[Remix](https://remix.ethereum.org/)
    
*   **节点包管理器**— [Node.js/npm](https://www.w3schools.com/nodejs/nodejs_npm.asp)与带有[Web3](https://www.npmjs.com/package/web3)和[Eth](https://www.npmjs.com/package/web3-eth)模块的 Neon EVM 交互。
    

**设置 Neon 本地工作区环境**

目前，最灵活的方式是使用一组独立的 docker 容器共享公共的外部网络。要创建将在 docker 容器上使用的网络调用`local`，只需输入以下命令：

    docker network create local
    

如果您想将服务中的某些端口绑定到主机以能够连接它们并独立使用服务，只需使用指令扩展`docker-compose.yml`配置即可。`ports`例如，您可以通过这种方式将 Solana（8899、8900）或代理（9090）相关端口绑定到主机。

建立本地网络后，是时候启动以下容器了：

建立本地网络后，是时候启动以下容器了：

1.  Solana 验证人服务
    
2.  EVM加载器服务
    
3.  数据库服务
    
4.  索引器服务
    
5.  代理服务
    
6.  水龙头服务
    
7.  完整的测试套件服务
    

完成上述步骤后，您将拥有四个用于 Neon EVM 本地环境的运行容器：**solana**、`postgres`、`proxy`、`indexer`：

    49c864f47ccd   neonlabsorg/solana:v1.9.12-testnet   "./run.sh"               About an hour ago   Up About an hour (healthy)   8003/udp, 0.0.0.0:8899-8900->8899-8900/tcp, :::8899-8900->8899-8900/tcp, 9900/tcp   solana
    92f6b4492894   neonlabsorg/proxy:latest             "./proxy/run-proxy.sh"   46 hours ago        Up About an hour             0.0.0.0:9090->9090/tcp, :::9090->9090/tcp                                           proxy
    932d4d860629   neonlabsorg/proxy:latest             "proxy/run-indexer.sh"   46 hours ago        Up About an hour             9090/tcp                                                                            indexer
    5a7df37069fc   postgres:14.0                        "docker-entrypoint.s…"   47 hours ago        Up About an hour (healthy)   127.0.0.1:5432->5432/tcp                                                            postgres
    

要查找事件或错误，只需`docker logs`为`solana`or`proxy`容器运行：

    $ docker logs -f solana 2>&1 | grep -v "Program Vote111111111111111111111111111111111111111"
    $ docker logs -f proxy
    

使用 Neon EVM
-----------

设置“MetaMask”Chromium 扩展以通过自定义 RPC 连接到代理`http://localhost:9090/solana`。下图描述了如何设置本地 Solana 连接：

![](https://storage.googleapis.com/papyrus_images/2319e71098cd92e484e614df23e613858d211832631e316560a50c6177995fe0.png)

注意：在 MetaMask 中创建或导入新帐户后，一些 NEON 将被空投到其中。

打开 Remix（也在 Chromium 中）并选择`Injected Web3`环境。您可以在 Solana 上部署 EVM 包装的智能合约并输入以下指令：

![](https://storage.googleapis.com/papyrus_images/bcf9b3a659629f92955149264515309bf5784611bb001440d9d740a0a99bc2e8.png)

**带有 Neon EVM**

Truffle 是部署和测试 Solidity 程序的流行平台。本节向您展示如何检查 Neon EVM 和 Truffle 套件的兼容性。

在新终端中，创建一个 Truffle 项目并将合约部署到 EVM：

    $ sudo npm install -g truffle
    $ mkdir myproject && cd myproject
    $ truffle init
    $ npm install web3 @truffle/hdwallet-provider
    

### 常见松露设置

将您的`truffle-config.js`放入松露根：

    $ echo 'const Web3 = require("web3");
    
    const Web3eth = require("web3-eth");
    const HDWalletProvider = require("@truffle/hdwallet-provider");
    
    const web3eth = new Web3eth();
    const accs = Array.from(Array(10), (_, x) => web3eth.accounts.create());
    const privateKeys = accs.map((account) => account.privateKey);
    
    module.exports = {
      networks: {
        solana: {
          provider: new HDWalletProvider(privateKeys, "http://127.0.0.1:9090/solana"),
          from: accs[0].publicKey,
          network_id: "111",
          gas: 3000000,
          gasPrice: 1000000000,
        }
      },
    
      compilers: {
        solc: {
          version: "0.8.9"
        }
      }
    };' > truffle-config.js
    

**合同创建**

在以下位置创建一个简单的合同`contracts/Storage.sol`：

    $ echo '// SPDX-License-Identifier: GPL-3.0
    
    pragma solidity >=0.7.0 <0.9.0;
    
    contract Storage {
        uint256 number;
    
        function put(uint256 num) public {
            number = num;
        }
    
        function get() public view returns (uint256) {
            return number;
        }
    }' > contracts/Storage.sol
    

**测试**

您现在可以开始`Storage`使用 Truffle 工具测试调用：

    $ echo 'const Storage = artifacts.require("Storage");
    
    contract("Storage", (accounts) => {
        let storage;
    
        beforeEach(async () => {
            storage = await Storage.new();
        });
    
        it("should store a value", async () => {
            const setResult = await storage.put(248);
            assert.equal(setResult.receipt.status, true);
            const value = await storage.get();
            assert.equal(value, 248);
        })
    })' > test/Storage.test.js
    
    $ truffle test test/Storage.test.js --network solana
    

**可能出现的问题**

如果由于某些原因您删除了 Solana 容器并再次运行它，那么存储在外部系统中的所有相关帐户从那一刻起都将失效。这就是为什么您需要重新运行代理容器并重置 MetaMask 和 Truffle 的状态，以使所有关系保持一致。

要重置 MetaMask 状态，请按照`Settings`、`Advanced`、处的步骤操作`Reset Account`。

可以通过以下方式重新部署 Truffle 状态：

    $ truffle compile --network solana --reset
    

* * *

[_在Solana_](https://solana.com/)_驱动的_[_Neon EVM_](https://neon-labs.org/)_上部署您的 Solidity 程序_。

部署dApp
------

**使用混音**

_本教程将逐步向您展示如何使用_[_Remix_](https://docs.neon-labs.org/docs/about/terminology#remix)_和_[_MetaMask_](https://docs.neon-labs.org/docs/about/terminology#metamask)_在 Solana 上创建和部署一个简单的智能合约。虽然说明使用了 Solana 的_[_Testnet_](https://docs.solana.com/clusters#testnet)_，但它们也可能适用于 Solana 的_[_Devnet_](https://docs.solana.com/clusters#devnet)_或 Solana 的_[_Mainnet Beta_](https://docs.solana.com/clusters#mainnet-beta)_。_

**要求**

在开始之前，请确保以下内容：

*   MetaMask 已安装在您的设备上。
    
*   您已提供对 remix.ethereum.org 的在线访问以使用`Remix - Ethereum IDE`开源 Web 应用程序。
    
*   MetaMask 为代理和 Neon EVM 配置。（无论代理和 Neon EVM 如何运行，必须始终为它们配置 MetaMask 钱包。）
    

**网络配置：**

*   [Solana 集群](https://docs.solana.com/clusters)通过代理访问。
    
*   Solana 在测试模式下工作，代理通过 Neon EVM 与其交互。
    

**完成步骤**

**Step 1. 设置混音环境**

要使用 Remix 将智能合约加载到 Neon EVM 中，Remix 必须连接到您的 MetaMask 钱包并在`Injected Web3`环境中运行。 转到[http://remix.ethereum.org/](http://remix.ethereum.org/)并打开`Remix - Ethereum IDE`Web 应用程序。在左侧菜单中，选择`File explorers`。菜单将`FILE EXPLOPERS`处于活动状态（图 1）。

![图 1 - 连接到 localhost](https://storage.googleapis.com/papyrus_images/8887ce3347c87244e50be0027735b92d4cc6e9b0c752d24246c3c9fc76853610.png)

图 1 - 连接到 localhost

**步骤 2. 在Remix**

单击该图标`Create New File`并在其下方显示的字段中键入文件名。例如，helloWorld.sol 目前是一个空文件。要填充内容，请单击创建的文件名并在资源管理器右侧键入文本（或复制您预先准备的文本）（图 2）

![图 2 — 加载 helloWorld 智能合约](https://storage.googleapis.com/papyrus_images/5430668579a44f7c11a910410defa4cbc40d4dd29f14bdfdd1c430c057150a3f.png)

图 2 — 加载 helloWorld 智能合约

**步骤 3. 编译智能合约**

在左侧菜单中，选择`Solidity compiler`. `SOLIDITY COMPILER`菜单将处于活动状态。 点击`Compile helloWorld.sol`按钮编译加载的智能合约helloWorld（图3）

![图 3 — 编译 helloWorld 智能合约](https://storage.googleapis.com/papyrus_images/60a50583e02b02184bbd3bc07c1b77dea1735812b6ae8a27863efb18f63c9566.png)

图 3 — 编译 helloWorld 智能合约

如果编译成功，按钮附近会出现一个绿色图标`Solidity compiler`。 您还可以通过单击`Compilation Details`（图 4）获取有关编译过程的详细信息。

![图 4 - 编译细节](https://storage.googleapis.com/papyrus_images/d8d296b42ad1b742468bac21ac12f3271d54b8817384b6cdb244ee48fd2819db.png)

图 4 - 编译细节

**步骤 4. 将 Remix 连接到MetaMask**

与 Neon EVM 的交互是通过 MetaMask 进行的。选择`Injected Web3`环境以将 Remix 与 Metamask 中的活动帐户连接起来（图 5）

![图 5 — 注入的 Web3 将 Remix 与 Metamask 中的活动帐户连接起来](https://storage.googleapis.com/papyrus_images/e267b0798ea93778dbd3e5f4c0267ac36e11e7abe7fcec96f2123dc8adab8ae5.png)

图 5 — 注入的 Web3 将 Remix 与 Metamask 中的活动帐户连接起来

MetaMask 窗口应该出现。它应该显示可用帐户的列表。（在我们的例子中，只会显示一个帐户。）选择此帐户并单击`Next`（图 6）

![图 6 - 选择一个帐户与 Remix 交互](https://storage.googleapis.com/papyrus_images/f89a35499c7d92b0e5cd1cd5a67f2c3bd310764b99686001f28a64f9386a37d9.png)

图 6 - 选择一个帐户与 Remix 交互

单击`Connect`以连接到此帐户（图 7）

![图7](https://storage.googleapis.com/papyrus_images/4c86bd25186c75812a88f6b0ff4ae61662712418b4aabbf9bcd14209ad20fb5f.png)

图7

**步骤 5. 在Solana 测试网**

在左侧菜单中，选择`Deploy & run transactions`。`DEPLOY & RUN TRANSACTIONS`菜单将变为活动状态 。

在我们的例子中，只有一个智能合约要部署，因此它会自动从下拉列表中选择，Remix 将自动生成一笔交易。

该`Account`字段将显示钱包账户中的金额。该数据取自 MetaMask。

单击`Deploy`（图 8）

![图 8 — 部署智能合约](https://storage.googleapis.com/papyrus_images/ea43bd3e812074e428475f4843cdd178a3b1b8b8b11e893b278fa6923836b7ea.png)

图 8 — 部署智能合约

MetaMask 会以弹窗的形式发送通知以确认交易。单击`Confirm`（图 9）

![图 9 — MetaMask 通知](https://storage.googleapis.com/papyrus_images/016c217948b999f1c3ab0a69263caeb0f9c484748122dd29b50664958700df09.png)

图 9 — MetaMask 通知

确认交易后，您可以在右下角的消息中查看（图 10）

![图 10](https://storage.googleapis.com/papyrus_images/2c18ea343de0230fb4d4ae37a9b1e2d8572367a7750a0333ed53ccb2eee8c28e.png)

图 10

成功部署智能合约后，您将看到一条消息，其中包含上传智能合约的名称和地址（图 11）

![图 11 - 部署的智能合约数据](https://storage.googleapis.com/papyrus_images/32660c84afbc4a8757aa9491d9683567fe5ccc6d074332abf8a719dbdcd01fbc.png)

图 11 - 部署的智能合约数据

如果所有步骤都已成功完成，按钮附近将出现一个绿色图标`Deploy & run transactions`（图 12）

![图 12 - Remix 面板的最终视图](https://storage.googleapis.com/papyrus_images/34a2c3fbaa6d45aa5032d366566a556f2e8084025d3feaa5c2e020bb23746208.png)

图 12 - Remix 面板的最终视图

恭喜！您现在可以调用部署在 Solana 网络上的 helloWorld 智能合约的方法。（图 13 显示了您的智能合约的结果——文本字符串“Hello World！”）

![图 13 — 调用智能合约方法](https://storage.googleapis.com/papyrus_images/e0fc790e8dfa563e419981285075256eb283cf21aaa987f98d5d662ed38512ac.png)

图 13 — 调用智能合约方法

> **有用的链接** [https://ethereum.org/en/developers/tutorials/deploying-your-first-smart-contract/](https://ethereum.org/en/developers/tutorials/deploying-your-first-smart-contract/)

使用松露
====

_本页概述了使用 Truffle 工具在 Neon EVM 中部署和测试合约的方法。该技术对于参与 Neon EVM 开发和维护的人员非常有用。_

需要注意的是，以太坊合约也可以通过手动模式使用 Remix 成功部署在 Neon EVM 中。然而，由于 Remix 没有那么多功能，结果证明它不方便软件开发，因此我们希望为开发人员提供使用 Truffle 的更高级的方法。

**目标**

我们使用 Truffle 的主要目标是让开发人员更容易在 Neon EVM 中部署和调试合约。

使用松露，您可以获得：

*   配置参数的简单设置。
    
*   在网络中部署和调试合约的简单过程。
    
*   自动部署和运行测试。
    

**安装**

**设备要求**

您的设备上必须安装以下软件：

*   NodeJS v8.9.4 或更高版本
    
*   Web3 v1.2.0 或更高版本
    

> \*\*注意：\*\*虽然本教程使用的是 Ubuntu 平台，但提供的说明可以应用于其他 Linux 平台。

**安装松露**

如果您的设备上已经安装了 Truffle，您可以跳过此部分并继续下一个部分。对于刚入门的人，您需要阅读本节。

> \*\*注意：\*_此页面只是一个快速入门。要了解更多详细信息，您可以阅读_[Truffle 文档](https://www.trufflesuite.com/docs/truffle/getting-started/installation)\*。

为您的 Truffle 项目创建一个新目录：

    $ mkdir <project name>
    $ cd <project name>
    

安装松露：

    $ npm install truffle
    

通过运行以下命令初始化项目目录：

    $ truffle init
    

完成此操作后，您将拥有一个包含以下项目的项目结构：

*   `contracts/`— Solidity 合约目录
    
*   `migrations/`— 可编写脚本的部署文件目录
    
*   `test/`— 用于测试合约的测试文件目录
    
*   `truffle-config.js`— 松露配置文件
    

你可以运行`truffle compile`和`truffle migrate`来`truffle test`编译你的合约，将它们部署到网络，并运行它们相关的单元测试。

**安装 HDWalletProvider库**

支持 HD Wallet 的 Web3 提供程序 (HDWalletProvider) 是一个独立的库。它的功能之一是使用私钥签署交易。由于 Neon EVM 代理不存储私钥，因此无法签署交易。因此，在调试合约期间，HDWalletProvider 库用于对源自_12_或_24_字助记符的地址的交易进行签名。

默认情况下，Truffle 安装不提供 HDWalletProvider 库。如果在安装 Truffle 期间没有应用程序需要安装 HDWalletProvider 库，则需要单独安装它。

安装 HDWalletProvider 库：

    $ npm install @truffle/hdwallet-provider
    

> \*\*注意：\*_这里要详细介绍，可以查看_[官方文档](https://www.npmjs.com/package/@truffle/hdwallet-provider)\*。

**将 Truffle 连接到代理**

要将 Truffle 连接到 上的代理`node.js`，需要使用[Ethereum JSON RPC API](https://eth.wiki/json-rpc/API)`eth_accounts`集中的方法。此方法允许提供客户端拥有的\*20字节地址列表。\*由于 Neon EVM 代理不支持连接 Truffle 所需的方法，因此使用 HDWalletProvider 库作为此方法。连接配置在.`eth_accountstruffle-config.js`

配置文件是公开可用的，因此文件中包含的`word mnemonic`和`private key`也是公开可用的。这使得图书馆可以使用这些数据。HDWalletProvider 从配置文件中获取`word mnemonic`或`private key`从配置文件中获取，并在将交易发送到代理之前使用此数据对交易进行签名。

这种配置方式方便调试模式，但不适合实际工作。由于开发过程使用“测试”钱包，因此这些数据没有任何价值。

> \*\*注意：\*\*我们强烈建议仅在 Neon EVM 中使用 Truffle 来开发或测试合约。

**配置**

您的配置文件被调用`truffle-config.js`并位于项目目录的根目录中。该文件是一个 JavaScript 文件，可以执行创建配置所需的任何代码。

**编制合同**

您的所有合同都位于您的项目`contracts/`目录中。要编译 Truffle 项目，请切换到项目所在目录的根目录并运行以下命令：

    $ truffle compile
    

首次运行时，将编译所有合约。在随后的运行中，只有自上次编译后发生变化的合约才会被再次编译。

如果要重新编译所有合约，请使用以下`--all`选项运行上述命令：

    $ truffle compile --all
    

**运行迁移**

迁移用于将您的合约部署到网络。此操作使用目录中包含的 JavaScript 文件执行`migration/`。迁移只是一组托管部署脚本。

运行迁移以部署合约：

    $ truffle migrate
    

这将运行位于`migrations/`目录中的所有迁移。如果您的迁移之前已成功运行，则 truffle migrate 将从上次运行的迁移开始执行，仅运行新创建的迁移。如果不存在新的迁移，则 truffle migrate 不会执行任何操作。

如果您需要从头开始运行所有迁移，而不是从上次完成的迁移运行，您可以使用以下`--reset`选项：

    $ truffle migrate --reset
    

您可以在运行迁移期间使用的全套选项列在带有[truffle migrate](https://www.trufflesuite.com/docs/truffle/reference/truffle-commands#migrate)命令的页面中。

**测试合约**

所有测试文件都应位于该`test/`目录中。

要默认运行所有测试，只需运行：

    $ truffle test
    

要仅运行整个测试套件中的一个文件或不在 中的特定文件`test/`，您需要指定该文件的全名：

    $ truffle test <./path/file.js>
    

您可以在测试期间使用的全套选项与[truffle test](https://www.trufflesuite.com/docs/truffle/reference/truffle-commands#test)命令一起列在页面中。

**配置文件设置**

使用 Node.js 上的单向库将 Truffle 连接到 devnet-proxy 的配置文件示例：

    const Web3 = require("web3");
    const HDWalletProvider = require("@truffle/hdwallet-provider");
    
    Web3.providers.HttpProvider.prototype.sendAsync = Web3.providers.HttpProvider.prototype.send
    
    const provider = new Web3.providers.HttpProvider("https://proxy.devnet.neonlabs.org/solana");
    
    const privateKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Specify your private key here
    
    module.exports = {
      networks: {
        neonlabs: {
          provider: () => {
            return new HDWalletProvider(
              privateKey,
              provider,
            );
          },
          from: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx", // Specify public key corresponding to private key defined above
          network_id: "*",
          gas: 3000000000,
          gasPrice: 443065000000,
        }
      }
    };
    

> \*\*注意：\*\*如果助记词和私钥都提供，则使用助记词。

使用下一个命令使用**neonlabs**网络部署合约：

    truffle migrate --network neonlabs
    

**示例项目**

您可以从此处获取示例 Truffle 项目：[https ://github.com/neonlabsorg/examples/tree/main/simple-erc20-truffle](https://github.com/neonlabsorg/examples/tree/main/simple-erc20-truffle)

使用安全帽
=====

Hardhat 是一个用于编译、部署、测试和调试以太坊软件的开发环境。它可以帮助开发人员管理和自动化构建智能合约和 dApp 的过程中固有的重复任务，并围绕此工作流程轻松引入更多功能。这意味着在核心上编译、运行和测试智能合约。

我们不会在这里描述使用 Hardhat 框架的细节。您可以通过以下链接找到所有必要的文档：[https](https://hardhat.org/getting-started/#overview) ://hardhat.org/getting-started/#overview 。

由于 Neon 是与 Ethereum 兼容的虚拟机和 RPC，您可以轻松地将现有的 Hardhat 项目迁移到它。唯一需要的是正确的**hardhat.config.js**文件。您可以参考以下代码作为配置文件内容的示例：

    require("@nomiclabs/hardhat-waffle");
    
    const proxy_url = 'https://proxy.devnet.neonlabs.org/solana';
    const network_id = 245022926;
    const deployerPrivateKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'; // place your private key here (note that wallet must have non-zero balance of NEONs to pay fees)
    
    module.exports = {
      solidity: "0.8.4",
      defaultNetwork: 'neonlabs',
      networks: {
        neonlabs: {
          url: proxy_url,
          accounts: [deployerPrivateKey],
          network_id: network_id,
          chainId: network_id,
          gas: 3000000,
          gasPrice: 1000000000,
          blockGasLimit: 10000000,
          allowUnlimitedContractSize: false,
          timeout: 1000000,
          isFork: true
        }
      }
    };
    

**安全帽项目**

您可以从此处获取示例 Hardhat 项目：[https](https://github.com/neonlabsorg/examples/tree/main/simple-erc20-hardhat) ://github.com/neonlabsorg/examples/tree/main/simple-erc20-hardhat

将 dApp 迁移到 Neon EVM
===================

_本文档的目的是向以太坊用户展示他们的 dApp 可以多么容易地移植到 Neon EVM。以_[_Neon Swap_](https://docs.neon-labs.org/docs/about/terminology#neonswap)_为例，我们将向您展示如何在_[_Solana_](https://docs.solana.com/introduction)_上运行 dApp，而无需更改任何软件代码。_

每个 dApp 都包含一个合同和支持该合同的软件。在 Neon EVM 中，所有 dApp 都通过 Neon 代理部署。部署 dApp 需要向代理发送请求，代理会自动在 Neon EVM 环境中部署 dApp 的合约。合约被加载到链中，软件部署在单独的服务器上，为用户提供与这些合约的交互。

在本描述中，我们将向您展示如何将 Uniswap 服务移植到 Neon EVM 环境。由于我们没有 Uniswap 的本地密钥，我们将使用 Uniswap-V2 的一个分支，称为[NeonSwap](https://docs.neon-labs.org/docs/about/terminology#neonswap)。

将 dApp 迁移到 Neon EVM 分三个阶段完成： **第 1 阶段**\- 在 Neon EVM 环境中部署合约  
**第 2 阶段**\- 检查部署的合约是否正常工作 **第 3 阶段**\- 部署合约接口

**阶段 1. 在 Neon EVM环境**

以[NeonSwap](https://docs.neon-labs.org/docs/about/terminology#neonswap)为例，我们可以证明移植 dApp 不需要更改软件服务合约。仅对在 Neon EVM 上运行所需的组件进行更改。

这些合约由以太坊中使用的典型 Solidity 编译器构建。编译后，所有必要的合约都使用[Web3](https://docs.neon-labs.org/docs/about/terminology#web-3)代理部署在 Neon EVM 上。该代理提供了以太坊实用程序和工具可以使用的标准接口。

例如，Uniswap 包括以下需要部署的合约列表：

*   治理
    
*   Uniswap-v2-外设
    
*   多路通话
    

**部署合约**

在 Neon EVM 合约中部署 Uniswap 时，我们对其进行了以下更改：

*   超时值增加。
    
*   交易配方的重复请求数量增加：
    

    // The call  
        wait factoryV1.createExchange(WETHPartner.address, overrides)
    // was replaced with  
        let id = await factoryV1.createExchange(WETHPartner.address, overrides) let receipt = await provider.waitForTransaction(id.hash, 3)
    

*   添加了`deploy contracts()`方法。
    

由于我们没有 Uniswap 的本地密钥，我们不得不更改以下上传合约的地址：

*   UNI\_ADDRESS
    
*   TIMELOCK\_ADDRESS
    
*   治理\_地址
    
*   MULTICALL\_ADDRESS
    
*   MIGRATOR\_ADDRESS
    
*   FACTORY\_ADDRESS
    
*   ROUTER1\_ADDRESS
    
*   ROUTER\_ADDRESS
    
*   V1\_FACTORY\_ADDRESS
    
*   WETH\_ADDRESS
    

**阶段 2. 检查部署的合约是否正常**

合约健康检查在真正的链中执行，而不是在完全托管的测试环境中执行。

与测试环境不同，在真实的工作链中，测试操作的范围不能全部执行。（例如，不包括生成具有指定交易数量的块等操作。）在一条链中，所有操作都依赖于实时，用户检查合约不能影响块的生成。

为了测试[NeonSwap](https://docs.neon-labs.org/docs/about/terminology#neonswap)，我们使用其存储库中可用的整套 Uniswap-v2-core 测试在以太坊上进行测试。运行这些测试的方法已更改。在运行测试之前，表明合约的部署、对其方法的调用以及测试不是在测试框架中进行，而是在真正的区块链中进行。

> 对于测试，我们使用非托管环境。但是，在 Uniswap-v2-core 测试中（在合约中），有部分程序代码包含环境管理。在这些作品中，我们能够成功地将环境管理替换为对连锁反应的期望。也就是说，在要生成块的地方设置延迟。然后执行一个动作并评估合约的反应；即是否符合预期。同时，我们认为出块的数量可能会有所不同。

调整测试的需要是因为无论运行条件如何，测试都必须发出正确的结果。

**运行 Uniswap-v2-core 测试套件**

为了在 Neon EVM 中运行 Uniswap-v2-core 测试套件，进行了以下更改：

*   扩展合同时增加超时
    
*   更改了 ChainId
    
*   替换了 rcp-request 库，包括以下内容：`Web3Provider`并`MockProvider`替换为`JsonRpcProvider`
    
*   `mineBlock()`使用方法更改测试
    
*   增加了在库中重新请求`ethereum-waffle`接收交易收据的次数，包括以下内容：
    

    // In the file  
    uniswap-v2-core/node_modules/@ethereum-waffle/chai/dist/cjs/matchers/emit.js  
    // the line  
    const derivedPromise = promise.then((tx) => contract.provider.getTransactionReceipt(tx.hash) ).then((receipt) => {  
    // was replaced with  
    const derivedPromise = promise.then((tx) => contract.provider.waitForTransaction(tx.hash, 3) ).then((receipt) => {  
    

*   增加了`gasLimit`在`ethereum-waffle`图书馆的价值。
    

**第 3 阶段。部署 Uniswap接口**

在我们将合约地址加载到 Neon EVM 后，我们就可以开始部署 Uniswap 接口了。有必要指定我们使用真正的区块链，并且我们的合约位于该区块链中。

使用实用应用程序
========

### NeonSwap界面

为了在 Neon EVM 中成功[运行 NeonSwap](https://docs.neon-labs.org/docs/about/terminology#neonswap)接口，我们进行了以下更改：

*   为适应的 NeonSwap 接口代码添加了新的测试网。具有新链 ID 的新网络的名称已在所有使用它的地方注册：
    
    *   添加`ChainId LOCAL`到依赖库和源。
        
    *   ChainID, url 在 .env 文件中指定。
        
*   对于新网络，注册了一组加载的合约。在目录`node_modules`中，替换了源库和依赖库中的合约地址。
    

* * *

> **更多详细信息 有关** 使用 NeonSwap 的快速指南，请参阅[如何交换 ERC-20 代币](https://docs.neon-labs.org/docs/developing/utilities/neonswap)。
> 
> 我们为将 Uniswap 服务移植到 Neon EVM 所做的所有更改都可以在[Uniswap-v2-core 存储库](https://github.com/neonlabsorg/uniswap-v2-core)中找到。

**与 SPL 令牌交互**

ERC-20 SPL 包装合约通过 ERC-20 接口提供对在 SPL 代币合约中注册的原生 Solana 代币的访问。

这允许 Solana 应用程序与 EVM（Solidity、Vyper 等）字节码合约进行交互。ERC-20 SPL 包装器还可用于使用 MetaMask 等以太坊钱包以 Solana 代币转移资金。

该合约作为 Neon EVM 程序的一部分在 Rust 中实现。

源代码：

*   [锈源代码](https://github.com/neonlabsorg/neon-evm/blob/c43345d7abf7af14aa840e6b15c0fc64b084bb2c/evm_loader/program/src/precompile_contracts.rs#L106)
    
*   [Solidity 包装器源代码](https://github.com/neonlabsorg/neon-evm/blob/develop/evm_loader/solidity/erc20_wrapper.sol)
    

**合约接口**

    interface IERC20 {
        function decimals() external view returns (uint8);
        function totalSupply() external view returns (uint256);
        function balanceOf(address who) external view returns (uint256);
        function allowance(address ow ERC-20 SPL-Wrapperer, address spender) external view returns (uint256);
        function transfer(address to, uint256 value) external returns (bool);
        function approve(address spender, uint256 value) external returns (bool);
        function transferFrom(address from, address to, uint256 value) external returns (bool);
    
        event Transfer(address indexed from, address indexed to, uint256 value);
        event Approval(address indexed owner, address indexed spender, uint256 value);
    
        function approveSolana(bytes32 spender, uint64 value) external returns (bool);
        event ApprovalSolana(address indexed owner, bytes32 indexed spender, uint64 value);
    }
    

接口模块的功能：

*   `decimals()`— 返回用于获取其用户表示的小数位数。例如，如果`decimals`等于 2，则应向用户显示 505 个代币的余额为 5,05 (505 / 10 \* 2)。
    
*   `totalSupply()`— 返回存在的代币数量。
    
*   `balanceOf(address account)`— 返回 拥有的代币数量`account`。
    
*   `allowance(address owner, address spender)spender`— 返回允许a代表`owner`通过`​​​​​​​transferFrom`的剩余代币数量 默认情况下为零。
    
*   `transfer(address recipient, uint256 amount)`— 将指定`amount`的令牌从调用者的账户余额发送到`recipient's`账户余额。
    
*   `approve(address spender, uint256 amount)`— 将 a 设置`amount`为花费者对调用者代币的津贴。
    
*   `transferFrom(address sender, address recipient, uint256 amount)`— 将`amount`的令牌从转移`sender`到`recipient`。
    
*   `approveSolana(bytes32 spender, uint64 value)`— 允许**_Solana_**用户`spender`多次从调用者的帐户中提款，最多可达`value`金额。当时只有一个 Solana`spender`可以存在。转换为 SPL 令牌`Approve`指令。
    

**限制条件**

根据 SPL 代币结构，u64 用于存储余额。（在 ERC-20 中，它是 u256）。基于 u64，最大余额和转账金额受 (2^64-1)/(10^9) 限制（精确到小数点后 9 位）。

**查找代币账户地址**

给定钱包地址的代币账户是一个程序派生账户，由以下常量组成：以太坊钱包地址本身、ERC-20 合约地址和代币铸币厂。

账户地址可以在 Rust 中通过以下方式派生：

    const ACCOUNT_SEED_VERSION: u8 = 1;
    
    fn token_address(owner: &H160, contract: &H160, mint: &Pubkey, neon_evm: &Pubkey) {
        let seeds: &[&[u8]] = &[&[ACCOUNT_SEED_VERSION], b"ERC20Balance", &mint.to_bytes(), contract.as_bytes(), owner.as_bytes()];
        Pubkey::find_program_address(seeds, neon_evm)
    }
    

**创建代币账户**

账户持有代币余额并使用`ERC20CreateTokenAccount`指令创建。

这条指令可以在 Rust 中创建：

    fn create_token_account(funding: Pubkey, owner: H160, contract: H160, mint: Pubkey, neon_evm: Pubkey) {
        let (token_address, _) = token_address(&owner, &contract, &mint, &neon_evm);
        let (wallet_address, _) = Pubkey::find_program_address(&[&[ACCOUNT_SEED_VERSION], owner.as_bytes()], &neon_evm);
        let (contract_address, _) = Pubkey::find_program_address(&[&[ACCOUNT_SEED_VERSION], contract.as_bytes()], &neon_evm);
    
        Instruction::new_with_bincode(
            neon_evm,
            &(15_u8),
            vec![
                AccountMeta::new(funding, true),
                AccountMeta::new(token_address, false),
                AccountMeta::new_readonly(wallet_address, false),
                AccountMeta::new_readonly(contract_address, false),
                AccountMeta::new_readonly(mint, false),
                AccountMeta::new_readonly(system_program::id(), false),
                AccountMeta::new_readonly(spl_token::id(), false),
                AccountMeta::new_readonly(sysvar::rent::id(), false)
            ]
        )
    }
    

**使用 ERC-20 代币**

在 Neon EVM 中对令牌执行操作时，重要的是要知道可以使用哪个令牌符号或地址。拥有可用令牌列表，您可以在选择所需令牌时轻松导航。

_您可以在_[_令牌列表_](https://github.com/neonlabsorg/token-list/)_存储库_中找到其合约部署在 Neon EVM 中并且可供您使用的令牌列表。

霓虹通行证
=====

NeonPass 是一项开源服务，旨在在 Solana 和 Neon EVM 之间传输代币。

前往[NeonPass](https://neonpass.live/)页面调用 NeonPass 应用程序。

[在令牌转移](https://docs.neon-labs.org/docs/token_transferring/neonpass_usage)中阅读更多关于 NeonPass 的信息。

霓虹交换

目标
--

使用 NeonSwap 应用程序将 ERC-20 代币与另一个相同标准的代币交换。

_条件：_ ERC-20 代币可以是合约符合[ERC-20 标准](https://docs.neon-labs.org/docs/about/terminology#erc-20)且部署在 Neon EVM 上的任何[SPL 代币。](https://docs.neon-labs.org/docs/about/terminology#spl-token)

**开始之前**

*   熟悉以下内容：
    
    *   [Solana](https://docs.solana.com/clusters)网络。
        
    *   [元掩码](https://docs.neon-labs.org/docs/about/terminology#metamask)。
        
*   MetaMask钱包必须安装在您的设备上，[并且](https://docs.neon-labs.org/docs/about/terminology#decentralized-application-daapp)可以从您使用的浏览器访问。
    
*   阅读指南[如何将 MetaMask 连接到 Solana 的网络](https://docs.neon-labs.org/docs/wallet/metamask_setup)。
    

NeonSwap概述
----------

[_NeonSwap 是从Uniswap V2 衍生_](https://uniswap.org/blog/uniswap-v2)_出来的开源服务，并经过修改以与 Neon EVM 一起使用。_

NeonSwap 是一个开源 dApp，其主要功能是提供在 Neon EVM 上部署以太坊合约所需的服务。在以太坊中，诸如用一种代币交换另一种代币等交易需要部署合约。这些合约使用其特定服务运行，不能在此环境之外部署。

我们想要证明我们的 Neon EVM 产品允许您将应用程序从以太坊转移到 Solana，同时确保它们可靠地运行。NeonSwap 基础架构为 Neon EVM 上的应用程序以及单独服务器上的交换接口提供全面支持。无需更改即可使用 NeonSwap 服务移植应用程序。

> \*\*[NeonSwap](https://docs.neon-labs.org/docs/about/terminology#neonswap)\*\*服务为以太坊开发人员提供了一个机会，可以毫无困难地将他们的应用程序迁移到 Neon EVM。

**步骤**

NeonSwap 应用程序允许任何用户将一个令牌换成另一个。您只需按照分步说明将您的钱包连接到应用程序。交换代币将自动进行，无需向交易所发送资金。应用程序需要支付一些天然气交易费用。

例如，本教程概述了 ETH->USDT 代币的交换。

**步骤 1. 打开 NeonSwap 应用程序并连接您的钱包**

进入[NeonSwap](https://neonswap.live/)页面调用 NeonSwap 应用程序。在进行交换之前，您需要连接您的钱包。单击`Connect Wallet`交换屏幕。

![从下拉列表中显示的列表中，您必须选择您的钱包。（在我们的例子中，这是MetaMask。）选择您要连接的帐户。](https://storage.googleapis.com/papyrus_images/047723d3366b6b24e378f2be09fa03108ef7088260b36100aaf43293492b4ce3.png)

从下拉列表中显示的列表中，您必须选择您的钱包。（在我们的例子中，这是MetaMask。）选择您要连接的帐户。

**步骤2. 选择一对要兑换**

连接钱包后，您可以开始设置交易所。您需要选择将要交换的令牌。它将从连接的钱包中检索您的余额。在我们的例子中，它将是 ETH。

单击`Select a token`以打开一个菜单，您可以在其中选择要交换的令牌。

![](https://storage.googleapis.com/papyrus_images/c1a3d8bdc4e19c19fa30ca2e47047f1c48b36efa6fa2e3c227a5be824582cd91.png)

**步骤3.如有必要**

该`Select a token`菜单包含部署在 Neon EVM 中的令牌。如果您指定的令牌符号不在列表中，您可以粘贴令牌的地址（如果您知道它是什么）。注意：令牌必须首先部署在 Neon EVM 网络上。

如果要向列表中添加新令牌，请单击`Manage`框底部的 。该`Manage`选项卡将在屏幕上打开。添加部署在 Neon EVM 网络中的新令牌的地址，然后单击`Import`。（您可以从[令牌列表](https://github.com/neonlabsorg/token-list/)中获取令牌的地址。）

![](https://storage.googleapis.com/papyrus_images/b1866746a45b2ce9f80e8b39895f3bb4fcf93c4edc924a24793b7d95ad625586.png)

您将收到一条警告消息，“交易风险自负！” 如果您对自己的行为有信心，请选择同意，`I understand`然后单击`Import`。

新代币的符号将出现在可用于交换的代币列表中。

**步骤4. 输入您要出售**

要查看所售代币的余额，请单击`max`（代币符号旁边）。请记住，必须花费一定数量的代币作为费用来支付执行交易所需的气体。如果您指定交易的全部资金金额，则由此产生的兑换金额将减去费用。

如果池中没有足够的代币进行交换，NeonSwap 将通过发出消息“此交易的流动性不足”来警告您。

在我们的例子中，我们将 ETH 代币换成 USDT 代币。让我们指定要兑换的代币数量等于 10。Neon Swap 将指示购买的 USDT 代币的预期数量，对应于我们交易前的汇率为 2.49176。

![](https://storage.googleapis.com/papyrus_images/aeca8a18d06299175dc8074cca66af6935c02f3ed8bc558b05ab9fac6260d29a.png)

**步骤5. 进行兑换**

在提交此交换之前，您需要了解以下内容：

*   `Price`— 可以进行交换的价格
    
*   `Minimum received`— 如果交易完成，您将收到的最低代币数量（在我们的例子中是 USDT）。如果在交易过程中价格偏离太多（也称为[滑点](https://docs.neon-labs.org/docs/about/terminology#slippage)），交易将失败。
    
*   `Price impact`— 告诉你你的掉期会对这个代币的价格产生多大的影响。这个值可以被视为您将在掉期中承担的损失。这个数字越接近零越好。
    
*   `Liquidity Provider Fee`— 您将为此交易支付的费用。NeonSwap 收取总交易金额的\*0.03%的费用。\*此费用以您出售的代币（在我们的例子中为 ETH）表示。
    

一旦您准备好执行交换，请单击`Swap`。将弹出一个确认窗口，其中包含交换的详细信息。如果条件被接受，请单击`Confirm Swap`。将向 MetaMask 发送请求以确认交易。

**步骤6. 确认兑换**

该请求将打开一个 MetaMask 窗口，您可以在其中确认交易。您可以看到您将支付多少汽油的估计值。点击`Confirm`发送交易。

![](https://storage.googleapis.com/papyrus_images/c519393132c83dbc4bc9a99d32cf0561cfe514b74811bfef6ac8b1b9e9f3fc33.png)

您还可以在 NeonSwap 窗口中查看交易结果。点击`Close`完成交易。

![](https://storage.googleapis.com/papyrus_images/451fff430b86c6796aaf930268c74c73ebe993274c01fdbc75c8c0237f696786.png)

现在您可以打开 MetaMask 以及代币列表，通过单击`Select a token`确保代币余额已更改为预期值。

![交易完成，这意味着您已成功将您的 ETH 兑换为 USDT。](https://storage.googleapis.com/papyrus_images/365aded011cd96f8dc4da0c24cea9a25e4709ba7572b32f103d69a13a7d6102c.png)

交易完成，这意味着您已成功将您的 ETH 兑换为 USDT。

**步骤 7.交易**

单击齿轮图标。`Transaction Settings`屏幕上会弹出设置高级交换的窗口：

![](https://storage.googleapis.com/papyrus_images/4517f7975a826ff7d2deee6084a900d9cbf0c76fa10c45799240e9f0050a5fb6.png)

交易设置：

*   `Slippage tolerance`— 允许的价格变动量。这意味着订单的履行价格与您的预期不同。如果超过选择的容差水平，交易将不会通过。如果您在高波动期间进行交易，您可能需要增加此值。提高交易速度可以帮助您减少高[滑](https://docs.neon-labs.org/docs/about/terminology#slippage)点的机会。
    
*   `Transaction deadline`— 如果处理时间过长，允许交易自动取消。
    
*   `Toggle Expert Mode`— 禁用确认屏幕并删除[滑点](https://docs.neon-labs.org/docs/about/terminology#slippage)限制。除非您完全了解风险，否则不建议启用此模式。
    
*   `Disable Multihops`— 禁用复杂的转换路径。例如，如果“A->B”代币对中没有足够的流动性，那么算法可以让其他代币找到“A->C->B”中间路径，为你进行兑换。此操作需要更多的网络费用，因为涉及多个智能合约。
    

**水龙头（测试币）**

使用 Faucet，您可以在 Solana devnet 上请求测试 NEON 令牌。

**通过UI界面获取**

第1步

按照[设置 MetaMask 设置 MetsMask](https://docs.neon-labs.org/docs/wallet/metamask_setup#installing-metamask)

第2步

[使用以下链接](https://neonswap.live/#/get-tokens)转到页面以请求测试令牌。

第3步

连接你的钱包：

*   点击按钮`CONNECT WALET`
    

![](https://storage.googleapis.com/papyrus_images/e9a3f7553d89f9081fc12cb42d0e2c5450ad9a1b8f0dccbf4b5f686635994905.png)

*   点击按钮`CONNECT METAMASK`
    

![](https://storage.googleapis.com/papyrus_images/d81c254afff57f6286afb252813ecf7482cd4a7a221e4971edb0c93041d7f651.png)

*   在 MetaMask 窗口中，选择一个或多个帐户并单击`Next`。
    

![](https://storage.googleapis.com/papyrus_images/6716b6100bd1474b67f254d54ba42868f2cf8583cb58029c8712ec4c73e55916.png)

*   点击`Connect`按钮确认。
    

![](https://storage.googleapis.com/papyrus_images/b40dbe8b41cae391d219aa1afa56a7185c09c873fa97b97b3b65c2e4eaf8f600.png)

*   在出现的表单中，输入请求令牌的数量并单击按钮`GET TOKENS`。
    

![](https://storage.googleapis.com/papyrus_images/2c388bc1a03bc566a5913e7cb39449a3de6a0c756edefeb521e695c14f45480b.png)

**通过 HTTP API 端点请求测试 NEON 令牌**

客户端使用 POST 请求将数据发送到服务器。支持多个端点。

    |------------------------------------------------------------------------------------------
    | Endpoint               | Workload    | Description
    |------------------------------------------------------------------------------------------
    | request_ping           | text        | Requests ping to check availability of the service
    | request_version        |             | Requests version of the service
    | request_neon_in_galans | JSON        | Requests NEON tokens, amount in galans (fractions)
    | request_neon           | JSON        | Requests NEON tokens
    | request_erc20          | JSON        | Requests ERC20 tokens
    |------------------------------------------------------------------------------------------
    

JSON 工作负载示例：

    { "wallet": "0x4570e07200b6332989Dc04fA2a671b839D26eF0E", "amount": 1 }
    

**使用curl**实用程序的 ping 请求示例：

    curl -i -X POST -d 'Hello' 'http://localhost:3333/request_ping'
    

**使用curl**实用程序的版本请求示例：

    curl -i -X POST 'http://localhost:3333/request_version'
    

**使用curl**实用程序的 NEON 删除请求示例：

    curl -i -X POST \
        -d '{"wallet": "0x4570e07200b6332989Dc04fA2a671b839D26eF0E", "amount": 1}' \
        'http://localhost:3333/request_neon'
    

**配置**

配置文件应为 TOML 格式。

    |----------------------------------------------------------------------------------------------
    | Option                  | Description
    |----------------------------------------------------------------------------------------------
    | rpc.bind                | Local interface TCP address
    | rpc.port                | TCP port to listen
    | rpc.allowed_origins     | List of client URLs that can send requests
    | web3.enable             | Flag to on/off the entire web3 section
    | web3.rpc_url            | Ethereum network endpoint
    | web3.private_key        | Ethereum private key to support operations
    | web3.tokens             | List of available ERC20 token addresses
    | web3.max_amount         | Largest amount of ERC20 tokens to distribute with a single request
    | solana.enable           | Flag to on/off the entire solana section
    | solana.url              | Solana network endpoint
    | solana.commitment       | Solana client commitment level
    | solana.operator_keyfile | Solana keyfile to support operations
    | solana.evm_loader       | Address of the EVM Loader program
    | solana.max_amount       | Largest amount of NEONs to distribute with a single request
    |----------------------------------------------------------------------------------------------
    

配置文件内容示例：

    [rpc]
    bind = "0.0.0.0"
    port = 3333
    allowed_origins = ["http://localhost"]
    
    [web3]
    enable = true
    rpc_url = "http://localhost:9090/solana"
    private_key = "0x0000000000000000000000000000000000000000000000000000000000000Ace"
    tokens = ["0x00000000000000000000000000000000CafeBabe",
              "0x00000000000000000000000000000000DeadBeef"]
    max_amount = 1000
    
    [solana]
    enable = true
    url = "http://localhost:8899"
    commitment = "processed"
    evm_loader = "EvmLoaderId11111111111111111111111111111111"
    operator_keyfile = "operator_id.json"
    max_amount = 10
    

配置文件是可选的，如果存在，可能是不完整的（在这种情况下将使用默认值或环境变量）。

**环境变量**

环境变量（如果存在）会覆盖部分配置。

    |----------------------------------------------------------------------------------------------
    | Name                       | Overrides               | Value Example
    |----------------------------------------------------------------------------------------------
    | FAUCET_RPC_BIND            | rpc.bind                | `0.0.0.0`
    | FAUCET_RPC_PORT            | rpc.port                | `3333`
    | FAUCET_RPC_ALLOWED_ORIGINS | rpc.allowed_origins     | `["http://localhost"]`
    | FAUCET_WEB3_ENABLE         | web3.enable             | `true`
    | WEB3_RPC_URL               | web3.rpc_url            | `http://localhost:9090/solana`
    | WEB3_PRIVATE_KEY           | web3.private_key        | `0x00...0A`
    | NEON_ERC20_TOKENS          | web3.tokens             | `["0x00B", "0x00C"]`
    | NEON_ERC20_MAX_AMOUNT      | web3.max_amount         | `1000`
    | FAUCET_SOLANA_ENABLE       | solana.enable           | `true`
    | SOLANA_URL                 | solana.url              | `http://localhost:8899`
    | SOLANA_COMMITMENT          | solana.commitment       | `processed`
    | EVM_LOADER                 | solana.evm_loader       | `EvmLoaderId11111111111111111111111111111111`
    | NEON_OPERATOR_KEYFILE      | solana.operator_keyfile | `operator_id.json`
    | NEON_ETH_MAX_AMOUNT        | solana.max_amount       | `10`
    | NEON_LOG                   |                         | `json`
    | RUST_LOG                   |                         | `info`
    |----------------------------------------------------------------------------------------------

---

*Originally published on [白开水](https://paragraph.com/@baikaishui/neon)*
