首页>>资讯>>学院

用 OpenZeppelin 和 Foundry 创建和部署可升级的 ERC20 代币

2024-01-30 10:52:32 279

概述


在部署后能够调整和改进智能合约的能力变得至关重要。随着项目的发展,可能会出现意想不到的需求、潜在的优化或不同的产品。对许多人来说,传统的部署全新合约并迁移用户的方法不仅不切实际,而且可能导致用户的沮丧和信任流失。这就是可升级合约的威力所在,它允许你在保留其地址和用户数据的同时改进代币的逻辑。在本教程中,我们将向你展示如何利用 OpenZeppelin 的经过审计的合约套件和 Foundry 的部署功能来创建一个可升级的 ERC-20 代币。


将要做的事情


巩固你对 ERC-20 代币的理解

了解可升级性如何为你的 ERC-20 代币增加更多功能

使用 QuickNode[5] 连接到区块链 (译者备注:本文原作者为 QuickNode )

使用 OpenZeppelin[6] 和Foundry[7]创建和部署可升级的 ERC-20 代币


你需要准备的东西


以太坊和智能合约的基本理解[8]

了解 ERC-20 代币标准[9]

已安装[10] Node.js

一个 Web3 钱包


什么是 ERC-20 代币?


ERC-20 代币标准[11]是在以太坊和基于 EVM 的区块链上创建可互换代币的蓝图。ERC-20 引入了一套标准化的规则,包括了强制性的transfer、balanceOf和totalSupply等函数,确保了代币之间的一致行为。类似于面向对象编程中的接口,开发人员可以欣赏它在强制采用这些关键函数方面的作用。这种统一性已经彻底改变了代币的交互方式,使它们变得无缝和高效,现在代币可以轻松交易、在 dApps 中使用或存储在钱包中,而所有这些都是在以太坊的区块链上运行的。


什么是可升级的 ERC-20 代币?


在其核心,可升级的代币拥抱在部署后增强或修改其功能的灵活性。这是通过分层架构实现的:代理充当与用户交互的不可变智能合约,而逻辑智能合约(有时也称为实现合约)包含业务逻辑。升级是通过更改代理对较新逻辑合约的引用来实现的,确保代币余额和其他状态变量保持不变。在这种设计中,管理员角色通常管理升级过程,决定逻辑合约何时以及如何更改,从而在代币的生命周期中引入了一种治理元素。


有不同类型的可升级智能合约,让我们来介绍最常见的并进行比较。


升级方式


透明代理


透明代理模式旨在区分管理员和普通用户。它通过使用两个不同的地址来工作:一个用于管理员(可以升级合约),另一个用于普通用户(可以与合约的函数交互)。代理合约包括了区分管理员调用和普通用户调用的逻辑,防止在常规使用过程中意外执行管理功能。


UUPS 代理


UUPS(通用可升级代理标准)代理是一种更简化和更节省 gas 的方法。在这种模式中,升级功能嵌入在逻辑合约本身中。这种设计减少了对额外'管理员'合约的需求,简化了结构。但是,它也要求逻辑合约在设计时考虑到可升级性,在其中嵌入必要的升级功能。


Beacon 代理


Beacon 代理模式引入了一个中央的“信标(Beacon)”合约,所有代理实例都引用该合约以获取当前逻辑合约的地址。这种设计允许更高效的升级过程,因为在信标中更新逻辑合约地址会自动更新所有关联的代理。在需要保持多个代理合约与同一逻辑合约同步的情况下,这是特别有用的。


要了解更多关于代理的信息,请查看这个 QuickNode 指南[12]和OpenZeppelin 代理[13]。


在本指南的技术演示中,我们将介绍 UUPS 代理方法。


为什么选择 OpenZeppelin?


OpenZeppelin[14]提供了一系列可重用的智能合约,这些合约是安全的并且经过了审计,确保了你的智能合约的基本构建块是安全的。对于可升级性,OpenZeppelin 提供了代理合约,将调用委托给实现合约。这种方法允许开发人员替换实现合约,同时保留代理的存储、地址和余额。


要了解更多关于 OpenZeppelin 及其可升级性插件的信息,请查看这个资源[15] 。


