主页 > imtoken冷钱包手机版 > 教程 | 以太坊编程简介,第 3 部分

教程 | 以太坊编程简介,第 3 部分

imtoken冷钱包手机版 2023-04-27 07:42:01

以太坊eth挖矿详细教程_以太坊教程_以太坊注册及挖矿教程

这是我们以太坊入门指南的第三部分。 如果您还没有阅读该系列的第一和第二部分(编者注:中文版见文末),我强烈建议您阅读前两部分以更好地理解本文。

享受学习过程,如果您有任何问题、更改建议或反馈,请告诉我。

目录

1.迈出第一步

2.与合约交互

3. 现实世界的框架和工具

3.1. 通过松露部署

3.2. 测试智能合约

3.3. 打开飞艇

4. 真正的DApp,代币市场——敬请期待

3. 现实世界的框架和工具

您可能已经注意到,我们所做的大部分工作都依赖于人。 尽管这是一个新兴行业,但一些工具可以简化开发过程。 其中一些描述如下。

3.1. 通过松露部署

到目前为止,我们与合约交互的唯一方式是通过节点控制台手动将它们部署到 testrpc 节点,并使用 Web3 加载它们。 现在,我想向您介绍 Truffle。 它是一个以太坊开发框架,具有调试、部署和测试智能合约等功能。

我们要做的第一件事是通过 Truffle 部署合约。 让我们为此创建一个新目录,通过运行以下命令安装 Truffle,然后启动我们的项目:

$ mkdir truffle-experiment
$ cd truffle-experiment/
$ npm install truffle@4.0.4
$ npx truffle init

您将看到创建了一些文件夹和文件。 我们的目录如下所示:

truffle-experiment/
├── contracts/
│   └── Migrations.sol
├── migrations/
│   └── 1_initial_migration.js
├── test/
├── truffle.js
└── truffle-config.js

智能合约应放在contracts文件夹中。 迁移文件夹中的 javascript 文件将帮助我们在网络上部署合约。 您可能还会在第一个文件夹中看到迁移合同,在这个文件夹中,我们的迁移历史将存储在区块链上。 测试文件夹最初是空的,专门用来存放我们的测试文件。 最后,您将看到两个文件,truffle.js 和 truffle-config.js。 我们暂时跳过它们,但您可以查看它们的文档以了解详细信息。

现在,让我们把无聊的事情放在一边,专注于有趣的事情。 为了说明我们如何通过 Truffle 部署合约,请使用与本指南上一篇文章中相同的代币合约示例。 请复制此代码并将其粘贴到合同文件夹中的 MyToken.sol 文件中。 之后,创建一个名为 2_deploy_my_token.js 的新迁移文件并将以下行复制到其中:

const MyToken = artifacts.require('./MyToken.sol')
module.exports = function(deployer) {
  deployer.deploy(MyToken)
}

如您所见,迁移将我们的令牌部署到网络。 这一次,我们不需要运行 testrpc 节点,因为 Truffle 已经自带了一个 mock 节点,可以用于开发和测试目的。 我们只需要打开一个运行 npx truffle develop 的开发控制台,并在其中使用 truffle migrate 运行迁移。 之后,您将看到以下输出值:

truffle(develop)> truffle migrate
Using network ‘develop’.
Running migration: 1_initial_migration.js
Deploying Migrations…
… 0xf5776c9f32a9b5b7600d88a6a24b0ef433f559c31aaeb5eaf6e2fc5e2f7fa669
Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0
Saving successful migration to network…
… 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956
Saving artifacts…
Running migration: 2_deploy_my_token.js
Deploying MyToken…
… 0xc74019c2fe3b3ef1d4e2033c2e4b9fa13611f3150f8b6b37334a8e29e24b056c
MyToken: 0x345ca3e014aaf5dca488057592ee47305d9b3e10
Saving successful migration to network…
… 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0
Saving artifacts…

我们只关注 MyToken: 0x345ca3e0...305d9b3e10 这行,这是我们部署的代币合约的地址。 默认情况下,Truffle 会为模拟节点预先提供 10 个虚拟 ETH 地址,就像使用 testrpc 时一样。 我们可以通过 web3 以太账户访问这个地址列表。 此外,Truffle 使用列表中的第一个地址(索引为 0 的地址)部署这些合约,这意味着它将成为 MyToken 的所有者。

