
使用 ChatGPT 赚钱的 12 种简单方法(任何人都可以做到)
立即开始,ChatGPT 可免费使用。使用 ChatGPT 赚钱是目前互联网上最热门的话题之一。此文章深入探讨了 12 种直接的获利方法,并通过实际示例指导您走向成功。 ChatGPT 是一款卓越的 AI 聊天机器人,由 Open AI 打造,Elon Musk 是其联合创始人之一,Sam Altman 担任首席执行官。该 AI 由 GPT-3.5 技术提供支持,并以其类似人类的对话技巧令人惊叹。 这一创新工具为技术互动打开了一个充满机遇的世界,并预示着一个令人兴奋的未来。在使用 ChatGPT 赚钱之前作为一种高度先进的语言模型,ChatGPT 可以毫不费力地预测后面的单词并生成非常准确的书面内容。 它已经过训练,可以通过使用 RLHF(人类反馈强化学习)来响应人类提示,这是一种创新的额外层,可以提高模型理解和参与自然语言对话的能力。 要有效利用 ChatGPT,请不要忽视提供清晰、详细说明的重要性。您不仅是在训练 AI 机器人,也是在训练您自己如何提出正确的问题并提供必要的信息。您必须认真查看 ChatGPT 的回复并相应地调整您的提示,直到达到预期的结果。使用 ChatGP...

CEX/DEX 交易所开发案例 现成源码
加密货币交易记录在区块链上,为去中心化的价值交换铺平了道路。通过为自己创建一个加密货币交易所,您可以成为即将到来的十亿美元革命的一部分。一旦您了解交易所的工作方式,它将帮助您轻松了解加密买卖双方的交易行为。西西弗斯网络科技是一家加密货币交易所等区块链业务开发公司,率先开发完整的加密货币交易所软件以促进安全和快速的交易。 我们的团队经验丰富的区块链开发人员将为您构建一个可定制和可扩展的加密交换平台,高度关注安全性、连接性和无缝环境。成为通过加密货币交易所开发确保数字资产革命的公司。让我们开始吧!https://www.cobofi.com/交易所开发服务我们的交易软件支持所有主要数字货币,例如比特币、比特币现金、以太坊、莱特币等。该交易所还支持美元和主要法定货币。交易所为合格投资者和合法交易自动进行 KYC/AML 验证。该交易所与具有多货币支持和多重签名的安全加密钱包集成。该软件符合 GDPR,符合高级安全协议,包括 DDoS、X-XSS、2FA 等。交换结构允许客户根据自己的喜好有效地添加或删除加密货币。该软件集成了尖端功能和区块链技术。主导匹配引擎和加密价格行情工具交换可以根...

什么是总价值锁定 (TVL)、它在DeFi中很重要吗?
本期呢就来讲一讲TVL,相信各位在观看咨询是,会发现某某TVL已经突破多少多少亿美元,TVL是什么?都知道被咨询报出来的币种TVL,基本呢都是DeFi里面的币种,那么TVL在DeFi中很重要吗? 如果很重要,那么那个TVL是最高的?带着这些问题,随着小编的视角接着看下去。1.锁定的总价值(Total Value Locked)是什么意思?首先呢先来讲一下总价值,说的简单易懂点就是我们俗称的TVL。 除了市值、交易量以及总供应量和流通供应量之外,锁定总价值 (TVL) 是一种加密指标,在 DeFi 投资者中很流行,用于评估在所有 DeFi 中存放的资产(以美元或任何法定货币)的总价值协议或单个 DeFi 项目中。 DeFi资产包括奖励和利息,来自典型的服务,如借贷、抵押和流动资金池,以智能合约的形式提供。例如,质押中的 TVL 对于希望以最高回报支持 DeFi 平台的投资者来说是一个特别有用的指标。它是锁定在 DeFi 质押协议中的总价值,代表流动性提供者存入的资产数量。 到 2022 年,全球 TVL 已从前两年的 4 亿美元增长到近 20 亿美元。随着 DeFi 在加密货币领域...
AI 破局俱乐部, 玩赚 ChatGPT。 AI 的 iPhone 时刻来了,现在在 AI 领域学习一年,相当于在其他行业混10年。 欢迎链接:15829049609(VX)

使用 ChatGPT 赚钱的 12 种简单方法(任何人都可以做到)
立即开始,ChatGPT 可免费使用。使用 ChatGPT 赚钱是目前互联网上最热门的话题之一。此文章深入探讨了 12 种直接的获利方法,并通过实际示例指导您走向成功。 ChatGPT 是一款卓越的 AI 聊天机器人,由 Open AI 打造,Elon Musk 是其联合创始人之一,Sam Altman 担任首席执行官。该 AI 由 GPT-3.5 技术提供支持,并以其类似人类的对话技巧令人惊叹。 这一创新工具为技术互动打开了一个充满机遇的世界,并预示着一个令人兴奋的未来。在使用 ChatGPT 赚钱之前作为一种高度先进的语言模型,ChatGPT 可以毫不费力地预测后面的单词并生成非常准确的书面内容。 它已经过训练,可以通过使用 RLHF(人类反馈强化学习)来响应人类提示,这是一种创新的额外层,可以提高模型理解和参与自然语言对话的能力。 要有效利用 ChatGPT,请不要忽视提供清晰、详细说明的重要性。您不仅是在训练 AI 机器人,也是在训练您自己如何提出正确的问题并提供必要的信息。您必须认真查看 ChatGPT 的回复并相应地调整您的提示,直到达到预期的结果。使用 ChatGP...