项目条件:创建 RPC 端点


要将智能合约部署到区块链,你需要一个 API 端点来与网络通信。你可以使用公共节点或部署和管理自己的基础设施;但是,如果你希望获得 8 倍更快的响应时间,你可以把繁重的工作交给我们(QuickNode)。在这里[16]注册一个免费账户。


登录后,点击创建端点按钮,然后选择你要部署的区块链和网络。在本指南中,我们将选择以太坊 Sepolia链。


创建端点后,复制 HTTP 提供程序链接并保持方便,因为你将在接下来的部分中需要它。

1.png

项目先决条件:为钱包充值


如果你需要在 Sepolia 测试网上获得 ETH,Multi-Chain QuickNode Faucet[17] 可以帮助你轻松获取测试 ETH!


转到 Multi-Chain QuickNode Faucet 并连接你的钱包(例如 MetaMask、Coinbase 钱包)或粘贴你的钱包地址以获取测试 ETH。请注意,以太坊主网需要 0.001 ETH 的余额要求才能使用 EVM 水龙头。你还可以在推特上发布你的请求以获得奖励!

1.png

在下一节中,我们将转向创建项目目录并配置项目文件和依赖项。


创建可升级的 ERC-20 代币项目


现在我们对 ERC-20 代币以及以太坊上的可升级性有了很好的基本理解,让我们开始编写一个实际的示例。首先,让我们安装并初始化一个 Foundry 项目。


安装 Foundry


如果你尚未安装 Foundry,请打开你的终端并运行以下命令:


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


上面的命令将安装Foundryup。然后,根据屏幕上的指示继续操作,这将使你能够在 CLI 中使用foundryup命令。安装完成后,你可以在终端中运行foundryup -v命令来检查版本并安装最新的(夜间)预编译二进制文件。


提示


如果你使用的是 Windows,你需要安装并使用 Git BASH 或 WSL 作为你的终端,因为 Foundryup 目前不支持 Powershell 或 Cmd。请按照此处[18]的说明进行操作。


或者,如果你使用的是 M1 Mac,并且出现错误:dyld[32719]: Library not loaded: /usr/local/opt/libusb/lib/libusb-1.0.0.dylib;请尝试通过 brew 安装该库:brew install libusb。


配置完成后,使用以下命令初始化一个 Foundry 项目并进入该目录:


forge init erc20_upgradeable && cd erc20_upgradeable


然后,进入erc20_upgradeable目录,你的项目结构应如下所示:

.

├── lib

├── script

├── src

└── test

foundry.toml


你可能会在项目中看到一些现有的示例文件,但你可以忽略它们。


让我们回顾一下这个结构。


lib:存储依赖项的目录

script:部署合约或与现有智能合约交互的目录

src:智能合约的默认目录

test:运行测试的默认目录

foundry.toml:可以修改版本、优化、RPC 网络、合约验证等设置的配置文件。


我们还需要创建项目所需的文件。运行以下命令以创建智能合约文件、测试文件、部署文件和 remappings.txt(我们将使用它来正确映射我们的库依赖项)。


echo > src/MyToken.sol && echo > src/MyTokenV2.sol && echo > test/MyTokenTest.t.sol && echo > script/deployToken.s.sol && echo > script/deployProxy.s.sol && echo > remappings.txt


在下一节中,我们将安装所需的库并设置我们的配置。


配置项目


通过初始化我们的项目,让我们安装本指南中将要使用的 OpenZeppelin 库。在项目的根目录中,在你的终端中运行以下命令:


forge install OpenZeppelin/openzeppelin-contracts --no-commit

forge install OpenZeppelin/openzeppelin-foundry-upgrades --no-commit

forge install OpenZeppelin/openzeppelin-contracts-upgradeable --no-commit


注意末尾的--no-commit标志。这是因为你的项目文件夹已经与 git 存储库关联,所以我们必须指定不提交任何内容。


现在,让我们通过填写我们之前创建的remappings.txt文件来将导入配置到正确的路径。


向文件中添加以下配置:


@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/

@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/


保存文件后,让我们打开foundry.toml文件,并向你的文件添加以下代码:


