第19讲|上手搭建一条自己的智能合约(代码片段)

sueyyyy sueyyyy     2023-01-08     744

关键词:

  上一篇我们聊到了区块链智能合约,我主要介绍了智能合约的概念,但是并没有给你提供智能合约的实际运行案例,那么今天,我们就自己动手写一个智能合约,并且介绍一下智能合约标准模板,供你参考学习, 并搭建起自己的智能合约。

  本篇将以以太坊作为基础知识进行讲解,本篇面向没有任何智能合约基础的人群,所以配备了较多的插图和操作命令,如果你正在收听音频,可以点击文稿查看,希望读完这篇文章可以帮助你快速入门智能合约。

搭建一条智能合约

  在实际操作智能合约之前,我们首先回顾一下以太坊,以太坊又称以太坊钱包。以太坊钱包提供了包括账户管理,以太坊转账、Dapp部署与使用在内的一些常规功能。

  以太坊社区提供了多种语言实现的客户端和开发库,多数客户端支持JSON-RPC2.0标准,目前支持的客户版本有Go-ethereum(Go语言)、Parity(Rust语言)、Cpp-ethereum(C++语言)、Ethereum-lib(Javascript)、EthererumJ(Java语言)、Pyethapp(Python语言),基本涵盖了主流编程语言。

技术分享图片

图片来自以太坊官方文档

   官方推荐使用的版本是Go-ethererum,这是Go语言实现的版本,又称Geth客户端。

  需要提醒你的是,这里客户端的实现语言并不是要求用户熟悉相应的编程语言,这里的用户是指Dapp开发者,比如在操作Geth客户端的时候,用户其实并不需要了解Go语言。

1.下载与安装Geth

  本文使用Geth来进行测试,首先我们要获取Geth客户端,如果用户使用的是Ubuntu环境的话,可以直接从PPA安装。

 # apt-get install software-properties-common
 # add-apt-repository -y ppa:ethereum/ethereum
 # apt-get update
 # apt-get install ethereum

  安装成功后,我们可以查看Geth的版本。

技术分享图片

  表示我们已经安装成功,当然你可以也可以编译安装,由于篇幅有限,你可以另寻资料进行尝试。

2.搭建以太坊私链

  如果在以太坊的主网上运行和开发测试智能合约,这是不明智的,因为会消耗真实的以太币,不过我们可以使用Geth搭建一条属于自己的以太坊区块链,也就是以太坊私链。

  怎么搭建呢?其实很简单,只需要修改配置文件和一些运行参数即可。

   
"config": 
    "chainId": 98,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
,
"difficulty": "200000000",
"gasLimit": "2100000",
"alloc": 
    "7df9a875a174b3bc565e6424a0050ebc1b2d1d82":  "balance": "300000" ,
    "f41c74c9ae680c1aa78f42e5647a62f353b7bdde":  "balance": "400000" 

  然后执行:

    $ geth --datadir /root/geth-test/ init genesis.json

  这样,我们就初始化了属于自己的创世区块信息。

  接下来我们创建一个账户,由于是用户私链挖矿,只有你一个人挖矿,所以使用CPU挖矿完全没有问题。

  我们通过如下命令进入Geth命令行交互页面:

 $ geth --datadir /root/geth-test/ --networkid 98 console

技术分享图片

  如上图所示的那样,运行通过。

personal.newAccount()

  我们创建了一个新账户,这个账户就是EOA账户,并通过eth.getBalance获取了当前地址的余额,显示为0。

  输入Exit退出后,我们开始以挖矿模式启动,这里我们最好记录一下我们的地址:

0xf8f7ff845596f0bab1e973859bfcaec6cd2a82ab

  我们使用如下命令启动挖矿,注意在Etherbase的地方填上述地址:

$ geth --datadir /root/geth-test/ --networkid 98 --mine --minerthreads=1 --etherbase=0xf8f7ff845596f0bab1e973859bfcaec6cd2a82ab

  以太坊的PoW挖矿算法是内存困难型的,首先需要生成DAG,这个视你设备的性能而定,需要耗费一定时间,请耐心等待,如下图所示,我们可以看到DAG生成非常耗费时间。

技术分享图片

  在我的远程开发机上一共耗费了6分半,又经过了4分钟,我挖到了第一个块,如下图所示。

技术分享图片

  这期间机器的负载如下。