CEX/DEX 交易所开发案例 现成源码
加密货币交易记录在区块链上,为去中心化的价值交换铺平了道路。通过为自己创建一个加密货币交易所,您可以成为即将到来的十亿美元革命的一部分。一旦您了解交易所的工作方式,它将帮助您轻松了解加密买卖双方的交易行为。西西弗斯网络科技是一家加密货币交易所等区块链业务开发公司,率先开发完整的加密货币交易所软件以促进安全和快速的交易。 我们的团队经验丰富的区块链开发人员将为您构建一个可定制和可扩展的加密交换平台,高度关注安全性、连接性和无缝环境。成为通过加密货币交易所开发确保数字资产革命的公司。让我们开始吧!https://www.cobofi.com/交易所开发服务我们的交易软件支持所有主要数字货币,例如比特币、比特币现金、以太坊、莱特币等。该交易所还支持美元和主要法定货币。交易所为合格投资者和合法交易自动进行 KYC/AML 验证。该交易所与具有多货币支持和多重签名的安全加密钱包集成。该软件符合 GDPR,符合高级安全协议,包括 DDoS、X-XSS、2FA 等。交换结构允许客户根据自己的喜好有效地添加或删除加密货币。该软件集成了尖端功能和区块链技术。主导匹配引擎和加密价格行情工具交换可以根...

什么是总价值锁定 (TVL)、它在DeFi中很重要吗?
本期呢就来讲一讲TVL,相信各位在观看咨询是,会发现某某TVL已经突破多少多少亿美元,TVL是什么?都知道被咨询报出来的币种TVL,基本呢都是DeFi里面的币种,那么TVL在DeFi中很重要吗? 如果很重要,那么那个TVL是最高的?带着这些问题,随着小编的视角接着看下去。1.锁定的总价值(Total Value Locked)是什么意思?首先呢先来讲一下总价值,说的简单易懂点就是我们俗称的TVL。 除了市值、交易量以及总供应量和流通供应量之外,锁定总价值 (TVL) 是一种加密指标,在 DeFi 投资者中很流行,用于评估在所有 DeFi 中存放的资产(以美元或任何法定货币)的总价值协议或单个 DeFi 项目中。 DeFi资产包括奖励和利息,来自典型的服务,如借贷、抵押和流动资金池,以智能合约的形式提供。例如,质押中的 TVL 对于希望以最高回报支持 DeFi 平台的投资者来说是一个特别有用的指标。它是锁定在 DeFi 质押协议中的总价值,代表流动性提供者存入的资产数量。 到 2022 年,全球 TVL 已从前两年的 4 亿美元增长到近 20 亿美元。随着 DeFi 在加密货币领域...
AI 破局俱乐部, 玩赚 ChatGPT。 AI 的 iPhone 时刻来了,现在在 AI 领域学习一年,相当于在其他行业混10年。 欢迎链接:15829049609(VX)

Subscribe to 元峰GPT

Subscribe to 元峰GPT
Share Dialog
Share Dialog
<100 subscribers
<100 subscribers


https://www.blocktrain.info/blog/build-a-full-stack-erc-20-dapp
使用 Solidity 创建智能合约。
利用 OpenZeppelin 创建 ERC20 合约
使用 Hardhat 编译和部署智能合约。
连接到 Metamask 钱包。
Metamask 钱包重要方法和事件。
通过 Etherjs 与来自 React/Next 应用程序的智能合约交互。
如果你以前使用过 Javascript 和 Reactjs,你会相处得很好。
你需要安装 Nodejs。
您还需要为 chrome 安装和设置 Metamask。
我们正在建立一个网站,用户可以在其中连接到他们的以太坊钱包并铸造 ERC20 代币以换取一些 goerli 以太币。
我们将使用 Alchemy 节点将此智能合约部署在 Goerli 测试网上。

一旦用户连接到钱包,他就可以铸造、转移甚至销毁他的 HKP 代币。
HKP 是我名字 Harsh Kumar Pandey 的缩写。我用它作为令牌的符号。您可以使用您的姓名或其他任何内容。

