探索ERC20代币:构建您的第一个去中心化应用

news2024/11/17 13:40:27

下面文章中会涉及到该资源中的代码,如果想要完整版代码可以私信我获取🌹

文章目录

  • 概要
  • 整体架构流程
  • 技术名词解释
    • ERC20
    • 智能合约
    • web3.js
  • 技术细节
    • ERC20合约部署
    • 创建前端界面
    • 前端与智能合约互连
    • 运行DAPP
  • 小结

概要

在加密货币世界中,ERC20代币是最常见的一种代币标准之一。它们在以太坊区块链上发挥着重要作用,被用于代币募资、去中心化交易所和其他金融应用中。本文将介绍ERC20代币的基础知识,并通过构建一个简单的去中心化应用(DApp)来展示如何与ERC20代币进行交互。

在这里插入图片描述

整体架构流程

  1. 智能合约开发:
    首先,需要开发一个符合ERC20标准的智能合约。这个智能合约定义了代币的基本功能,如转账、余额查询等。在开发过程中,需要考虑安全性、效率和合规性等方面的因素。

  2. 智能合约部署:
    将编写的智能合约部署到以太坊网络上。可以使用以太坊开发工具如RemixTruffleHardhat来完成部署过程。部署智能合约后,会生成一个合约地址,用于与合约进行交互。

  3. 前端开发:
    创建一个前端界面,让用户可以与智能合约进行交互。前端界面可以使用HTML、CSS和JavaScript等技术来构建,并使用Web3.js或其他以太坊JavaScript库来与以太坊网络进行通信。

  4. 连接以太坊网络:
    在前端代码中,使用Web3.js库连接到以太坊网络。这样可以与部署的智能合约进行交互,例如调用合约的方法和获取合约的状态。

  5. 实现功能:
    在前端界面中实现ERC20代币的各种功能,如查看账户余额、转账代币、铸造和销毁代币等。用户可以通过界面与智能合约进行交互,并执行相应的操作。

  6. 测试和优化:
    在完成功能实现后,对DApp进行测试以确保其功能正常。可以使用自动化测试工具或手动测试来检查DApp的各个方面。同时,可以优化DApp的用户体验、性能和安全性,以提升用户满意度。

  7. 部署和推广:
    当DApp通过测试并且已经优化完毕后,可以将其部署到主网或测试网上。在部署之前,确保遵循安全最佳实践和合规要求。部署完成后,可以通过社交媒体、论坛等渠道推广DApp,吸引用户使用和参与。

  8. 持续维护:
    一旦DApp上线,就需要进行持续的维护和更新。监控DApp的性能和安全性,并及时解决出现的问题。同时,根据用户反馈和市场需求,不断优化和改进DApp,保持其竞争力和吸引力。

技术名词解释

ERC20

  • ERC20是以太坊区块链上的一种代币标准,全称为"Ethereum Request for Comment 20"。
  • 它是一种智能合约标准,定义了以太坊上可互操作的代币合约接口和规则。
  • 符合ERC20标准的代币具有一系列标准方法,如转账、查询余额、授权等,使得它们可以与其他智能合约和应用程序进行交互。

智能合约

  • 智能合约是一种在区块链上运行的自动化合约,它们包含了预先编写好的代码和规则。
  • 这些代码和规则可以自动执行,而不需要第三方进行干预,从而实现了可信的去中心化交易和业务逻辑。
  • 智能合约通常使用Solidity等编程语言编写,然后部署到区块链网络上。以太坊是最流行的智能合约平台之一。

web3.js

  • Web3.js是一个JavaScript库,用于与以太坊网络进行交互。
  • 它允许开发人员通过JavaScript代码与以太坊节点通信,例如发送交易、- 调用智能合约方法、查询区块链状态等。
    Web3.js提供了丰富的API和工具,使得以太坊开发更加简单和便捷。

技术细节

ERC20合约部署

首先进到remix网站开发以及部署智能合约,创建一个ERC20.sol文件和IERC20.sol文件,放入下面的代码,对ERC20.sol进行编译部署