鉴于 Web3 在 Truffle 控制台中可用,您可以运行以下命令来检查所有者的余额:

truffle(develop)> owner = web3.eth.accounts[0]
truffle(develop)> instance = MyToken.at('[DEPLOYED_ADDRESS]')
truffle(develop)> instance.balanceOf(owner)

注意:不要忘记将 [DEPLOYED_ADDRESS] 替换为 Truffle 提供的已部署合约的地址,例如:0x345ca3e0...305d9b3e10。

我们也可以先发送一些代币到另一个地址,然后查看更新后的余额:

// send tokens
amount = 10
recipient = web3.eth.accounts[1]
txHash = instance.sendTokens(recipient, amount, { from: owner })
// check balances
instance.balanceOf(owner)
instance.balanceOf(recipient)

您现在可以看到收款人的账户中有 10 个代币! 我们可以通过以下代码查询交易信息:

web3.eth.getTransaction(txHash)

3.2. 测试智能合约

接下来,关于 Truffle 的更有趣和有用的事情之一是我们可以测试我们的合约。 该框架允许您以两种不同的方式编写测试代码:Javascript 和 Solidity。 在这篇文章中,我们将学习一些关于最常用选项 JS 测试的基础知识。

Truffle 在幕后使用 Mocha 作为测试框架,并使用 Chai 来执行断言。 如果你不熟悉这两个库也没关系,它们真的很简单,执行的语法与其他测试框架类似。 如果需要,您还可以阅读官方的 Mocha 文档。

准备好了,让我们介绍第一个测试用例。 我们需要在测试文件夹中创建一个 MyToken.js 文件。 创建后,将下面的代码粘贴到其中。

const MyToken = artifacts.require('MyToken')
contract('MyToken', accounts => {
  it('has a total supply and a creator', async function () {
    const owner = accounts[0]
    const myToken = await MyToken.new({ from: owner })
    const creator = await myToken.creator()
    const totalSupply = await myToken.totalSupply()
    assert(creator === owner)
    assert(totalSupply.eq(10000))
  })
})

要运行 Truffle 测试,您只需使用命令 npx truffle test。 温馨提示:这里不需要在后台运行rpc测试节点,因为Truffle会帮你运行。

您可能已经注意到,这是我们第二次在代码中使用 artifacts.require() 。 第一次是在编写 MyToken 迁移代码时,现在您可能想知道这意味着什么。 工件是分别编译每个合约的结果。 这些工件将放置在相对于项目根目录的 build/contracts/ 目录中。 我们通过 artifacts.require() 告诉 Truffle 我们想要与之交互的合约。 仅提供合约名称并实现抽象。 您可以阅读本文以了解有关 Truffle 工件的更多信息。

剩下唯一重要的就是contract()函数,它确实类似于Mocha的describe()函数。 这就是 Truffle 保护洁净室环境的方式。 Truffle 会将你的合约重新部署到你的以太坊客户端,并在每次调用时提供可用账户列表。 但是,我们不建议使用已部署的合约实例进行测试。 让每个测试管理自己的实例会更好。

现在我们了解了一些关于 Truttle 测试的基础知识,让我们介绍一个更有趣的场景。 我们将测试账户之间的代币转账:

it('allows token transfers', async function () {
  const owner = accounts[0]
  const recipient = accounts[1]
  const myToken = await MyToken.new({ from: owner })
  await myToken.sendTokens(recipient, 10, { from: owner })
  const ownerBalance = await myToken.balanceOf(owner)
  assert(ownerBalance.eq(9990))
  const recipientBalance = await myToken.balanceOf(recipient)
  assert(recipientBalance.eq(10))
})

最后,虽然一些极端的例子会很好,但我会把这些留给你去尝试。 在这里查看其他测试示例,从中你也可以看到我是如何使用Truffle来完成这个迷你DApp的。 您会看到我设置的属性与我们在上一篇文章中为应用程序所做的相同。 唯一改变的是我们使用 Truffle 推出测试节点,部署我们的合约并添加一些测试以确保我们的合约按我们预期的方式工作。

3.3. 打开飞艇

如果您已经读到这里,您可能听说过 OpenZeppelin。 如果您还没有,您只需要知道它是帮助您构建智能合约的最常用框架。 它是一个开源框架,提供可重用的智能合约来构建分布式应用程序、协议和组织,从而降低使用经过社区测试和审查的标准代码带来的安全风险。