Project-ERC20 项目预览
首先,您需要获取 node/npm。如果你没有它,请到这里
接下来,让我们前往航站楼。继续并 cd 到你想要工作的目录。一旦你在那里运行这些命令:
mkdir project-erc20
cd project-erc20
npx create-next-app .
npm install --save-dev hardhat
这里发生的是,你运行:
1. mkdir project-erc20 创建一个名为“project-erc20”的目录。
2. cd project-erc20 进入新建的目录。
3. npx create-next-app . 在当前目录中生成下一个应用程序模板。
4. npm install --save-dev hardhat 安装 Hardhat。
在运行最后一个命令并安装 Hardhat 后,您可能会看到有关漏洞的消息。每次从 NPM 安装某些东西时,都会进行安全检查,以查看您正在安装的任何软件包或库是否有任何已报告的漏洞。这更像是对你的警告,所以你要知道!
太棒了,现在我们应该拥有 hardhat 了。
注意:如果您在 Windows 上使用 Git Bash 安装 hardhat,您可能会在这一步 (HH1) 遇到错误。如果遇到问题,您可以尝试使用 Windows CMD 执行 HardHat 安装。可以在此处找到其他信息。
选择创建基本示例项目的选项。对一切都说是。
示例项目将要求您安装 hardhat-waffle 和 hardhat-ethers。这些是我们稍后会用到的其他好东西。
这将生成一些文件夹和文件,我们将在后面详细介绍所有内容。
继续安装这些其他依赖项,以防它没有自动执行。
npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers dotenv
您还需要安装 OpenZeppelin,这是另一个经常用于开发安全智能合约的库。我们将在下一节中详细了解它。现在,只需安装它 :)。
npm install @openzeppelin/contracts
首先,我们需要让我们的本地以太坊网络正常工作。这就是我们编译和测试智能合约代码的方式。
现在,您只需要知道智能合约是一段存在于区块链上的代码。区块链是一个公共场所,任何人都可以通过收费安全地读写数据。
在合约内部,有变量和函数。变量存储数据(如数据库),函数帮助读取和写入这些变量。
这里的大局是:
我们要写一个智能合约。该合约具有围绕我们的 ERC20 的所有逻辑,即铸币、转让和销毁代币。
现在项目设置已经完成,我们可以开始为我们的应用程序编写智能合约。
在 contracts 文件夹中,创建一个名为 Token.sol 的新文件,并向其中添加以下代码。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
// This will import all the variables and methods of contracts mentioned after <is<
// So we can accessing and override them according to our needs.
contract HKPtoken is ERC20, ERC20Burnable, Ownable {
// public keyword here creates a getter function which returns the value or the variable.
// We can access these variable by simply writing variable name <tokenPrice<
// But to access these vairables from inherited contracts, we need to call them <tokenPrice()<.
uint public tokenPrice;
uint public maxSupply;
constructor() ERC20("HKPtoken", "HKP") {
// In solidity, quantity of 1 means 1 * 10^18
// and 1 Ether means, 1 * 10^18 wei
// Setting token price to 0.2 ether
tokenPrice = 2000000000000000;
// Max supply is 150 tokens
maxSupply = 150000000000000000000;
}
function mint(uint amount) public payable{
// totalSupply means total number of Tokens already minted.
// checking if totalSupply + requested amount is <= max allowed Supply(maxSupply)
require(
totalSupply() + amount <= maxSupply,
"Exceeding max supply"
);
// checking if ether sent by minter is in accordence with tokenPrice and amount.
require(
msg.value * 10 ** decimals() / amount >= tokenPrice,
"Pay Ether according to Token Price"
);
// This _mint() function is provided by OpenZeppelin ERC20 contract. There are generic codes that every ERC20 contract must have. OpenZeppelin helps us by removing the need to writing generic code and focus on requirement part.
_mint(msg.sender, amount);
}
function withdrawEther() public onlyOwner {
payable(owner()).transfer(address(this).balance);
}
// We will call this function to get these information to show in front-end application.
// We are returning multiple things from single function here so that we won<t have to call each getter function one by one.
function returnState() public view returns(uint _myBalance, uint _maxSupply, uint _totalSupply, uint _tokenPrice ){
return (balanceOf(msg.sender), maxSupply, totalSupply(), tokenPrice);
}
// Notice how we are calling <totalSupply()< to access.This is because this variable is inherited from ERC20 contract by OpenZeppelin.
}
让我们在 hardhat.config.js 更新 hardhat 配置。
// We need to import these extensions in order for hardhat to function properly
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
// We need hardhat-etherscan to upload(verify) aur smart contractto etherscan.
require("@nomiclabs/hardhat-etherscan");
require("dotenv").config();
module.exports = {
solidity: "0.8.9",
networks: {
goerli: {
url: process.env.ALCHEMY_RPC_URL,
accounts: [`0x${process.env.WALLET_PRIVATE_KEY}`],
},
},
// We don<t need following ethescan block for deployment, but we need it for smart contract verification (upload).
etherscan: {
apiKey: process.env.NEXT_PUBLIC_ETHERSCAN_API_KEY,
},
};
ALCHEMY_RPC_URL 是在我们的应用程序和区块链之间创建连接。
WALLET_PRIVATE_KEY 是将部署合约并将成为合约所有者的帐户。
需要 NEXT_PUBLIC_ETHERSCAN_API_KEY 来验证智能合约。这样我们也可以看到来自 etherscan 的智能合约并与之交互。
1.在 alchemy.com 上创建一个帐户。
2.进入仪表板后,单击“创建应用程序”。

3.为 App 命名和描述。

4.保留链以太坊并选择 Goerli 作为网络。
5.创建 App 后,您将看到 Key、HTTPS Url 和 Websocket。

6.复制 HTTPS Url 并将其粘贴到 .env 中,这是我们的 RPC URL
在 etherscan.io 上创建一个帐户
登录然后访问etherscan.io/myapikey
单击“添加”,为应用程序命名,仅此而已。
您将看到 api 密钥,复制并粘贴到 .env 中

请注意,我们可以在免费计划中每秒进行 5 次 API 调用。我们之前在合约中创建的“getState()”函数将保存 api 调用并在一次调用中获取所有重要信息。
1.打开 MetaMask chrome 扩展。
2.解锁并点击右上角的3个点
3.单击“帐户详细信息”。

4.单击“导出私钥”。
5.将私钥复制到 .env 中
现在你的 .env 文件应该是这样的。
WALLET_PRIVATE_KEY = "6sadf43rtf7df3451f033453b7a293651096083e534rfcff48";
NEXT_PUBLIC_ETHERSCAN_API_KEY = "SD678FTGW7FU6GWEDFC6WE5FF88";
ALCHEMY_RPC_URL =
"https://eth-goerli.g.alchemy.com/v2/SDFSDFSEFRR345T43R34RTFR";
确保在推送到 github 之前将此文件添加到 .gitignore。
现在我们可以部署甚至验证我们的智能合约了。
继续并在 scripts 文件夹下创建一个名为 deploy.js 的文件。
将下面的代码复制粘贴到 deploy.js 文件。
const main = async () => {
// Here <hre< is injected automatically by hardhat, no need to import it explicitly.
const DevToken = await hre.ethers.getContractFactory("HKPtoken");
// Any value passed to deploy() will be passed to contructor of our contract as parameters.
const devToken = await DevToken.deploy();
// <deploy()< in previous line deploys the contract.
// <deployed() in next line checks if contract is deployed.
await devToken.deployed();
// Once deployed (in 20-30 seconds) you will see the contract address in console. You can also check the transaction on etherscan goerli network.
console.log("Contract deployed to: ", devToken.address);
};
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
让我们编译我们的合约,在终端中输入这段代码。
npx hardhat compile
这会在项目根目录中创建一个名为 artifacts 的新文件夹,并使用我们的令牌的编译版本填充它。
我们需要 artifacts 中的 HKPtoken.json 文件,以便稍后从前端与合约进行交互。
在我们部署我们的合约之前,我们需要在我们的账户中使用 goerli ether 来支付所有交易(部署,函数调用)的 gas 费用。
前往 Goerli Faucet 输入您的钱包地址,goerli eth将在20-30秒后转入您的钱包。
还有许多其他水龙头,如果您需要更多,请谷歌。
现在在终端中运行以下代码,通过运行我们之前创建的 deploy.js 文件来部署合约。
npx hardhat run ./scripts/deploy.js --network goerli
运行几秒钟后,您将在终端中看到您部署的合约地址,如下所示
npx hardhat run ./scripts/deploy.js --network goerli
Contract deployed to: 0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b
复制此地址并将其保存在文件中,稍后我们将需要它以及 HKPtoken.json 文件来与合约进行交互。
现在,如果您转到 https://goerli.etherscan.io/address/0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b 并单击合同。 你会看到合约的字节码。