技术分享图片

  可以看到CPU和内存占用很高,我这里使用测试的机器是2Core 4GB Ubuntu16.04。

  现在我们再去检查一下Etherbase所指向地址的余额。

技术分享图片

  可以看到已经有5个以太币了,以太币的最小单位wei,所以5后面18个零表示5个以太币。

3.编写并部署属于自己的智能合约

  智能合约的开发与钱包是独立的,用户可以使用IDE进行调试等操作,目前Dapp的IDE并不多,常见有Truffle、Embark、Remix几种;

  这篇文章中,我并不使用IDE,这里仅仅会给出一些示例代码,即经典的Hello Word,你如果想尝试编写自己的智能合约,可以使用在线IDE。

  https://ethereum.github.io/browser-solidity/

  首先我们要获取Solidity编译器,通过 apt-get install solc 来安装。

  安装成功后,我们新建一个Solidity源码文件,命名为helloword.sol,并且写入代码如下。

pragma solidity ^0.4.11;
contract helloWorld 
function renderHelloWorld () returns (string) 
 return helloWorld;

  执行 solc --bin helloword.sol 获得EVM二进制码。

技术分享图片

  编译器警告我们暂时不必理会,接下来我们还需要生成ABI部署参数,使用命令 solc --abi helloword.sol。

技术分享图片

  开始部署,我们进入console,

  定义code和abi两个变量如下,注意code的值最前面有0x,二进制数据是用十六进制表示的。

 >code="0x6060604052341561000f57600080fd5b6101578061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063942ae0a714610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc610117565b6040805190810160405280600a81526020017f68656c6c6f576f726c6400000000000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820fcce0b6910e479539e4796b7d56620a6f90e03ba47449c843bec54958f68bf700029"

>abi=["constant":false,"inputs":[],"name":"renderHelloWorld","outputs":["name":"","type":"string"],"payable":false,"stateMutability":"nonpayable","type":"function"]

  你可以在控制台分别执行,由于结果比较长,这里就不放出来了。

  // 这一步解锁账户,用于方便部署合约 
  >personal.unlockAccount("0xf8f7ff845596f0bab1e973859bfcaec6cd2a82ab")
   // 使用上述定义的abi变量生成合约信息
  >myHelloWorld=eth.contract(abi)
  // 注入code信息,激活合约
>contract=myHelloWorld.new(from:"0xf8f7ff845596f0bab1e973859bfcaec6cd2a82ab",data:code,gas:1000000)   

  最终执行结果如下。技术分享图片

  我们可以通过txpool来查看未确认的交易。

技术分享图片

  接下来只要等待出块即可,你的合约就会成为正常运行的合约了,否则合约还不可以调用。

  由于我本地挖矿出块异常缓慢,所以我尝试了Remix IDE,运行后我们可以得到如下结果。技术分享图片

  至此一个简单的HelloWord智能合约就生成啦,不过它的运行成本非常高昂,所以我们极力建议使用在一些方便的虚拟环境中。

智能合约标准模板

  当任何人都可以写代码自定义业务逻辑的时候,也就意味着需要一套标准让人们降低开发门槛,标准化的接口让产品之间可以协作。那么我们接下来就来讨论一下以太坊上的三种智能合约标准模板。

  这三种模板都与Token有关。那么首先我们就来区分一下数字货币与Token的概念,数字货币一般指一个区块链项目的平台代币,比如以太坊上的以太币,元界上的ETP都是基础代币。

  而Token往往代表了一种资产,这些资产在已经存在的其他区块链之上运行,资产还可以像商品一样交易,例如消费积分、游戏虚拟资产。Token离具体的区块链应用也会更近,因为区块链应用的项目方通常也是Token的发行方。

  目前最广泛使用的三种Token标准都是基于以太坊的,它们分别是ERC20、ERC223、ERC721。这里的ERC表示Ethereum Request for Comments,翻译过来就是以太坊意见征求稿。

1.ERC20

  2015年11月,V神在Github上提交了ERC20代币的技术标准,随后2016年到2017年,大量的区块链项目都使用ERC20作为工具进行ICO。这使得ERC20成为了区块链整个行业内的Token标准,可见这种标准的影响之大。

  实际上ERC20代币是一类运行在以太坊区块链上的智能合约,只不过这些合约代码遵循一定的规范,这个规范就是ERC20标准,它规定了跨Dapp转移Token、Token交易以及一些使用接口。

  ERC20一共定义了6个函数和两个触发事件,他们都是使用Solidity语言编写的。

  6个函数描述了如何转移以及Token的相关数据如何被访问,市面上99%的ERC20 Token都可以找到这6个函数。2个事件提供了Approve和Transfer的格式化输出。

  下面我们重点看一看ERC20的接口。

 // ---------------------------------------------
 // ERC Token Standard #20 Interface
 // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
 // -------------------------------------------