编译:
在这里插入图片描述

部署:
在这里插入图片描述

ERC20.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./IERC20.sol";

contract ERC20 is IERC20 {
    uint public totalSupply;
    mapping(address => uint) public balanceOf;
    mapping(address => mapping(address => uint)) public allowance;
    string public name = "HJYCoin";
    string public symbol = "HJYC";
    uint8 public decimals = 0;

    function transfer(address recipient, uint amount) external returns (bool) {
        balanceOf[msg.sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(msg.sender, recipient, amount);
        return true;
    }

    function approve(address spender, uint amount) external returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }  

    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool) {
        allowance[sender][msg.sender] -= amount;
        balanceOf[sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(sender, recipient, amount);
        return true;
    }

    function mint(uint amount) external {
        balanceOf[msg.sender] += amount;
        totalSupply += amount;
        emit Transfer(address(0), msg.sender, amount);
    }

    function burn(uint amount) external {
        balanceOf[msg.sender] -= amount;
        totalSupply -= amount;
        emit Transfer(msg.sender, address(0), amount);
    }
}

IERC20.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
interface IERC20 {
    function totalSupply() external view returns (uint);

    function balanceOf(address account) external view returns (uint);

    function transfer(address recipient, uint amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}

创建前端界面

打开vscode,创建index.html文件

index.html:

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript" src="web3.min.js"></script>
        <link rel="stylesheet" href="index.css" />
        <title>ERC20 DAPP</title>
    </head>

    <body>
        <div class="center">
            <h1>ERC20 DAPP</h1>
            点击获取地址和余额:
            <button type="submit" class="enableEthereumButton">获取</button>
            <h3>账户地址: <span class="showAccount"></span></h3>
            <h3>账户余额: <span class="MyBalance"></span></h3>
            <h3>代币余额:<span class="tokenBalance"></span></h3>

            <hr>
            
            <!-- 转账代币 -->
            <h2>ERC20 代币交易</h2> 
                 <input type="text" id="address" placeholder="输入你的账户地址">
                <div></div>
                <input type="text" id="token" placeholder="输入发送的代币数量">
                <button type="submit" class="sendbutton">发送</button> 

            <!-- 铸造代币 -->
            <h2>铸造ERC20代币</h2>
            <form id="mintForm">
                <input type="text" id="mintAmount" placeholder="输入铸造的代币数量">
            </form>
            <button type="submit" class="mintEthereumButton">铸造</button>
            <h3>交易Status:<span id="mintStatus"></span></h3>
            <h3>交易Hash:<ol id="mintTransactions"></ol></h3>

            <!-- 销毁代币 -->
            <h2>销毁ERC20代币</h2>
            <form id="burnForm">
                <input type="text" id="burnAmount" placeholder="输入销毁的代币数量">
            </form>
            <button type="submit" class="burnEthereumButton">销毁</button>
            <h3>交易Status:<span id="burnStatus"></span></h3>
            <h3>交易Hash:<ol id="burnTransactions"></ol></h3>