现在让我们验证我们的智能合约。
在终端中输入以下代码。
npx hardhat verify --network goerli 0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b
最后部署的合约地址
这段代码的执行完成后,再次转到 etherscan,合约选项卡。

您将看到已部署合约的代码,以及所有继承的合约。
您还会在左上角看到这些按钮,读取合同和写入合同按钮。所以现在你也可以在连接到钱包后从 etherscan 读取和写入状态变量。
将 artifacts/contracts/HKPtoken.json 的内容复制粘贴到 helpers/abi.json
制作另一个文件 helpers/contants.js 并复制粘贴到下面的代码中。
import abi from "./abi.json";
// Get abi array from abi.json file
export const contractABI = abi.abi;
// Deployed contract address
export const contractAddress = "0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b";
创建一个 context/walletContext.jsx 文件并添加以下代码。
上面的代码解释了有关连接钱包和处理事件的所有内容。
但是记住我已经为孟买测试网编码了 addNetwork() ,你必须找出并填写goerli 测试网的详细信息。
https://docs.metamask.io/guide/rpc-api.html#wallet-addethereumchain
现在让我们调用智能合约的函数并获取我们或 OpenZeppelin 声明的状态变量的值。
将下面的代码添加到 walletContext.jsx
const getContractState = async () => {
try {
// contractMethods will have all the functions of our smart contract as well as the inherited smart contract.
const contractMethods = getContract();
// We declared this function to get the values of our state variables. We were returning multiple values from this function, so we<ll recieve them in array.
const state = await contractMethods.returnState();
// Accessing them by index and storing in react state.
// Remember 1 in JS = 1*10^18 in solidity? Values returned by contract are not supported in JS, so ether gives us util function to format / parse them.
// so we are formatting the values using ethers.utils.formatEther().
setContractState({
myBalance: state[0] ? parseFloat(ethers.utils.formatEther(state[0])) : 0,
maxSupply: parseFloat(ethers.utils.formatEther(state[1])),
totalSupply: parseFloat(ethers.utils.formatEther(state[2])),
tokenPrice: ethers.utils.formatEther(state[3]),
});
} catch (error) {
console.log(error);
}
};
现在让我们了解如何通过向合约的 mint() 函数发送以太币和预期参数来铸造代币。
const handleMint = async () => {
// mintAmount is a react state hooked with an number input.
if (mintAmount == 0) return;
// Getting all the methods of contract.
const contractMethods = createEthereumContract();
// Declaring value (number of ether) that has to be sent with function call (Transaction).
// Calculating how munch ether user need to send based on tokenPrice to get mintAmount number of token.
// Like I<ve mentioned earlier, 1 in JS = 1*10^18 in Solidity, so we are converting JS value to Solidity supported value using ethers.utils.parseEther().
const options = {
value: ethers.utils.parseEther(
(mintAmount * contractState.tokenPrice).toString()
),
};
// ethers.utils.parseEther() only accepts string, so we need to convert mintAmount to String.
// Passing our option object as the LAST PARAMETER to mint() function of contract which determines how much ether to be sent.
try {
const txn = await contractMethods.mint(
ethers.utils.parseEther(mintAmount.toString()),
options
);
// Once transaction is initiated, we can wait for the transaction be get mined.
await txn.wait();
// Once transaction is mined, Fetch updated states of contract.
getContractStates();
} catch (error) {
console.log(error);
}
};
既然您已经了解了代币的铸造,那么转移和销毁它们就是简单的函数调用,就像铸造一样。
const handleTransfer = async () => {
// amount is react state hooked with number input to determine how much tkoen to transfer.
if (amount == 0) return;
// Fetching functions of contract.
const contractMethods = createEthereumContract();
try {
// Passing the wallet adrress of receiver and amount after parsing it.
const txn = await contractMethods.transfer(
to,
ethers.utils.parseEther(amount.toString())
);
// Waiting for transaction to be mined.
await txn.wait();
// Once mined, fetching updated contract states.
getContractStates();
} catch (error) {
// Handle Common Errors.
if (error.reason === "invalid address") alert("Invalid Address");
else if (
error.reason ===
"execution reverted: ERC20: transfer amount exceeds balance"
)
alert("Transfer amount exceeds balance");
else alert(error.reason);
}
};
使用 console.log(contractMethods) 检查 const contractMethods = createEthereumContract(); 之后有哪些可用方法。
您会发现带有一个参数的 burn() 方法。尝试自己实现 handleBurn() 方法。

这些红色标记是从我们合约的 returnState() 方法返回的合约状态。
超级令人兴奋,你能走到最后。相当重要!
感谢您通过学习这些东西为 Web3 的未来做出贡献。事实上,您知道它是如何工作的以及如何对其进行编码是一种超能力。明智地使用你的力量。
链游 /Dapp /NFT数藏 /公链 /交易所等区块链技术开发业务对接。 开启区块链元宇宙之旅,拥抱数字未来。 业务咨询:15829049609

https://www.blocktrain.info/blog/build-a-full-stack-erc-20-dapp
使用 Solidity 创建智能合约。
利用 OpenZeppelin 创建 ERC20 合约
使用 Hardhat 编译和部署智能合约。
连接到 Metamask 钱包。
Metamask 钱包重要方法和事件。
通过 Etherjs 与来自 React/Next 应用程序的智能合约交互。
如果你以前使用过 Javascript 和 Reactjs,你会相处得很好。
你需要安装 Nodejs。
您还需要为 chrome 安装和设置 Metamask。
我们正在建立一个网站,用户可以在其中连接到他们的以太坊钱包并铸造 ERC20 代币以换取一些 goerli 以太币。
我们将使用 Alchemy 节点将此智能合约部署在 Goerli 测试网上。