鉴于代币合约数量众多,以太坊社区在两年前创建了一个名为 ERC20 的代币标准。 这个想法是允许 DApp 和钱包以一种通用的方式跨多个接口和 DApp 处理代币。

也就是说以太坊教程,一些最常用的 OpenZeppelin 合约是 ERC20 用例也就不足为奇了。 这就是我们第一步要对 MyToken 合约做的事情:使其与 ERC20 兼容。 让我们首先安装 OpenZeppelin 框架,它需要运行:

$ npm install zeppelin-solidity

现在,看看我们使用一些 OpenZeppelin 合约构建的新用例。

import 'zeppelin-solidity/contracts/token/BasicToken.sol';
import 'zeppelin-solidity/contracts/ownership/Ownable.sol';
contract MyToken is BasicToken, Ownable {
  uint256 public constant INITIAL_SUPPLY = 10000;
  function MyToken() {
    totalSupply = INITIAL_SUPPLY;
    balances[msg.sender] = INITIAL_SUPPLY;
  }
}

如您所见,我们删除了许多核心功能。 好吧,我们并没有删除这些功能,我们只是给 OpenZeppelin 合约这个指令。 这非常有用,因为我们正在重用经过审计的安全代码,这意味着我们减少了合约的攻击面。

此外,您可能已经注意到,我们正在从两个 OpenZeppelin 合约 Ownable 和 BasicToken 扩展我们的代币合约。 是的,Solidity 支持多重继承,知道顺序很重要对您来说非常重要。 不幸的是,这超出了本文的范围,但您可以在此处找到更多详细信息。

如上所述,我们正在从 Ownable 扩展 MyToken。 我们来看看这份合约:

contract Ownable {
  address public owner;
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
  function Ownable() public {
    owner = msg.sender;
  }
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }
}

-OpenZeppelin 可拥有合约-

Ownable提供三个主要功能:

非常有用,对吧? 另一方面,我们也在扩展 BasicTokencontract(基础代币合约)。 让我们了解一下它的功能:

import '../math/SafeMath.sol'; contract ERC20Basic {  uint256 public totalSupply;  function balanceOf(address who) public view returns (uint256);  function transfer(address to, uint256 value) public returns (bool);  event Transfer(address indexed from, address indexed to, uint256 value); } contract BasicToken is ERC20Basic {  using SafeMath for uint256;  mapping(address => uint256) balances;  function transfer(address _to, uint256 _value) public returns (bool) {    require(_to != address(0));    require(_value <= balances[msg.sender]);    balances[msg.sender] = balances[msg.sender].sub(_value);    balances[_to] = balances[_to].add(_value);    Transfer(msg.sender, _to, _value);    return true;  }  function balanceOf(address _owner) public view returns (uint256 balance) {    return balances[_owner];  } }

-OpenZeppelin 基础代币合约-

相信你对这段代码比较熟悉。 这基本上就是我们过去在 MyToken 合约中所做的。 这里有一些细微的差别,因为我们没有遵循 ERC20 标准的原始版本。 我们这里说的 sendTokens 只是一个转账,除了触发转账事件外,它执行几乎相同的行为。

另一件重要的事情是使用 SafeMath 编写 uint256 代码。 SafeMath 是 OpenZeppelin 推荐的用于带安全检查的数学运算的库。 这是另一个常用的合约,因为它保证数学运算不会溢出。

OpenZeppelin 本身就是一个完整的领域,请花时间深入了解它。 您可以先阅读并密切关注已审查代码库的安全细节。

我们已经了解了以太坊领域中的两个令人惊叹的工具,它们肯定会让您的开发过程更加轻松。 Truffle 将帮助您进行测试和部署,而 OpenZeppelin 将帮助您使用经过审查的代码库编写安全的智能合约。

感谢您阅读本文,请记住以太坊教程,我们欢迎任何问题、反馈和建议! 如果您喜欢本文,请期待本指南的第四部分,重点介绍如何构建一个真正的DApp,代币市场!

如果您有兴趣讨论智能合约安全问题,请加入我们的 slack 频道,关注我们的 Medium,或提交工作申请! 我们也可以做智能合约的安全开发和审查工作。

原文链接: