<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>nzhl</title>
        <link>https://paragraph.com/@nzhl</link>
        <description>科学家, 数字货币&amp;NFT投机者 |
定期更新工具&amp;代码教程 |
代码致富 |
nzhlfred.eth |</description>
        <lastBuildDate>Wed, 29 Apr 2026 00:27:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>nzhl</title>
            <url>https://storage.googleapis.com/papyrus_images/5f7ec0e93a84cc3c4522e86a8fd21d10f0fea2f8f0d66e2c9321409e676340e4.png</url>
            <link>https://paragraph.com/@nzhl</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Web3 101：Dapp原理简介&实现自己的狗狗币]]></title>
            <link>https://paragraph.com/@nzhl/web3-101-dapp</link>
            <guid>ygMtz3c7OhBIWoelhoHr</guid>
            <pubDate>Sun, 13 Feb 2022 12:45:07 GMT</pubDate>
            <description><![CDATA[前言 & 背景话先说在前面, 文章只是学习交流. 虽然Telegram上玩土狗, 资金盘的一大堆, 但不代表这东西就合法合理, 写这个文章的目的, 一方面是学习交流, 另一方面就是从技术的角度告诉大家这玩意大概的原理, 希望大家保持清晰, 切勿瞎J8 FOMO. 记住, 搞土狗一定不能让你暴富, 反而可能会让你坐牢. 因为后面准备发一系列相关的文章, 也算是自己学习&总结, 会介绍目前常见的一些区块链应用的技术实现, 大部分背景、前置知识是相通的, 考虑到发币本身也比较简单, 如果单写发币可能文章篇幅太短, 所以准备顺便介绍一些前置知识, 基于上述, 这篇文章大概会分成以下几个部分:DApp架构的介绍会用到的工具链发币实现&流程土狗是怎么回事没有耐心的可以直接拉倒下面具体开发那一章节要求文章可能需要一定的前置知识, 对于没有太多基础的同学, 即使抛开文章本身我觉得这些知识是想要成为一个智能合约/ DApp 开发者所必须的 :熟悉JavaScript及常见的工具链, 主要用来做合约的部署&简单的网页引导用户与智能合约进行交互.区块链, 特别是ETH必须要有一定的认知, 也大概知道s...]]></description>
            <content:encoded><![CDATA[<h2 id="h-and" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">前言 &amp; 背景</h2><p><strong>话先说在前面, 文章只是学习交流. 虽然Telegram上玩土狗, 资金盘的一大堆, 但不代表这东西就合法合理, 写这个文章的目的, 一方面是学习交流, 另一方面就是从技术的角度告诉大家这玩意大概的原理, 希望大家保持清晰, 切勿瞎J8 FOMO. 记住, 搞土狗一定不能让你暴富, 反而可能会让你坐牢.</strong></p><p>因为后面准备发一系列相关的文章, 也算是自己学习&amp;总结, 会介绍目前常见的一些区块链应用的技术实现, 大部分背景、前置知识是相通的, 考虑到发币本身也比较简单, 如果单写发币可能文章篇幅太短, 所以准备顺便介绍一些前置知识, 基于上述, 这篇文章大概会分成以下几个部分:</p><ol><li><p>DApp架构的介绍</p></li><li><p>会用到的工具链</p></li><li><p>发币实现&amp;流程</p></li><li><p>土狗是怎么回事</p></li></ol><p>没有耐心的可以直接拉倒下面具体开发那一章节</p><h1 id="h-" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">要求</h1><p>文章可能需要一定的前置知识, 对于没有太多基础的同学, 即使抛开文章本身我觉得这些知识是想要成为一个智能合约/ DApp 开发者所必须的 :</p><ol><li><p>熟悉JavaScript及常见的工具链, 主要用来做合约的部署&amp;简单的网页引导用户与智能合约进行交互.</p></li><li><p>区块链, 特别是ETH必须要有一定的认知, 也大概知道solidity</p></li></ol><h1 id="h-dapp" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">DApp架构</h1><p>为了方便理解后面的工具链, 也方便技术朋友简单类比, 先简单介绍传统中心化应用与区块链去中心化应用的架构区别. 如果拿淘宝上买东西来举例的话, 大概是:</p><ol><li><p>h5/Andorid/iOS(大前端) 负责引导用户与应用进行交互, 比如购买一个手机</p></li><li><p>请求从大前端发到中心化的服务器(服务器属于淘宝)上，(简化掉CDN, 网关, 负载均衡以及其他一系列乱七八糟的东西), 服务端代码 (Java / Go) 负责处理具体的业务逻辑, 更新买家订单信息, 更新卖家数据库等等.</p></li></ol><p>可以看到你的逻辑&amp;信息都是放在淘宝的服务器上的, 如果淘宝哪天说, ok你这个订单我不认, 那没了就没了, 从技术上看, 淘宝是完全有能力让你的某一笔订单(相关数据)完全消失的.</p><p>DApp 区别在于第二步, 请求从大前端并没有发送到中心化的服务器上, 而是通过提交Transaction的方式发送到了链上, 智能合约代码 (Solidity) 负责处理具体的业务逻辑, 如果数据比较大的话, 可能还会用到 ipfs(索引) + Arweave (存储). 草图:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/dfdccbf4b051212d7b1c0bb520891a80f09585e4c1490fc07e704b4ad223cf3a.png" alt="CApp vs DApp" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">CApp vs DApp</figcaption></figure><h1 id="h-" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">工具链</h1><p>回到发币, 根据架构图来看, 我们需要:</p><ol><li><p>和用户交互的界面, 对于币而言, 主要就是币的买/卖, 去中心化交易所就是专门做这个的, 最常见的例如 uniswap, 所以我们不需要写代码.</p></li><li><p>provider, 上面图里出现了这个东西, 我还没来得及介绍, 本质是一个或者一群ETH节点, 它的作用是方便我们进行链上交互, 即: 查询链上信息, 发布交易(部署新合约, 与其他合约进行交互). 一般比较常见的会使用例如 alchemy, infura 之类的节点提供商, 当然你自己拿电脑起个节点理论上也是可以的, 但通常不会这么去做, 主要是部署成本和稳定性上的考虑.</p></li></ol><p>从开发的视角来看, 我们需要:</p><ol><li><p>solidity 编辑器, 我这边用vscode, 也可以用官方提供的 remix</p></li><li><p>开发&amp;测试&amp;部署工具链: 这里会使用 hardhat 类似的还有 Truffle</p></li><li><p>不管是用户真实使用还是我们自己测试, 我们都需要去和ETH进行交互(创建合约, 发币, 转账等等), 操作合约不可能是连上某个节点然后手动去操作, 都是编写代码进行操作的, js, python都有相关的工具库支持操作合约, 这里还是使用 js, 会用到一个叫 ethers.js 的库, 类似的还有web3.js.</p><p>这里的原理很简单: 你用js代码描述你需要如何与链上的合约进行交互, 由 ethers.js 负责编码你的合约完成交互(交易), 然后发送给 provider/链上节点. 所以通常来讲你需要要在 ethers.js 中声明你的 provider, 譬如提供你创建的 infura 节点的秘钥或者链接到你自己部署的ETH节点以及signer, 也就是你的私钥或是助记词.所以其实一些钱包应用譬如Metamask, 它本质也是一个provider + signer, 市面上常见的DApp让你连接Metamask然后完成各种操作, 这里Metamask 的作用就是使用你的秘钥对交易进行加密编码然后通过 Metamask 自己背后的 provider 服务发送到ETH上.</p></li></ol><p>考虑具体需求, 我们是要发空气币, 空气币一般遵循 ERC20 的代币接口规范, 里面定义了代币基本的一些交互功能(包括转账, 余额查询, 还有代币铸造与销毁), 这种代码不需要自己写, 我们直接引用 openzeppelin, 一个高质量的智能合约工具库, 里面对常见的一些代币、NFT等等的接口规范都进行了实现.</p><h1 id="h-" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">具体开发</h1><h3 id="h-1" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">1. 初始化项目</h3><p>讲了这么多终于进入正题了, 先起个项目, 智能合约项目其实和传统前端很类似:</p><pre data-type="codeBlock" text="# 新建项目
mkdir nzhl-coins
cd nzhl-coins
npm init -y

# 安装 hardhat
npm i -D hardhat

# 使用 hardhat 初始化项目
npx hardhat 
# ✔ What do you want to do? · Create an advanced sample project 
that uses TypeScript
# 这里选了TS模板, 然后后面的选择一直yes就行


# vscode 打开
code . 
"><code><span class="hljs-comment"># 新建项目</span>
<span class="hljs-built_in">mkdir</span> nzhl-coins
<span class="hljs-built_in">cd</span> nzhl-coins
npm init -y

<span class="hljs-comment"># 安装 hardhat</span>
npm i -D hardhat

<span class="hljs-comment"># 使用 hardhat 初始化项目</span>
npx hardhat 
<span class="hljs-comment"># ✔ What do you want to do? · Create an advanced sample project </span>
that uses TypeScript
<span class="hljs-comment"># 这里选了TS模板, 然后后面的选择一直yes就行</span>


<span class="hljs-comment"># vscode 打开</span>
code . 
</code></pre><p>先来简单介绍下目录</p><pre data-type="codeBlock" text="├── README.md  
├── contracts   (智能合约i.e solidity代码放这里)
│   └── Greeter.sol
├── hardhat.config.ts (负责hardhat的配置)
├── node_modules (譬如依赖的三方工具，类库的代码都在这)
├── package.json 
├── pnpm-lock.yaml 
├── scripts (目前只存放了用于合约部署的脚本)
│   └── deploy.ts
├── test (合约测试脚本, 本次用不到)
│   └── index.ts
└── tsconfig.json
"><code>├── README.md  
├── contracts   (智能合约i.e solidity代码放这里)
│   └── Greeter.sol
├── hardhat.config.ts (负责hardhat的配置)
├── node_modules (譬如依赖的三方工具，类库的代码都在这)
├── package.json 
├── pnpm<span class="hljs-operator">-</span>lock.yaml 
├── scripts (目前只存放了用于合约部署的脚本)
│   └── deploy.ts
├── test (合约测试脚本, 本次用不到)
│   └── index.ts
└── tsconfig.json
</code></pre><h3 id="h-2" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">2. 编写智能合约代码</h3><p>来写具体的合约代码, 由于我们会依赖 openzeppelin 的智能合约代码, 所以需要安装@openzeppelin/contracts 依赖</p><pre data-type="codeBlock" text="npm i @openzeppelin/contracts
"><code>npm <span class="hljs-selector-tag">i</span> <span class="hljs-keyword">@openzeppelin</span>/contracts
</code></pre><p>删除掉 contracts/Greeter.sol 新建 contracts/NzhlCoins.sol, 内容如下</p><pre data-type="codeBlock" text="// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;

import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;

contract NzhlCoins is ERC20 {
    constructor(uint256 initialSupply) ERC20(&quot;Nzhl Coins&quot;, &quot;nzhl&quot;) {
        _mint(msg.sender, initialSupply);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: UNLICENSED</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.4;</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC20/ERC20.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">NzhlCoins</span> <span class="hljs-keyword">is</span> <span class="hljs-title">ERC20</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> initialSupply</span>) <span class="hljs-title">ERC20</span>(<span class="hljs-params"><span class="hljs-string">"Nzhl Coins"</span>, <span class="hljs-string">"nzhl"</span></span>) </span>{
        _mint(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, initialSupply);
    }
}
</code></pre><p>大概意思就是我们声明了一种名字叫 Nzhl Coins 的代币, 代币符号是 nzhl (类比比特币叫 BitCoin, 代币符号btc), 这里有2点:</p><ol><li><p><code>contract NzhlCoins is ERC20</code> , 表示我们继承ERC20代币标准, 因为基本的代币功能都被openzeppelin ERC20 实现了, 我们进行继承就行了.</p></li><li><p><code>_mint(msg.sender, initialSupply);</code> 这里 _mint 是 ERC20的方法, 作用是用来铸造代币, 这里我们把初始供应的全量代币都发送给合约的创建者(msg.sender). 合约创建本质上就是我们send msg/transaction, 所以我们就是msg.sender.</p></li></ol><h3 id="h-3-and" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3. 测试&amp;部署</h3><p>合约写好之后, 接下来需要简单测试和发布下, 需要改动到2个文件</p><p><strong>hardhat.config.ts</strong></p><p>主要是是声明我们的本地/测试网/主网, 一般的开发流程是本地先开发, 开发的差不多了上测试网进行测试, 最后主网上线. 我们这里用BSC链(和ETH链一样, 只不过是币安主导的, 所以测试网、主网可以直接使用币安提供的provider接口, 即你在代码中看的那个url)</p><pre data-type="codeBlock" text="import { HardhatUserConfig } from &quot;hardhat/config&quot;;
import &quot;@nomiclabs/hardhat-ethers&quot;;
import &quot;@typechain/hardhat&quot;;

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

const config: HardhatUserConfig = {
  solidity: &quot;0.8.4&quot;,
  networks: {
    localhost: {
      url: &quot;http://127.0.0.1:8545&quot;,
    },
    hardhat: {},
    testnet: {
      url: &quot;https://data-seed-prebsc-1-s1.binance.org:8545&quot;,
      chainId: 97,
      gasPrice: 20000000000,
      accounts: [
        &quot;负责部署的钱包私钥, 一般格式是0x3432..., 这个就是上面提到的msg.sender, 后面币会转到这个钱包上&quot;,
      ],
    },
    mainnet: {
      url: &quot;https://bsc-dataseed.binance.org/&quot;,
      chainId: 56,
      gasPrice: 20000000000,
      accounts: [
        &quot;负责部署的钱包私钥, 一般格式是0x3432..., 这个就是上面提到的msg.sender, 后面币会转到这个钱包上&quot;,
      ],
    },
  },
};

export default config;
"><code>import { HardhatUserConfig } <span class="hljs-selector-tag">from</span> "hardhat/config";
import "<span class="hljs-keyword">@nomiclabs</span>/hardhat-ethers";
import "<span class="hljs-keyword">@typechain</span>/hardhat";

// You need <span class="hljs-selector-tag">to</span> export an <span class="hljs-selector-tag">object</span> <span class="hljs-selector-tag">to</span> set up your config
// Go <span class="hljs-selector-tag">to</span> https://hardhat.org/config/ to learn more

const config: HardhatUserConfig = {
  solidity: <span class="hljs-string">"0.8.4"</span>,
  networks: {
    localhost: {
      url: <span class="hljs-string">"http://127.0.0.1:8545"</span>,
    },
    hardhat: {},
    testnet: {
      url: <span class="hljs-string">"https://data-seed-prebsc-1-s1.binance.org:8545"</span>,
      chainId: <span class="hljs-number">97</span>,
      gasPrice: <span class="hljs-number">20000000000</span>,
      accounts: [
        <span class="hljs-string">"负责部署的钱包私钥, 一般格式是0x3432..., 这个就是上面提到的msg.sender, 后面币会转到这个钱包上"</span>,
      ],
    },
    mainnet: {
      url: <span class="hljs-string">"https://bsc-dataseed.binance.org/"</span>,
      chainId: <span class="hljs-number">56</span>,
      gasPrice: <span class="hljs-number">20000000000</span>,
      accounts: [
        <span class="hljs-string">"负责部署的钱包私钥, 一般格式是0x3432..., 这个就是上面提到的msg.sender, 后面币会转到这个钱包上"</span>,
      ],
    },
  },
};

export default config;
</code></pre><p>这里没什么要注意的, 把 accounts 里面换成自己的秘钥就行,</p><p><strong>scripts/deploy.ts</strong></p><p>改成如下, 大概意思就是部署 NzhlCoins 合约, 然后发行数量是10亿.</p><pre data-type="codeBlock" text="import { ethers } from &quot;hardhat&quot;;

const utils = ethers.utils;

async function main() {
  // We get the contract to deploy
  const factory = await ethers.getContractFactory(&quot;NzhlCoins&quot;);
  const contract = await factory.deploy(utils.parseEther(&quot;1000000000&quot;));

  await contract.deployed();

  console.log(&quot;Contract deployed to:&quot;, contract.address);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) =&gt; {
  console.error(error);
  process.exitCode = 1;
});
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title">ethers</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"hardhat"</span>;

const utils <span class="hljs-operator">=</span> ethers.utils;

async <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// We get the contract to deploy</span>
  const factory <span class="hljs-operator">=</span> await ethers.getContractFactory(<span class="hljs-string">"NzhlCoins"</span>);
  const <span class="hljs-class"><span class="hljs-keyword">contract</span> = <span class="hljs-title">await</span> <span class="hljs-title">factory</span>.<span class="hljs-title">deploy</span>(<span class="hljs-params">utils.parseEther(<span class="hljs-params"><span class="hljs-string">"1000000000"</span></span>)</span>);

  <span class="hljs-title">await</span> <span class="hljs-title"><span class="hljs-keyword">contract</span></span>.<span class="hljs-title">deployed</span>(<span class="hljs-params"></span>);

  <span class="hljs-title">console</span>.<span class="hljs-title">log</span>(<span class="hljs-params"><span class="hljs-string">"Contract deployed to:"</span>, <span class="hljs-keyword">contract</span>.<span class="hljs-keyword">address</span></span>);
}