一旦用户连接到钱包,他就可以铸造、转移甚至销毁他的 HKP 代币。
HKP 是我名字 Harsh Kumar Pandey 的缩写。我用它作为令牌的符号。您可以使用您的姓名或其他任何内容。

Project-ERC20 项目预览
首先,您需要获取 node/npm。如果你没有它,请到这里
接下来,让我们前往航站楼。继续并 cd 到你想要工作的目录。一旦你在那里运行这些命令:
mkdir project-erc20
cd project-erc20
npx create-next-app .
npm install --save-dev hardhat
这里发生的是,你运行:
1. mkdir project-erc20 创建一个名为“project-erc20”的目录。
2. cd project-erc20 进入新建的目录。
3. npx create-next-app . 在当前目录中生成下一个应用程序模板。
4. npm install --save-dev hardhat 安装 Hardhat。
在运行最后一个命令并安装 Hardhat 后,您可能会看到有关漏洞的消息。每次从 NPM 安装某些东西时,都会进行安全检查,以查看您正在安装的任何软件包或库是否有任何已报告的漏洞。这更像是对你的警告,所以你要知道!
太棒了,现在我们应该拥有 hardhat 了。
注意:如果您在 Windows 上使用 Git Bash 安装 hardhat,您可能会在这一步 (HH1) 遇到错误。如果遇到问题,您可以尝试使用 Windows CMD 执行 HardHat 安装。可以在此处找到其他信息。
选择创建基本示例项目的选项。对一切都说是。
示例项目将要求您安装 hardhat-waffle 和 hardhat-ethers。这些是我们稍后会用到的其他好东西。
这将生成一些文件夹和文件,我们将在后面详细介绍所有内容。
继续安装这些其他依赖项,以防它没有自动执行。
npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers dotenv
您还需要安装 OpenZeppelin,这是另一个经常用于开发安全智能合约的库。我们将在下一节中详细了解它。现在,只需安装它 :)。
npm install @openzeppelin/contracts
首先,我们需要让我们的本地以太坊网络正常工作。这就是我们编译和测试智能合约代码的方式。
现在,您只需要知道智能合约是一段存在于区块链上的代码。区块链是一个公共场所,任何人都可以通过收费安全地读写数据。
在合约内部,有变量和函数。变量存储数据(如数据库),函数帮助读取和写入这些变量。
这里的大局是:
我们要写一个智能合约。该合约具有围绕我们的 ERC20 的所有逻辑,即铸币、转让和销毁代币。
现在项目设置已经完成,我们可以开始为我们的应用程序编写智能合约。
在 contracts 文件夹中,创建一个名为 Token.sol 的新文件,并向其中添加以下代码。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
// This will import all the variables and methods of contracts mentioned after <is<
// So we can accessing and override them according to our needs.
contract HKPtoken is ERC20, ERC20Burnable, Ownable {
// public keyword here creates a getter function which returns the value or the variable.
// We can access these variable by simply writing variable name <tokenPrice<
// But to access these vairables from inherited contracts, we need to call them <tokenPrice()<.
uint public tokenPrice;
uint public maxSupply;
constructor() ERC20("HKPtoken", "HKP") {
// In solidity, quantity of 1 means 1 * 10^18
// and 1 Ether means, 1 * 10^18 wei
// Setting token price to 0.2 ether
tokenPrice = 2000000000000000;
// Max supply is 150 tokens
maxSupply = 150000000000000000000;
}
function mint(uint amount) public payable{
// totalSupply means total number of Tokens already minted.
// checking if totalSupply + requested amount is <= max allowed Supply(maxSupply)
require(
totalSupply() + amount <= maxSupply,
"Exceeding max supply"
);
// checking if ether sent by minter is in accordence with tokenPrice and amount.
require(
msg.value * 10 ** decimals() / amount >= tokenPrice,
"Pay Ether according to Token Price"
);
// This _mint() function is provided by OpenZeppelin ERC20 contract. There are generic codes that every ERC20 contract must have. OpenZeppelin helps us by removing the need to writing generic code and focus on requirement part.
_mint(msg.sender, amount);
}
function withdrawEther() public onlyOwner {
payable(owner()).transfer(address(this).balance);
}
// We will call this function to get these information to show in front-end application.
// We are returning multiple things from single function here so that we won<t have to call each getter function one by one.
function returnState() public view returns(uint _myBalance, uint _maxSupply, uint _totalSupply, uint _tokenPrice ){
return (balanceOf(msg.sender), maxSupply, totalSupply(), tokenPrice);
}
// Notice how we are calling <totalSupply()< to access.This is because this variable is inherited from ERC20 contract by OpenZeppelin.
}
让我们在 hardhat.config.js 更新 hardhat 配置。
// We need to import these extensions in order for hardhat to function properly
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-ethers");
// We need hardhat-etherscan to upload(verify) aur smart contractto etherscan.
require("@nomiclabs/hardhat-etherscan");
require("dotenv").config();
module.exports = {
solidity: "0.8.9",
networks: {
goerli: {
url: process.env.ALCHEMY_RPC_URL,
accounts: [`0x${process.env.WALLET_PRIVATE_KEY}`],
},
},
// We don<t need following ethescan block for deployment, but we need it for smart contract verification (upload).
etherscan: {
apiKey: process.env.NEXT_PUBLIC_ETHERSCAN_API_KEY,
},
};
ALCHEMY_RPC_URL 是在我们的应用程序和区块链之间创建连接。
WALLET_PRIVATE_KEY 是将部署合约并将成为合约所有者的帐户。
需要 NEXT_PUBLIC_ETHERSCAN_API_KEY 来验证智能合约。这样我们也可以看到来自 etherscan 的智能合约并与之交互。
1.在 alchemy.com 上创建一个帐户。
2.进入仪表板后,单击“创建应用程序”。