contract ERC20Interface 
 function totalSupply() public constant returns (uint);
 function balanceOf(address tokenOwner) public constant returns (uint balance);
 function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
 function transfer(address to, uint tokens) public returns (bool success);
 function approve(address spender, uint tokens) public returns (bool success);
 function transferFrom(address from, address to, uint tokens) public returns (bool success);
 event Transfer(address indexed from, address indexed to, uint tokens);
 event Approval(address indexed tokenOwner, address indexed spender, uint tokens);

Allowance:允许多次创建两个不同的地址之间的单向交易,Token的拥有者可以从此智能合约中提取Token;

Approve:这个函数需要引用Allowance,顾名思义,它定义了Token的拥有者同意创建属于自己的交易,这个函数要求两个参数作为输入,分别是花费者的地址,以及发送金额;

BalanceOf:定义了查询目标地址账户余额的接口;

Transfer和TransferFrom:定义了Token如何转移以及执行转移过程;

TotalSupply:定义了这个Token最大发行量。

  上面我们简要介绍了ERC20标准合约的接口,下面我们来看看升级版的ERC20。

2.ERC223

  在某些情况下,ERC20也有些缺陷。例如某人使用ERC20发送100个Token到另外一个账户,如果目标账户是一个合约账户,目标账户的合约代码如果不兼容ERC20 标准怎么办呢?

  这一点非常有可能,由于合约代码无法识别交易,所以这笔交易就会被拒绝。

  我们知道以太坊使用的并不是UTXO,这意味着合约之间不满足ACID,那么很遗憾,发送方的这100个Token就永久地丢失了。

  为了解决这个问题,非官方的社区开发者提交了ERC223模板,可以解决这个问题,使用者需要把既存的ERC20合约升级到ERC223合约。

3.ERC721

  2018年初,有一个区块链游戏火了,叫做以太坊养猫游戏,这个游戏也是一个智能合约。它基于ERC721标准,实际上它也是一种Token标准。

  ERC721与ERC20最大的区别是:ERC721定义了每一份Token都是唯一的,它们有唯一的标识。例如芒果和米饭是两种不同属性的资产,从物理世界来看,他们是不能直接混在一起使用的,我们不能把芒果加到大米中。

  这样一来,ERC721中Token的含义也转变成了一种物权所有权凭证,不再是ERC20中的同质资产。

总结

  今天我们介绍了以太坊钱包,手把手教你搭建了一条以太坊私链,并告诉你如何编译和部署智能合约,最后我还介绍了三种流行的智能合约模板,希望能帮助你上手并能深入地理解智能合约。

  参考链接:

  1. http://www.ethdocs.org/en/latest/ethereum-clients/go-ethereum/index.html
  2. https://github.com/ethereum/wiki/wiki/JSON-RPC
  3. http://remix.ethereum.org
  4. https://github.com/ethereum/go-ethereum/wiki/Private-network
  5. https://theethereum.wiki/w/index.php/ERC20_Token_Standard

第156篇用智能合约给自己做个钱包(代码片段)

 本文使用solidity合约实现私人钱包功能;1.简单钱包实现最简单的钱包功能:任何人都可以给我发Ether;只有我可以提取Ether;//SPDX-License-Identifier:MITpragmasolidity^0.8.13;contractEtherWalletaddresspayablepublicowner;constructor()owner=payable(msg 查看详情

第156篇用智能合约给自己做个钱包(代码片段)

...不能直接接收 Ether,必须调用deposit;任何人都可以把自己的 Ether存入钱包;每个人可以提取自己的 查看详情

区块链(代码片段)

...坊私链private-network搭建以太坊私有链笔记以太坊私有链搭建一台电脑上部署多个节点。安装go-ethereum#下载代码gitclonehttps://github.com/eth 查看详情

搭建一款属于自己的全能hexo(代码片段)

目录切换镜像源方法1方法2HEXO的安装和插件文档加密插件文档置顶插件一键上传插件高级文本插件清空缓存SSH秘钥EXO常用指令一键部署指令增加页面指令收集了一些hexo使用时常常使用到的东西切换镜像源方法1切换淘宝镜像npmconf... 查看详情