<span class="hljs-comment">// We recommend this pattern to be able to use async/await everywhere</span>
<span class="hljs-comment">// and properly handle errors.</span>
<span class="hljs-title">main</span>(<span class="hljs-params"></span>).<span class="hljs-title"><span class="hljs-keyword">catch</span></span>(<span class="hljs-params">(<span class="hljs-params"><span class="hljs-keyword">error</span></span>) => {
  console.<span class="hljs-keyword">error</span>(<span class="hljs-params"><span class="hljs-keyword">error</span></span>);
  process.exitCode = <span class="hljs-number">1</span>;
}</span>);
</span></code></pre><p>配置好接下来就是正式</p><pre data-type="codeBlock" text="# 用hardhat本地起一个测试Node
npx hardhat node

# 在本地先尝试部署一下
npx hardhat run --network localhost scripts/deploy.ts

# 没问题的话, 执行部署代码把合约部署到bsc测试网
# 这里要求你提供的秘钥对应的地址在测试网中有一定bnb, 没有的话可以
# google 搜索 bsc testnet faucet 找水龙头领取
npx hardhat run --network testnet scripts/deploy.ts

# 如果没有意外, 你将看到
Contract deployed to: 0x5FbDB23156...(这就是你的合约地址)
"><code># 用hardhat本地起一个测试Node
npx hardhat node