3.为 App 命名和描述。

4.保留链以太坊并选择 Goerli 作为网络。
5.创建 App 后,您将看到 Key、HTTPS Url 和 Websocket。

6.复制 HTTPS Url 并将其粘贴到 .env 中,这是我们的 RPC URL
在 etherscan.io 上创建一个帐户
登录然后访问etherscan.io/myapikey
单击“添加”,为应用程序命名,仅此而已。
您将看到 api 密钥,复制并粘贴到 .env 中

请注意,我们可以在免费计划中每秒进行 5 次 API 调用。我们之前在合约中创建的“getState()”函数将保存 api 调用并在一次调用中获取所有重要信息。
1.打开 MetaMask chrome 扩展。
2.解锁并点击右上角的3个点
3.单击“帐户详细信息”。

4.单击“导出私钥”。
5.将私钥复制到 .env 中
现在你的 .env 文件应该是这样的。
WALLET_PRIVATE_KEY = "6sadf43rtf7df3451f033453b7a293651096083e534rfcff48";
NEXT_PUBLIC_ETHERSCAN_API_KEY = "SD678FTGW7FU6GWEDFC6WE5FF88";
ALCHEMY_RPC_URL =
"https://eth-goerli.g.alchemy.com/v2/SDFSDFSEFRR345T43R34RTFR";
确保在推送到 github 之前将此文件添加到 .gitignore。
现在我们可以部署甚至验证我们的智能合约了。
继续并在 scripts 文件夹下创建一个名为 deploy.js 的文件。
将下面的代码复制粘贴到 deploy.js 文件。
const main = async () => {
// Here <hre< is injected automatically by hardhat, no need to import it explicitly.
const DevToken = await hre.ethers.getContractFactory("HKPtoken");
// Any value passed to deploy() will be passed to contructor of our contract as parameters.
const devToken = await DevToken.deploy();
// <deploy()< in previous line deploys the contract.
// <deployed() in next line checks if contract is deployed.
await devToken.deployed();
// Once deployed (in 20-30 seconds) you will see the contract address in console. You can also check the transaction on etherscan goerli network.
console.log("Contract deployed to: ", devToken.address);
};
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
让我们编译我们的合约,在终端中输入这段代码。
npx hardhat compile
这会在项目根目录中创建一个名为 artifacts 的新文件夹,并使用我们的令牌的编译版本填充它。
我们需要 artifacts 中的 HKPtoken.json 文件,以便稍后从前端与合约进行交互。
在我们部署我们的合约之前,我们需要在我们的账户中使用 goerli ether 来支付所有交易(部署,函数调用)的 gas 费用。
前往 Goerli Faucet 输入您的钱包地址,goerli eth将在20-30秒后转入您的钱包。
还有许多其他水龙头,如果您需要更多,请谷歌。
现在在终端中运行以下代码,通过运行我们之前创建的 deploy.js 文件来部署合约。
npx hardhat run ./scripts/deploy.js --network goerli
运行几秒钟后,您将在终端中看到您部署的合约地址,如下所示
npx hardhat run ./scripts/deploy.js --network goerli
Contract deployed to: 0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b
复制此地址并将其保存在文件中,稍后我们将需要它以及 HKPtoken.json 文件来与合约进行交互。
现在,如果您转到 https://goerli.etherscan.io/address/0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b 并单击合同。 你会看到合约的字节码。

现在让我们验证我们的智能合约。
在终端中输入以下代码。
npx hardhat verify --network goerli 0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b
最后部署的合约地址
这段代码的执行完成后,再次转到 etherscan,合约选项卡。

您将看到已部署合约的代码,以及所有继承的合约。
您还会在左上角看到这些按钮,读取合同和写入合同按钮。所以现在你也可以在连接到钱包后从 etherscan 读取和写入状态变量。
将 artifacts/contracts/HKPtoken.json 的内容复制粘贴到 helpers/abi.json
制作另一个文件 helpers/contants.js 并复制粘贴到下面的代码中。
import abi from "./abi.json";
// Get abi array from abi.json file
export const contractABI = abi.abi;
// Deployed contract address
export const contractAddress = "0x3a7a068B3Bf32675F8C8dA60d34Cea7C02a5736b";
创建一个 context/walletContext.jsx 文件并添加以下代码。
上面的代码解释了有关连接钱包和处理事件的所有内容。
但是记住我已经为孟买测试网编码了 addNetwork() ,你必须找出并填写goerli 测试网的详细信息。
https://docs.metamask.io/guide/rpc-api.html#wallet-addethereumchain
现在让我们调用智能合约的函数并获取我们或 OpenZeppelin 声明的状态变量的值。
将下面的代码添加到 walletContext.jsx
const getContractState = async () => {
try {
// contractMethods will have all the functions of our smart contract as well as the inherited smart contract.
const contractMethods = getContract();
// We declared this function to get the values of our state variables. We were returning multiple values from this function, so we<ll recieve them in array.
const state = await contractMethods.returnState();
// Accessing them by index and storing in react state.
// Remember 1 in JS = 1*10^18 in solidity? Values returned by contract are not supported in JS, so ether gives us util function to format / parse them.
// so we are formatting the values using ethers.utils.formatEther().
setContractState({
myBalance: state[0] ? parseFloat(ethers.utils.formatEther(state[0])) : 0,
maxSupply: parseFloat(ethers.utils.formatEther(state[1])),
totalSupply: parseFloat(ethers.utils.formatEther(state[2])),
tokenPrice: ethers.utils.formatEther(state[3]),
});
} catch (error) {
console.log(error);
}
};
现在让我们了解如何通过向合约的 mint() 函数发送以太币和预期参数来铸造代币。
const handleMint = async () => {
// mintAmount is a react state hooked with an number input.
if (mintAmount == 0) return;
// Getting all the methods of contract.
const contractMethods = createEthereumContract();
// Declaring value (number of ether) that has to be sent with function call (Transaction).
// Calculating how munch ether user need to send based on tokenPrice to get mintAmount number of token.
// Like I<ve mentioned earlier, 1 in JS = 1*10^18 in Solidity, so we are converting JS value to Solidity supported value using ethers.utils.parseEther().
const options = {
value: ethers.utils.parseEther(
(mintAmount * contractState.tokenPrice).toString()
),
};
// ethers.utils.parseEther() only accepts string, so we need to convert mintAmount to String.
// Passing our option object as the LAST PARAMETER to mint() function of contract which determines how much ether to be sent.
try {
const txn = await contractMethods.mint(
ethers.utils.parseEther(mintAmount.toString()),
options
);
// Once transaction is initiated, we can wait for the transaction be get mined.
await txn.wait();
// Once transaction is mined, Fetch updated states of contract.
getContractStates();
} catch (error) {
console.log(error);
}
};
既然您已经了解了代币的铸造,那么转移和销毁它们就是简单的函数调用,就像铸造一样。
const handleTransfer = async () => {
// amount is react state hooked with number input to determine how much tkoen to transfer.
if (amount == 0) return;
// Fetching functions of contract.
const contractMethods = createEthereumContract();
try {
// Passing the wallet adrress of receiver and amount after parsing it.
const txn = await contractMethods.transfer(
to,
ethers.utils.parseEther(amount.toString())
);
// Waiting for transaction to be mined.
await txn.wait();
// Once mined, fetching updated contract states.
getContractStates();
} catch (error) {
// Handle Common Errors.
if (error.reason === "invalid address") alert("Invalid Address");
else if (
error.reason ===
"execution reverted: ERC20: transfer amount exceeds balance"
)
alert("Transfer amount exceeds balance");
else alert(error.reason);
}
};
使用 console.log(contractMethods) 检查 const contractMethods = createEthereumContract(); 之后有哪些可用方法。
您会发现带有一个参数的 burn() 方法。尝试自己实现 handleBurn() 方法。