build_info = true

extra_output = ["storageLayout"]

[rpc_endpoints]

sepolia = "QUICKNODE_ENDPOINT_URL"


前两行(例如,build_info和extra_output)是在使用 OpenZeppelin Foundry Upgrades library[19](感谢 ericglau!)时所需的配置。此外,由于我们在本指南中在 Sepolia 测试网上部署,我们将把这个端点命名为sepolia。如果你在其他网络上部署,可以更改名称。注意,请记住将QUICKNODE_ENDPOINT_URL占位符替换为你之前创建的实际 QuickNode HTTP 提供程序 URL。


最后,让我们在环境中设置我们的私钥,使用以下变量名和你的私钥。在你的终端中运行以下命令,并将YOUR_PRVATE_KEY占位符更新为你的实际私钥。


export PRIVATE_KEY=YOUR_PRIVATE_KEY


配置设置完成后,让我们继续创建可升级的 ERC-20 代币。


创建可升级的 ERC-20 代币智能合约


是时候为可升级的 ERC-20 代币合约构建逻辑了。在我们开始编写代码之前,让我们先了解一下我们的 ERC-20 代币将具有的确切功能。


我们将在 ERC-20 代币中继承不同的智能合约:


ERC20Upgradeable - 包含可升级功能的 ERC-20 代币

OwnableUpgradeable - 仅允许所有者执行某些功能(所有者可以被转移)

ERC20PermitUpgradeable - 添加了一个许可功能,用户可以使用它来节省离线批准的成本

Initializable - 类似于构造函数,我们将使用它来设置代币的初始参数

UUPSUpgradeable - 我们的 ERC-20 代币将继承的通用可升级代理标准模式逻辑


现在,进入你的src文件夹,并打开MyToken.sol文件。更新文件内容以包括:


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;


import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol";

import "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol";

import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol";

import "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";

import "openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";


contract MyToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, ERC20PermitUpgradeable, UUPSUpgradeable {

    /// @custom:oz-upgrades-unsafe-allow constructor

    constructor() {

        _disableInitializers();

    }


    function initialize(address initialOwner) initializer public {

        __ERC20_init("MyToken", "MTK");

        __Ownable_init(initialOwner);

        __ERC20Permit_init("MyToken");

        __UUPSUpgradeable_init();


        _mint(msg.sender, 1000000 * 10 ** decimals());

    }


    function mint(address to, uint256 amount) public onlyOwner {

        _mint(to, amount);

    }


    function _authorizeUpgrade(address newImplementation)

        internal

        onlyOwner

        override

    {}

}


为了下次轻松部署,请查看Remix.IDE[20]


记得保存文件。让我们回顾一下代码。


如上所述,在我们的 ERC-20 代币中继承了不同的智能合约。然后,在合约的constructor中,我们通过调用_disableInitializers()确保初始化方法只运行一次,以防止意外重新初始化。中间的initialize函数设置了代币的名称为"MyToken"和符号为"MTK",将所有权分配给提供的initialOwner,并激活了增强的授权机制和可升级功能。还向调用此函数的用户铸造了初始代币供应。此外,合约提供了一个仅限所有者的mint函数,允许创建新代币。通过内部的_authorizeUpgrade方法,确保了安全的合约升级,只允许所有者授权新的合约版本。


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;


import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol";

import "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol";

import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol";

import "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";

import "openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";


/// @custom:oz-upgrades-from MyToken

contract MyTokenV2 is Initializable, ERC20Upgradeable, OwnableUpgradeable, ERC20PermitUpgradeable, UUPSUpgradeable {

    /// @custom:oz-upgrades-unsafe-allow constructor

    constructor() {

        _disableInitializers();

    }


    function initialize(address initialOwner) initializer public {

        __ERC20_init("MyTokenV2", "MTKV2");

        __Ownable_init(initialOwner);

        __ERC20Permit_init("MyTokenV2");

        __UUPSUpgradeable_init();


        _mint(msg.sender, 1000000 * 10 ** decimals());

    }


    function mint(address to, uint256 amount) public onlyOwner {

        _mint(to, amount);

    }


    function _authorizeUpgrade(address newImplementation)

        internal

        onlyOwner

        override

    {}

}


总的来说,上面的 ERC-20 智能合约与MyToken.sol非常相似,但存在差异,例如不同的合约名称、符号,并包含升级我们的合约所需的 Foundry/OpenZepplin 注释(例如,/// @custom:oz-upgrades-from MyToken)。


现在,让我们进行编译和测试。


编译和测试可升级的 ERC-20 代币


有了我们编写的智能合约,让我们尝试编译合约并测试可升级的 ERC-20 代币逻辑的行为。


我们将测试以下功能:


检查我们合约的铸造功能(请注意,这仅限于Owner)

测试并验证我们的 ERC-20 代币的可升级性


现在,转到test文件夹并打开MyTokenTest.t.sol文件。正如你可能已经猜到的那样,Foundry 中的测试是用 Solidity 编写的。更新文件的内容以包含以下内容:


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;


import "forge-std/Test.sol";

import "../src/MyToken.sol";

import "forge-std/console.sol";

import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";

import { Upgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol";


contract MyTokenTest is Test {

    MyToken myToken;

    ERC1967Proxy proxy;

    address owner;

    address newOwner;


    // Set up the test environment before running tests

    function setUp() public {

        // 部署实现

        MyToken implementation = new MyToken();

        // Define the owner address

        owner = vm.addr(1);

        // Deploy the proxy and initialize the contract through the proxy

        proxy = new ERC1967Proxy(address(implementation), abi.encodeCall(implementation.initialize, owner));

        // 用代理关联 MyToken 接口

        myToken = MyToken(address(proxy));

        // Define a new owner address for upgrade tests

        newOwner = address(1);

        // Emit the owner address for debugging purposes

        emit log_address(owner);

    }


    // Test the basic ERC20 functionality of the MyToken contract

    function testERC20Functionality() public {

        // Impersonate the owner to call mint function

        vm.prank(owner);

        // Mint tokens to address(2) and assert the balance

        myToken.mint(address(2), 1000);

        assertEq(myToken.balanceOf(address(2)), 1000);

    }

    // 测试升级

    function testUpgradeability() public {

        // Upgrade the proxy to a new version; MyTokenV2

        Upgrades.upgradeProxy(address(proxy), "MyTokenV2.sol:MyTokenV2", "", owner);

    }

}


测试代码相当长,但我们已添加了注释,以便你更好地理解每个测试用例的发生情况。


现在,要编译我们的合约并执行测试,请在终端中运行以下命令:


forge build && forge test --ffi


包括--ffi标志是为了运行我们的代码需要访问的外部脚本。


你可能会收到一些警告,例如“源文件未指定所需的编译器版本!”但这可以忽略。


你将看到类似以下的输出:


[⠢] Compiling...

[⠃] Compiling 62 files with 0.8.22

[⠰] Solc 0.8.22 finished in 3.79s

Compiler run successful with warnings:

Warning (3420): Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.22;"

--> script/deployProxy.s.sol


Warning (3420): Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.22;"

--> script/deployToken.s.sol


[⠢] Compiling...

No files changed, compilation skipped


Running 2 tests for test/MyTokenTest.t.sol:MyTokenTest

[PASS] testERC20Functionality() (gas: 48673)

[PASS] testUpgradeability() (gas: 1642043)

Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 2.43s


Running 2 tests for test/Counter.t.sol:CounterTest

[PASS] testFuzz_SetNumber(uint256) (runs: 256, μ: 27709, ~: 28409)

[PASS] test_Increment() (gas: 28379)

Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 2.43s


Ran 2 test suites: 4 tests passed, 0 failed, 0 skipped (4 total tests)


注意:如果你在测试中遇到错误,你可能需要运行命令 - forge clean && forge build && forge test --ffi 以删除构建工件和缓存目录,然后重新编译并运行测试。


此外,你将注意到两个新目录;out目录包含合约工件,例如 ABI,而cache文件夹被 forge 用于重新编译必要的内容。


唯一剩下的就是部署可升级的 ERC-20 代币。让我们开始吧!


部署可升级的 ERC-20 代币


Foundry 通过使用forge create命令使通过 CLI 轻松部署智能合约;但是,你也可以使用脚本进行部署。请注意,Foundry 一次只能部署一个合约,但这对我们目前来说并不构成障碍。


要部署 ERC-20 代币,让我们使用一个脚本。打开我们之前创建的scripts/deployToken.s.sol文件,并更新文件以使用以下代码:


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;


import "../src/MyToken.sol";

import "forge-std/Script.sol";


contract DeployTokenImplementation is Script {

    function run() public {

        // Use address provided in config to broadcast transactions

        vm.startBroadcast();

        // Deploy the ERC-20 token

        MyToken implementation = new MyToken();

        // Stop broadcasting calls from our address

        vm.stopBroadcast();

        // Log the token address

        console.log("Token Implementation Address:", address(implementation));

    }

}


记得保存文件!剩下的就是执行脚本。


forge script script/DeployToken.s.sol --rpc-url sepolia --private-key $PRIVATE_KEY --broadcast


上述命令使用我们在foundry.toml文件中配置的sepolia RPC URL 执行脚本。--private-key标志设置我们用于交易的账户,--broadcast命令用于将它们广播到网络中。


提示


如果你想要验证你的合约在 Etherscan 上,以便让你和其他人能够从区块浏览器读取和写入你的智能合约,你将需要在上述命令的末尾添加--etherscan-api-key YOUR_ETHERSCAN_API_KEY --verify标志。在本指南的结尾,我们将演示如何从代理中读取,因此如果你想执行该步骤,这将是必需的。


成功后,你将看到如下输出:


== Logs ==

Token Implementation Address: 0x195136BA4F105dAe042F96a59E4dbeF9DCAdE773

...

...

✅  [Success]Hash: 0xe097b9397cd7d36bcf8dc379c95b511746b8d6802e4794e4b0b1125e36bf75bf

Contract Address: 0x5FbDB2315678afecb367f032d93F642f64180aa3

Block: 1

Paid: 0.00673602 ETH (1684005 gas * 4 gwei)


接下来,让我们部署代理合约。


打开scripts/deployProxy.s.sol文件并输入以下代码:


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;


import "../src/MyToken.sol";

import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

import "forge-std/Script.sol";


contract DeployUUPSProxy is Script {

    function run() public {


        address _implementation = YOUR_DEPLOYED_SMART_CONTRACT_ADDRESS; // Replace with your token address

        vm.startBroadcast();


        // Encode the initializer function call

        bytes memory data = abi.encodeWithSelector(

            MyToken(_implementation).initialize.selector,

            msg.sender // Initial owner/admin of the contract

        );


        // Deploy the proxy contract with the implementation address and initializer

        ERC1967Proxy proxy = new ERC1967Proxy(_implementation, data);


        vm.stopBroadcast();

        // Log the proxy address

        console.log("UUPS Proxy Address:", address(proxy));

    }

}


重要提示:现在,在运行下一个命令之前,你需要使用你从上一步骤部署的智能合约地址(例如,代币地址)更新_implementation变量。记得保存文件。


然后,要部署代理,请运行以下命令:


forge script script/deployProxy.s.sol:DeployUUPSProxy --rpc-url sepolia --private-key $PRIVATE_KEY --broadcast

请记住,可选地,你还可以在上述命令的末尾添加--etherscan-api-key YOUR_ETHERSCAN_API_KEY --verify标志以验证你的合约。如果你想要在接下来的步骤中与你的智能合约交互,这将是必需的。


花点时间通过查看 Etherscan 来验证你的智能合约是否已部署。你可以通过 Etherscan 验证合约是否是代理,方法是导航到Code选项卡,单击More Options下拉菜单,然后选择Is this a proxy?。你将被提示验证地址(单击继续),然后导航回 Code 选项卡,你应该会看到两个新选项卡,Read as Proxy和Write as Proxy。如果需要,你可以通过 Etherscan 在这些选项卡上与你的 ERC-20 代币合约进行交互。


例如,让我们使用Read as Proxy选项卡查看地址的 ERC-20 代币余额:

1.png

在上面的图像中,我们正在检查所有者的余额,因为我们在部署时向其铸造了代币。


你现在可以采取的下一步是与你的智能合约进行交互。由于我们在测试部分已经涵盖了交互,所以我们将暂时跳过这部分。


使用 QuickNode 的 Token API 获取代币数据


在结束本教程之前,让我们看看如何可以使用 QuickNode 的 Token API[21] 轻松获取 ERC-20 代币元数据和交易。


要使用 Token API,你可以使用 QuickNode SDK[22] 或在你喜欢的 web3 SDK(如 ethers.js 和 Eth.go)中实现它(在此处查看文档[23] )。


以下是一个快速示例,演示如何使用 cURL 获取你的 ERC-20 代币的元数据:


curl QUICKNODE_ENDPOINT_URL \

  -X POST \

  -H "Content-Type: application/json" \

  --data '{

    "id":67,

    "jsonrpc":"2.0",

    "method":"qn_getTokenMetadataByContractAddress",

    "params": [{

      "contract": "YOUR_TOKEN_ADDRESS"

    }]

  }'


只需将代码粘贴到你的终端,并记得用你的实际 HTTP 提供程序 URL 和代币地址替换QUICKNODE_ENDPOINT_URL和YOUR_TOKEN_ADDRESS。


通过在我们的 ERC-20 代币上调用qn_getTokenMetadataByContractAddress RPC 方法,我们可以返回诸如其元数据和交易信息(例如创建代币的创世块)之类的代币详细信息。


示例响应:


{

    "jsonrpc": "2.0",

    "id": 67,

    "result": {

        "name": "MyToken",

        "symbol": "MTK",

        "contractAddress": "0xc731bc16e15e97687130f4c9a7232781ea060040",

        "decimals": "18",

        "genesisBlock": "4701990",

        "genesisTransaction": "0xa8c93e0c5108f73a039e1537b02f94e871398b6b3fe3f4efafc97c8782965b8a"

    }

}


QuickNode 还提供 NFT API[24],允许你检索聚合的 NFT 数据,例如集合详细信息、转移历史、元数据等。这两个 API 都受 QuickNode 的 Graph API[25] 支持,该 API 允许你查询相同的数据,但以灵活的响应形式,并支持其他聚合数据,例如历史交易数据(例如 OHLC)和频繁更改的数据的实时订阅。


结语


给自己一个鼓励吧!你已经完成了这篇关于创建和部署可升级 ERC-20 代币的技术指南。在这个过程中,你回顾了可升级智能合约的概念以及它们的不同类型,然后设置了一个智能合约环境来创建、测试和部署你的可升级 ERC-20 代币。


本翻译由 DeCert.me[26] 协助支持, 在 DeCert 构建可信履历,为自己码一个未来。


参考资料


[1]

Deploy an Upgradeable ERC20 Token: https://www.quicknode.com/guides/ethereum-development/smart-contracts/how-to-create-and-deploy-an-upgradeable-erc20-token#create-the-erc-20-upgradeable-token-smart-contract


[2]

登链翻译计划: https://github.com/lbc-team/Pioneer


[3]

翻译小组: https://learnblockchain.cn/people/412


[4]

Tiny 熊: https://learnblockchain.cn/people/15


[5]

QuickNode: https://www.quicknode.com/signup?utm_source=internal&utm_campaign=guides&utm_content=how-to-create-and-deploy-an-upgradeable-erc20-token


[6]

OpenZeppelin: https://www.openzeppelin.com/


[7]

Foundry: https://book.getfoundry.sh/getting-started/installation


[8]

对以太坊和智能合约的基本理解: https://decert.me/tutorials


[9]

了解 ERC-20 代币标准: https://learnblockchain.cn/tags/ERC20


[10]

安装: https://nodejs.org/en


[11]

ERC-20 代币标准: https://learnblockchain.cn/docs/eips/eip-20.html


[12]

QuickNode 指南: https://www.quicknode.com/guides/ethereum-development/smart-contracts/an-introduction-to-upgradeable-smart-contracts


[13]

OpenZeppelin 代理: https://docs.openzeppelin.com/contracts/5.x/api/proxy


[14]

OpenZeppelin: https://www.openzeppelin.com/


[15]

资源: https://docs.openzeppelin.com/upgrades-plugins/


[16]

这里: https://www.quicknode.com/signup?utm_source=internal&utm_campaign=guides&utm_content=how-to-create-and-deploy-an-upgradeable-erc20-token


[17]

Multi-Chain QuickNode Faucet: https://faucet.quicknode.com/?utm_source=internal&utm_campaign=guides


[18]

此处: https://book.getfoundry.sh/getting-started/installation


[19]

library: https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades


[20]

Remix.IDE: https://remix.ethereum.org/?#code=Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCAiQG9wZW56ZXBwZWxpbi9jb250cmFjdHMtdXBncmFkZWFibGVANS4wLjAvdG9rZW4vRVJDMjAvRVJDMjBVcGdyYWRlYWJsZS5zb2wiOwppbXBvcnQgIkBvcGVuemVwcGVsaW4vY29udHJhY3RzLXVwZ3JhZGVhYmxlQDUuMC4wL2FjY2Vzcy9Pd25hYmxlVXBncmFkZWFibGUuc29sIjsKaW1wb3J0ICJAb3BlbnplcHBlbGluL2NvbnRyYWN0cy11cGdyYWRlYWJsZUA1LjAuMC9wcm94eS91dGlscy9Jbml0aWFsaXphYmxlLnNvbCI7CmltcG9ydCAiQG9wZW56ZXBwZWxpbi9jb250cmFjdHMtdXBncmFkZWFibGVANS4wLjAvcHJveHkvdXRpbHMvVVVQU1VwZ3JhZGVhYmxlLnNvbCI7Cgpjb250cmFjdCBNeVRva2VuIGlzIEluaXRpYWxpemFibGUsIEVSQzIwVXBncmFkZWFibGUsIE93bmFibGVVcGdyYWRlYWJsZSwgVVVQU1VwZ3JhZGVhYmxlIHsKICAgIC8vLyBAY3VzdG9tOm96LXVwZ3JhZGVzLXVuc2FmZS1hbGxvdyBjb25zdHJ1Y3RvcgogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgX2Rpc2FibGVJbml0aWFsaXplcnMoKTsKICAgIH0KCiAgICBmdW5jdGlvbiBpbml0aWFsaXplKGFkZHJlc3MgaW5pdGlhbE93bmVyKSBpbml0aWFsaXplciBwdWJsaWMgewogICAgICAgIF9fRVJDMjBfaW5pdCgiTXlUb2tlbiIsICJNVEsiKTsKICAgICAgICBfX093bmFibGVfaW5pdChpbml0aWFsT3duZXIpOwogICAgICAgIF9fVVVQU1VwZ3JhZGVhYmxlX2luaXQoKTsKICAgIH0KCiAgICBmdW5jdGlvbiBtaW50KGFkZHJlc3MgdG8sIHVpbnQyNTYgYW1vdW50KSBwdWJsaWMgb25seU93bmVyIHsKICAgICAgICBfbWludCh0bywgYW1vdW50KTsKICAgIH0KCiAgICBmdW5jdGlvbiBfYXV0aG9yaXplVXBncmFkZShhZGRyZXNzIG5ld0ltcGxlbWVudGF0aW9uKQogICAgICAgIGludGVybmFsCiAgICAgICAgb25seU93bmVyCiAgICAgICAgb3ZlcnJpZGUKICAgIHt9Cn0K&deployProxy=true


[21]

QuickNode 的 Token API: https://www.quicknode.com/token-api


[22]

QuickNode SDK: https://www.quicknode.com/docs/quicknode-sdk/getting-started


[23]

文档: https://www.quicknode.com/docs/ethereum/qn_getTokenMetadataByContractAddress_v2


[24]

NFT API: https://www.quicknode.com/nft-api?utm_source=internal&utm_campaign=guides


[25]

QuickNode 的 Graph API: https://www.quicknode.com/graph-api?utm_source=internal&utm_campaign=guides


[26]

DeCert.me: https://decert.me/

声明:本网站所有相关资料如有侵权请联系站长删除,资料仅供用户学习及研究之用,不构成任何投资建议!