# 在本地先尝试部署一下
npx hardhat run <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network localhost scripts<span class="hljs-operator">/</span>deploy.ts

# 没问题的话, 执行部署代码把合约部署到bsc测试网
# 这里要求你提供的秘钥对应的地址在测试网中有一定bnb, 没有的话可以
# google 搜索 bsc testnet faucet 找水龙头领取
npx hardhat run <span class="hljs-operator">-</span><span class="hljs-operator">-</span>network testnet scripts<span class="hljs-operator">/</span>deploy.ts

# 如果没有意外, 你将看到
Contract deployed to: <span class="hljs-number">0x5FbDB23156</span>...(这就是你的合约地址)
</code></pre><p>接下来打开 testnet.bscscan.com 搜索这个合约地址, 你将看到类似</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b79f757c22c7e851cacc457926ccf2fd3b91735cb7ce4326a65b21a867cf6a66.png" alt="testnet.bscscan.com" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">testnet.bscscan.com</figcaption></figure><p>同样的方式依葫芦画瓢在主网上操作一次, 至此, 你的空气币就发布完成了. 当然根据你的需要, 可以修改 contracts/NzhlCoins.sol, 比如在转账中添加一些额外的逻辑, 譬如貔貅盘只允许买入, 少于XX个币不允许卖出就是这么实现的.</p><h2 id="h-4" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">4. 土狗是怎么回事</h2><p>既然已经发币了, 顺便介绍下土狗, 比如刚才我们现在发了10亿个币, 一种玩法常见的玩法是: 去bsc链上组池子, 譬如组 0.5个BNB:10亿个币的LP池子, 这时候由于池子深度浅(只有0.5BNB), 随便多来几个韭菜放个10个BNB就能把你的空气币价格拉飞, 很容易造成币价飞涨, 当韭菜都已经FOMO以后, 这时候你(庄家)可以选择撤出流动性, 因为你占市场的大部分份额, 所以池子里绝大多数的BNB都到了你手里, 这时候韭菜兑换的币已经没有价值了, 所以才叫空气币, 当然真实情况下玩法会很复杂, 不过基本上都是这个原理做的改版&amp;变种.</p><p>所以再次提醒大家, 土狗就是个传销游戏, 别去碰.</p>]]></content:encoded>
            <author>nzhl@newsletter.paragraph.com (nzhl)</author>
        </item>
    </channel>
</rss>