这些红色标记是从我们合约的 returnState() 方法返回的合约状态。
超级令人兴奋,你能走到最后。相当重要!
感谢您通过学习这些东西为 Web3 的未来做出贡献。事实上,您知道它是如何工作的以及如何对其进行编码是一种超能力。明智地使用你的力量。
链游 /Dapp /NFT数藏 /公链 /交易所等区块链技术开发业务对接。 开启区块链元宇宙之旅,拥抱数字未来。 业务咨询:15829049609

import { createContext, useContext, useEffect, useState } from "react";
import { contractABI, contractAddress } from "@/helpers/constants";
import { ethers } from "ethers";
export const walletContext = createContext();
export const useWalletContext = () => useContext(walletContext);
function WalletProvider({ children }) {
const [currentAccount, setCurrentAccount] = useState(null);
const [contractState, setContractState] = useState(null);
// Create a button labled "Connect Wallet" and on Click, call this function.
const connectWallet = async () => {
try {
// If metamask extension is not installed, etherem will be undefined.
const { ethereum } = window;
if (!ethereum) return;
const accounts = await ethereum.request({
// This opens metamask and ask to connect to the website.
method: "eth_requestAccounts",
});
// If connected, returns array of accounts(address) which you allow during request
setCurrentAccount(accounts[0]);
} catch (error) {
console.log(error);
}
};
// This Function checks if website is connected to wallet or not.
const checkConnection = async () => {
try {
// If metamask extension is not installed, etherem will be undefined.
const { ethereum } = window;
if (!ethereum) return;
const accounts = await ethereum.request({
// this method check for any connection and returns array of accounts which are connected
method: "eth_accounts",
});
// First account in array is the active one.
setCurrentAccount(accounts[0]);
try {
// If you are on mumbai network on metamask, this will ask you to switch to goerli network
await window.ethereum.request({
method: "wallet_switchEthereumChain",
// chainId must be in hexadecimal numbers.
params: [{ chainId: `0x${Number(80001).toString(16)}` }],
});
} catch (error) {
console.log(error);
// If there was error switching, code 4902 represents that goerli network is not added to metamask, so method below will pre-fill the network details and ask user to add the network.
if (error.code === 4902) {
addNetwork();
}
if (error.code === -32002) {
alert("Open Metamask");
}
}
// This function is declared at the bottom.
// Will explain this with function declaration.
getContractState();
} catch (error) {
console.log(error);
}
};
const addNetwork = async () => {
try {
await window.ethereum.request({
// Learn more about this method here https://docs.metamask.io/guide/rpc-api.html#wallet-addethereumchain
// To get the details of any chain, visit https://chainid.network/chains.json
method: "wallet_addEthereumChain",
params: [
{
chainId: `0x${Number(80001).toString(16)}`,
chainName: "Mumbai",
nativeCurrency: {
name: "MATIC",
symbol: "MATIC",
decimals: 18,
},
rpcUrls: [
"https://matic-mumbai.chainstacklabcom",
"https://rpc-mumbai.maticvigil.com",
"https://matic-testnet-archive-rpbwarelabs.com",
],
blockExplorerUrls: ["https://mumbapolygonscan.com"],
},
],
});
} catch (error) {
console.log(error);
}
}
const getContract = () => {
const { ethereum } = window;
if (!ethereum) return;
// This provider is connecting us to blockchain, there could be different types of web3 providers.
// lern more here https://docs.ethers.io/v5/api/providers/
const provider = = new ethers.providers.Web3Provider(ethereum);
// signer is required to call <write methods< of contracts. Every transaction is signed by this signer with the help of private key of your wallet, provided with ethereum object.
const signer = provider.getSigner();
// We pass the contract address, abi and signer to get access to all the functions of the contract, and the ability to call setter functions.
// We can also pass provider instead of signer in case user is not connected to wallet. In this user cannot call setter functions of contract, only getter functions could be called.
const contractMethods = new ethers.Contract(
contractAddress,
contractABI,
signer
);
return contractMethods;
};
useEffect(() => {
if (!window.ethereum) return;
// Metamask is installed, check connection and get contract state (tokenPrice, totalSupply, maxSupply, balance of user)
checkConnection();
// Adding event listeners
// In metamask, you can either change the active account(user), or change the active network (goerli, mumbai, kovan, etc.)
ethereum.on("chainChanged", handleChainChanged);
ethereum.on("accountsChanged", handleDisconnect);
// Cleanup of listener on unmount
return () => {
ethereum.removeListener("chainChanged", handleChainChanged);
ethereum.removeListener("accountsChanged", handleDisconnect);
};
}, []);
const handleDisconnect = (accounts) => {
if (accounts.length == 0) {
setCurrentAccount("");
} else {
setCurrentAccount(accounts[0]);
}
};
const handleChainChanged = (chainId) => {
// If the chain is changed to goerli network, don<t do anything.
if (chainId == "0x13881") return; // chain id is received in hexadecimal
// chain is changed to any other network, reload the page.
// On reload, checkConnection will run due to useEffect.
// Inside of that function, we are asking user to switch to goerli network.
window.location.reload();
};
const contextValue = {
connectWallet,
currentAccount,
contractState,
getContract,
};
return (
<walletContext.Provider value={contextValue}>
{children}
</walletContext.Provider>
);
}
export default WalletProvider;
import { createContext, useContext, useEffect, useState } from "react";
import { contractABI, contractAddress } from "@/helpers/constants";
import { ethers } from "ethers";
export const walletContext = createContext();
export const useWalletContext = () => useContext(walletContext);
function WalletProvider({ children }) {
const [currentAccount, setCurrentAccount] = useState(null);
const [contractState, setContractState] = useState(null);
// Create a button labled "Connect Wallet" and on Click, call this function.
const connectWallet = async () => {
try {
// If metamask extension is not installed, etherem will be undefined.
const { ethereum } = window;
if (!ethereum) return;
const accounts = await ethereum.request({
// This opens metamask and ask to connect to the website.
method: "eth_requestAccounts",
});
// If connected, returns array of accounts(address) which you allow during request
setCurrentAccount(accounts[0]);
} catch (error) {
console.log(error);
}
};
// This Function checks if website is connected to wallet or not.
const checkConnection = async () => {
try {
// If metamask extension is not installed, etherem will be undefined.
const { ethereum } = window;
if (!ethereum) return;
const accounts = await ethereum.request({
// this method check for any connection and returns array of accounts which are connected
method: "eth_accounts",
});
// First account in array is the active one.
setCurrentAccount(accounts[0]);
try {
// If you are on mumbai network on metamask, this will ask you to switch to goerli network
await window.ethereum.request({
method: "wallet_switchEthereumChain",
// chainId must be in hexadecimal numbers.
params: [{ chainId: `0x${Number(80001).toString(16)}` }],
});
} catch (error) {
console.log(error);
// If there was error switching, code 4902 represents that goerli network is not added to metamask, so method below will pre-fill the network details and ask user to add the network.
if (error.code === 4902) {
addNetwork();
}
if (error.code === -32002) {
alert("Open Metamask");
}
}
// This function is declared at the bottom.
// Will explain this with function declaration.
getContractState();
} catch (error) {
console.log(error);
}
};
const addNetwork = async () => {
try {
await window.ethereum.request({
// Learn more about this method here https://docs.metamask.io/guide/rpc-api.html#wallet-addethereumchain
// To get the details of any chain, visit https://chainid.network/chains.json
method: "wallet_addEthereumChain",
params: [
{
chainId: `0x${Number(80001).toString(16)}`,
chainName: "Mumbai",
nativeCurrency: {
name: "MATIC",
symbol: "MATIC",
decimals: 18,
},
rpcUrls: [
"https://matic-mumbai.chainstacklabcom",
"https://rpc-mumbai.maticvigil.com",
"https://matic-testnet-archive-rpbwarelabs.com",
],
blockExplorerUrls: ["https://mumbapolygonscan.com"],
},
],
});
} catch (error) {
console.log(error);
}
}
const getContract = () => {
const { ethereum } = window;
if (!ethereum) return;
// This provider is connecting us to blockchain, there could be different types of web3 providers.
// lern more here https://docs.ethers.io/v5/api/providers/
const provider = = new ethers.providers.Web3Provider(ethereum);
// signer is required to call <write methods< of contracts. Every transaction is signed by this signer with the help of private key of your wallet, provided with ethereum object.
const signer = provider.getSigner();
// We pass the contract address, abi and signer to get access to all the functions of the contract, and the ability to call setter functions.
// We can also pass provider instead of signer in case user is not connected to wallet. In this user cannot call setter functions of contract, only getter functions could be called.
const contractMethods = new ethers.Contract(
contractAddress,
contractABI,
signer
);
return contractMethods;
};
useEffect(() => {
if (!window.ethereum) return;
// Metamask is installed, check connection and get contract state (tokenPrice, totalSupply, maxSupply, balance of user)
checkConnection();
// Adding event listeners
// In metamask, you can either change the active account(user), or change the active network (goerli, mumbai, kovan, etc.)
ethereum.on("chainChanged", handleChainChanged);
ethereum.on("accountsChanged", handleDisconnect);
// Cleanup of listener on unmount
return () => {
ethereum.removeListener("chainChanged", handleChainChanged);
ethereum.removeListener("accountsChanged", handleDisconnect);
};
}, []);
const handleDisconnect = (accounts) => {
if (accounts.length == 0) {
setCurrentAccount("");
} else {
setCurrentAccount(accounts[0]);
}
};
const handleChainChanged = (chainId) => {
// If the chain is changed to goerli network, don<t do anything.
if (chainId == "0x13881") return; // chain id is received in hexadecimal
// chain is changed to any other network, reload the page.
// On reload, checkConnection will run due to useEffect.
// Inside of that function, we are asking user to switch to goerli network.
window.location.reload();
};
const contextValue = {
connectWallet,
currentAccount,
contractState,
getContract,
};
return (
<walletContext.Provider value={contextValue}>
{children}
</walletContext.Provider>
);
}
export default WalletProvider;
No activity yet