        </div>
        <script type="text/javascript" src="app.js"></script>
    </body>
</html>

前端与智能合约互连

打开vscode,创建app.js文件

下面的contractERC20Abi在下图中复制过去
在这里插入图片描述

合约地址ERC20_address
在这里插入图片描述

app.js:

console.log("ERC20")

let accounts = [];
let web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
console.log("web3===>", web3)

if (typeof window.ethereum !== 'undefined') {
    console.log('MetaMask is installed!');
}

console.log("isMetaMask:" + ethereum.isMetaMask)

//这里contractERC20Abi为上面ERC20合约编译得到的ABI
var contractERC20Abi = [...];

// ERC20_address为部署合约得到的合约地址
const ERC20_address = '...'
const contractERC20 = new web3.eth.Contract(contractERC20Abi, ERC20_address)
console.log('contractERC20:', contractERC20)

//获取按钮
$(".enableEthereumButton").click(function () {
    getAccount()
})
//转账按钮
$(".sendbutton").click(function () {
    sendToken()
})

//铸造按钮
$(".mintEthereumButton").click(function () {
	event.preventDefault(); // 防止默认的表单提交行为

    const mintAmount = $("#mintAmount").val(); // 从输入字段获取要铸造的数量

    if (mintAmount) {
        mintTokens(mintAmount);
    } else {
        $("#mintStatus").text("请输入铸造的代币数量");
    }
})

//销毁按钮
$(".burnEthereumButton").click(function () {
	event.preventDefault(); // 防止默认的表单提交行为

    const burnAmount = $("#burnAmount").val(); // 从输入字段获取要销毁的数量

    if (burnAmount) {
        burnTokens(burnAmount);
    } else {
        $("#burnStatus").text("请输入销毁的代币数量");
    }
})
async function getAccount() {
    accounts = await ethereum.request({ method: 'eth_requestAccounts' });
    const account = accounts[0];
	accountBalance = await web3.eth.getBalance(account); 
    $(".showAccount").html(account);
	$(".MyBalance").html(web3.utils.fromWei(accountBalance, 'ether') + ' ETH');
    getBalance();
}

async function getBalance() {
    accounts = await ethereum.request({ method: 'eth_requestAccounts' });
    contractERC20.methods.balanceOf(accounts[0]).call({ from: accounts[0] }).then(
        function (result) {
            console.log('tokenBalance', result)
            $(".tokenBalance").html(web3.utils.fromWei(result, 'ether') + ' HJYETH')

        }
    );
} 

// 铸造代币函数
async function mintTokens(amount) {
    try {
        accounts = await ethereum.request({ method: 'eth_requestAccounts' });
		amuountETH = web3.utils.toWei(amount, 'ether');
        const result = await contractERC20.methods.mint(amuountETH).send({ from: accounts[0] });
        $("#mintStatus").text("铸造成功");
		$("#mintTransactions").append( result.transactionHash );
    } catch (error) {
        $("#mintStatus").text("铸造失败: " + error.message);
    }
}

// 销毁代币函数
async function burnTokens(amount) {
    try {
        accounts = await ethereum.request({ method: 'eth_requestAccounts' });
		amuountETH = web3.utils.toWei(amount, 'ether');
        const result = await contractERC20.methods.burn(amuountETH).send({ from: accounts[0] });
        $("#burnStatus").text("销毁成功");
		$("#burnTransactions").append( result.transactionHash);
    } catch (error) {
        $("#burnStatus").text("销毁失败: " + error.message);
    }
}


// 转账代币函数
async function sendToken() {
    _address = $('#address').val();
    TokenNum = $('#token').val();
    console.log('_address:', _address,'TokenNum', TokenNum)
    // getErc20($(".ErcAddress").html());
    accounts = await ethereum.request({ method: 'eth_requestAccounts' });
	TokenNumETH = web3.utils.toWei(TokenNum, 'ether');
    contractERC20.methods.transfer(_address,TokenNumETH).send({ from: accounts[0] }).then(
        function (result) {
            console.log('result', result)
            // $("#status").html(result.status)
            // $("#transactions").html(result.transactionHash)
            }
)} 


ethereum.on('accountsChanged', function (accounts) {
    console.log("accountsChanged");
    getAccount()
});

ethereum.on('chainChanged', (chainId) => {
    console.log("chainId", chainId);

});

运行DAPP

index.html里面右键单击,再点击open with live server跳转到DAPP界面

在这里插入图片描述
在这里插入图片描述

启动geth私链,打开MetaMask小狐狸钱包,连接到geth网络,就可以进行界面中的各项操作了,例如:获取当前钱包账户地址,铸币,销毁,转账等操作

在这里插入图片描述


小结

通过构建一个简单的ERC20代币DApp,您可以深入了解以太坊智能合约和去中心化应用程序的开发过程。这个项目不仅可以帮助您学习以太坊开发的基础知识,还可以为您未来构建更复杂的DApp奠定基础。
希望本文能够帮助读者更好地了解区块链的DAPP含义,如果有任何疑问或者建议,欢迎留言讨论🌹

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1594983.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

<计算机网络自顶向下> P2P应用

纯P2P架构 没有或者极少一直运行的Server&#xff0c;Peer节点间歇上网&#xff0c;每次IP地址都可能变化任意端系统都可以直接通信利用peer的服务能力&#xff0c;可扩展性好例子&#xff1a;文件分发; 流媒体; VoIP类别:两个节点相互上载下载文件&#xff0c;互通有无&#…

【opencv】示例-text_skewness_correction.cpp 校正文本图像的倾斜度

// 此教程展示了如何矫正文本的偏斜。 // 程序接受一个偏斜的源图像作为输入&#xff0c;并显示非偏斜的文本。#include <opencv2/core.hpp> // 包含OpenCV核心功能的头文件 #include <opencv2/imgcodecs.hpp> // 包含OpenCV图像编解码功能的头文件 #include <o…

大模型实战案例:8卡环境微调马斯克开源大模型 Grok-1

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总…

文献阅读:Viv:在 web 上多尺度可视化高分辨率多重生物成像数据

文献介绍 「文献题目」 Viv: multiscale visualization of high-resolution multiplexed bioimaging data on the web 「研究团队」 Nils Gehlenborg&#xff08;美国哈佛医学院&#xff09; 「发表时间」 2022-05-11 「发表期刊」 Nature Methods 「影响因子」 47.9 「DOI…

java设计模式之策略模式实操

一、背景 临床服务项目流向规则匹配&#xff0c;比如说医生开一个“CT”检查&#xff0c;该检查应该由哪个科室来执行&#xff0c;是通过流向规则配置来决定的&#xff0c;具体配置如下图&#xff1a; 通过相关的条件匹配&#xff0c;最终找到流向科室。 二、设计思路 有几个注…

云计算:Linux 部署 OVN 集群

目录 一、实验 1.环境 2.Linux 部署 OVN 集群&#xff08;中心端&#xff09; 3.Linux 部署 OVN 集群&#xff08;业务端1&#xff09; 4.Linux 部署 OVN 集群&#xff08;业务端2&#xff09; 4.OVN 中心端 连接数据库 5.OVN 业务端1 加⼊控制器 6.OVN 业务端2 加⼊控…

AI克隆语音(基于GPT-SoVITS)

概述 使用GPT-SoVITS训练声音模型&#xff0c;实现文本转语音功能。可以模拟出语气&#xff0c;语速。如果数据质量足够高&#xff0c;可以达到非常相似的结果。相比于So-VITS-SVC需要的显卡配置更低&#xff0c;数据集更小&#xff08;我的笔记本NVIDIA GeForce RTX 4050 Lap…

基于LSTM的新闻中文文本分类——基于textCNN与textRNN

构建词语字典 def build_vocab(file_path, tokenizer, max_size, min_freq):# 定义词汇表字典&#xff1a;使用 vocab_dic {} 初始化一个空字典&#xff0c;用于存储每个词及其出现频率vocab_dic {}with open(file_path, r, encodingUTF-8) as f:for line in tqdm(f):lin l…

为什么光伏探勘测绘需要无人机?

随着全球对可再生能源需求的不断增长&#xff0c;光伏产业也迎来了快速发展的机遇。光伏电站作为太阳能发电的主要形式之一&#xff0c;其建设前期的探勘测绘工作至关重要。在这一过程中&#xff0c;无人机技术的应用正逐渐展现出其独特的优势。那么&#xff0c;为什么光伏探勘…

《手机维修600G资料》云盘下载地址

无意中发现一个生财之道&#xff0c;哈哈哈&#xff0c;就是发现有人在一些视频平台&#xff0c;发手机维修之类的视频吸引客户。这样自己就不用开店也可以接生意了。问题剩下就一个了&#xff0c;把手机维修技术学好&#xff0c;一技在手&#xff0c;天上我有。 《手机维修600…

有条件的打破IBGP水平分割----反射规则和联邦+实验举例

背景&#xff1a;在一个AS中的设备运行了BGP协议&#xff0c;那么正常应该都连接了其他的AS&#xff0c;存在EBGP邻居关系&#xff1b;又由于IBGP的水平分割规则&#xff0c;导致从外部学习到的路由传递给本地AS时&#xff0c;需要和本地AS中运行BGP协议都要建立IBGP邻居关系&a…

基于R语言实现的负二项回归模型【理解与实现】-理解负二项回归模型和泊松回归模型之间的区别

前言 我们可以在R语言中使用MASS包中的glm.nb函数来拟合负二项模型&#xff0c;以及使用glm函数来拟合泊松模型。以下是一个详细的过程&#xff0c;包括模拟数据的生成、模型的拟合、结果的比较和解释。 需要的包 if (!require("MASS")) install.packages("M…

ES增强框架easy-es

因为最近做的功能是关于舆情的,所以数据量比较大的,本来打算用MySQL做时间分表来做,但是经过一段时间的测试,发现数据量太大,用时间分表不能满足性能的要求,所以决定将数据存储改为ES,但是短时间内改底层框架又不是一个小工程,时间上不允许,所以找到了一个很合适的框架,他跟myb…

Echarts简单的多表联动效果和添加水印和按钮切换数据效果

多表联动 多表联动效果指的是在多个表格之间建立一种交互关系&#xff0c;以便它们之间的操作或选择能够相互影响。通常情况下&#xff0c;多表联动效果可以通过以下方式之一实现&#xff1a; 数据关联&#xff1a; 当在一个表格中选择或操作某些数据时&#xff0c;另一个表格…

DataGrip连接Docker中的MySQL容器

获取MySQL镜像 通过命令行工具或者docker desktop 命令行&#xff1a; docker pull mysqldocker desktop工具&#xff0c;tag可以指定版本 创建mysql容器 我们知道dockerfile用于编写镜像&#xff0c;dockercompose用于编排容器&#xff0c;所以这里我用dockercompose来创…

eNSP防火墙配置实验(trust、DMZ、untrust)

【拓扑】 设备 接口 IP地址/子网掩码/网关 AR1 G0/0/0 10.1.3.2/24 G0/0/1 100.1.1.2/24 FW1 G0/0/0 192.168.166.254/24 G1/0/0 10.1.1.1/24&#xff0c;trust域 G1/0/1 10.1.2.1/24&#xff0c;DMZ域 G1/0/2 100.1.3.1/24&#xff0c;untrust域 LSW1 G0/0/…

ssm051网上医院预约挂号系统+jsp

网上医院预约挂号系统设计与实现 摘 要 如今的信息时代&#xff0c;对信息的共享性&#xff0c;信息的流通性有着较高要求&#xff0c;因此传统管理方式就不适合。为了让医院预约挂号信息的管理模式进行升级&#xff0c;也为了更好的维护医院预约挂号信息&#xff0c;网上医院…

13.多通道视频流缓存以及显示架构

1 简介 多通道视频流缓存以及显示架构是一个在数字图像处理中很基础也很重要的一个架构。在图像拼接以及高分辨率图像显示方面应用范围较为广泛。本文将介绍一个四通道的图像显示。可以四个图像信息输入以及拼接到一个显示屏里面。使用的开发板为A7 2 框架图 架构图如下图所示…

Day20-【Java SE高级】单元测试 反射 注解 动态代理

一、单元测试 就是针对最小的功能单元(方法)&#xff0c;编写测试代码对其进行正确性测试。 1. 咱们之前是如何进行单元测试的?有啥问题? 只能在main方法编写测试代码&#xff0c;去调用其他方法进行测试。无法实现自动化测试&#xff0c;一个方法测试失败&#xff0c;可能…

FJSP:水鹿优化算法(Sambar Optimization Algorithm,SOA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题&#xff08;Flexible Job Shop Scheduling Problem&#xff0c;FJSP&#xff09;&#xff0c;是一种经典的组合优化问题。在FJSP问题中&#xff0c;有多个作业需要在多个机器上进行加工&#xff0c;每个作业由一系列工序组成&a…