第81篇以太坊可信支付智能合约(代码片段)

本文环境:     区块链版本:以太坊POA联盟链     节点版本:geth1.9.19     操作系统:windows64合约源码:https://github.com/BugrahanOzturk/Ethereum-Payment-Chann 查看详情

第一行代码:以太坊-使用更多的工具编写和测试智能合约(代码片段)

...文中已经使用了Remix环境运行和测试了本书编写的第一个智能合约程序,不过编写和测试智能合约的测试方式很多,例如,在testrpc环境测试;在IntellijIDEA集成开发环境中用Solidity语言编写智能合约;在纯Web环境中测试智能合约;... 查看详情

第79篇nft市场智能合约(代码片段)

本文环境:          区块链版本:以太坊POA联盟链          节点版本:geth1.9.19       &nb 查看详情

第20讲|区块链项目详解:比特股bts

  前面两篇我们都聊了智能合约的话题,智能合约可以说是当下区块链最热的概念了,在多数人眼里,没有智能合约的区块链价值几乎就大打折扣。  那么说,实际上是不是这样呢,我们今天就来聊聊一个并没有开放式智能... 查看详情

第80篇以太坊签名验证智能合约(代码片段)

本文环境:          区块链版本:以太坊POA联盟链          节点版本:geth1.9.19       &nb 查看详情

第一行代码:以太坊-使用solidity语言开发和测试智能合约(代码片段)

智能合约是以太坊的核心之一,用户可以利用智能合约实现更灵活的代币以及其他DApp。不过在深入讲解如何开发智能合约之前,需要先介绍一下以太坊中用于开发智能合约的Solidity语言,以及相关的开发和测试环境。智能合约就... 查看详情

通学智能合约系列(十八)--函数的重写与自我销毁(代码片段)

hello,大家好,通学智能合约系列文档已经出栏了,关注微信公众号【通学技术】,回复智能合约即可获取,大家快来领取吧~~~~~~~~~~~~~~~~~~~~~~~~~~~~~··19、继承中函数的重载重写在这节内容中,视频中的老... 查看详情

第88篇多重签名智能合约(0.8.5)(代码片段)

...约版本:solidity^0.8.5本文介绍一种基于以太坊的多重签名智能合约;本篇合约与前两篇文档合约有类似的地方,也有独到的地方,本文主要讲解其中的不同点,部分内容可能较简略,如果有兴趣,请参考前两篇文档;1.合约源码//... 查看详情

第86篇多重签名智能合约(0.4.24)(代码片段)

...约版本:solidity^0.4.24本文介绍一种基于以太坊的多重签名智能合约;1.合约源码pragmasolidity^0.4.24;contractMultipleSignatureaddressprivateowner;uint256publicsignEnd;uintpublicpassRates;uintprivatetransactionNum;uintpublicmanagerCount=1;modifierisOwnerrequire(owner==msg.sen... 查看详情

eos智能合约开发-智能合约编写(代码片段)

...兼容,导致生产上出问题.下面我们讲用以vscode做演示.配置智能合约项目先用vscode打开eosio.cdt项目代码目录,按提示安装相应的 查看详情

如何编写一个投票功能的智能合约(代码片段)

...据被篡改。本篇实现的合约思路是对于每次投票表决都创建一 查看详情

智能合约语言solidity教程系列4-数据存储位置分析(代码片段)

写在前面Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,建议你先看以太坊是什么这部分的内容官方英文文档讲的不是很透,因此我在参考Solidity官方文档(当前最新版... 查看详情

web3开发系列教程—创建你的第一个智能合约部署第一个智能合约(代码片段)

...并且不知道从哪里开始,或者你只是想了解如何部署智能合约并与之交互,那么本指南适合你。我们将介绍使用虚拟钱包(Metamask)、Solidity、Hardhat和Alchemy在Goerli测试网络上创建和部署一个简单的智能合约(如果你还不... 查看详情

第83篇笔记-猜拳游戏智能合约(代码片段)

本合约实现经典的包袱剪刀锤子猜拳游戏;源码:pragmasolidity0.5.10;contractrpsaddresspublicowner;uint256publicbalance;uint256publicgamesPlayed;stringpubliclastResult;enumhandROCK,PAPER,SCISSORSenumresultWIN,LOSE,TIEeven 查看详情