在上一篇文章中,我展示了如何为RSK Mainnet编写Solidity ERC20代币,如何导入和使用OpenZeppelin库和合约,以及如何使用Truffle来部署和交互我们的智能合约。
虽然我们使用Truffle成功完成了我们的任务并实现了我们的目标,但最终这个套件在你发送交易,部署或管理帐户时还是可能会出现一些问题。在我们的案例中,在遵循之前的文章说明时,我在使用Truffle管理新创建的帐户和发送交易时就遇到了一些问题。
我遇到的第一个问题是冻结了SBTC的部分资金,RSK Labs团队让我测试了Mainnet(感谢Maximiliano)。虽然我已经解锁了帐户,但节点仍然问我创建的帐户的私钥(正如我们在第一篇文章中看到的):
truffle(rsk)> web3.personal.newAccount(‘somePassword’)
truffle(rsk)> web3.personal.unlockAccount(web3.eth.accounts[0],'somePassword')
出于这个原因,为了保留我的少数SBTC的安全性,我在合约中添加了销毁功能,以防万一出现问题。
当我尝试与已部署的合约进行交互时,出现了第二个问题。在发送交易时,Truffle将其主体发送到具有数据和其余参数的节点(正如我在rsk.log文件中看到的那样)。但是,在20分钟之后,交易从未包含在任何块中,并且节点也没有收据或其哈希值。
我解决这个问题的方法是通过node.conf
文件中配置cors
参数,以允许Metamask连接到节点。然后,通过将有问题的函数及其参数编码为十六进制字符串并输入数据字段来发送交易。在使用与Truffle发送的交易相同的nonce
值发送后,它最终被包含在内。
不要误会我的意思,Truffle套件对于开发人员来说是一个很好的工具,但是如果你在开发智能合约时不时遇到一些问题,请保持专注并继续阅读。
我将在这里讨论的工具是Web3的Python版本:Web3.py。
由于rskj
的行为就像以太坊节点(即它提供了相同的JSON-RPC API),我们可以使用其他实现来与之交互。最受欢迎的Web3版本是用JavaScript(Web3.js)编写的版本。但自11月以来,Web3.py项目的更新率更高,大大提高了其可用性。此版本还允许比Web3.js更友好的交互体验。
在本文中,我们将讨论上一篇文章中使用的相同ERC20代币合约的部署和交互,以比较两种工具的可用性。
从rskj 4.2开始,RSK Testnet重新上线。出于这个原因,并且因为我们之前无法使用它,我们将在本文的网络上部署和测试我们的合约。
Web3.py是用Python3编写的。如果你之前从未使用过Python,那么你可能需要一些软件包。否则,当我们在我们的环境中安装Web3.py时,将在编译期间出错。我们安装它们:
$ sudo apt-get install gcc
$ sudo apt-get install python3-dev
我们希望将Web3.py
的实例与其他个人Python模块分开。为此,我们需要创建一个Python的虚拟环境:
$ sudo apt install virtualenv
$ virtualenv -p python3~ / web3_py
然后,我们使用以下命令激活实例:
$ source web3_py/bin/activate
在终端中,我们应该能够看到命令提示符:
(web3_py) user@computer:~$
这意味着我们的Python虚拟环境现在处于活动状态。现在,我们将安装项目的库:
(web3_py) user@computer:~$ pip install web3
你不应该看到任何错误。
为了改善解释器的外观,我建议安装IPython
(不,不是从App Store):
(web3_py) user@computer:~$ pip install ipython
如果我们想休息并退出虚拟环境,我们可以这样做:
(web3_py) user@computer:~$ deactivate
我们将使用测试网络来部署我们的合约,所以请随时再次检查我们已经讨论过如何更改网络的第一篇文章(并自行更改!:))。
现在,我们有一个合适的环境来启动我们的脚本。
编译我们的.sol
(Solidity合约代码)不是Python的工作。这是我们的Solidity
编译器的一项任务:Solc
。要安装它的最新稳定版本,我们这样做:
$ sudo add-apt-repository ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install solc
有了这个,我们应该能够像这样编译我们的合约:
$ solc .sol --bin --abi --optimize -o /
其中
是Solidity代码文件,
是我们构建的ABI和字节码文件的位置。
一旦我们从虚拟环境中打开Python,我们就需要导入Web3和Json等库,但在此之前,必须注意一个问题。在某些情况下,即使使用Python3,使用双TAB的自动完成功能也不起作用。要解决此问题,需要导入一些库,执行以下操作:
>>> try:
... import readline
... except ImportError:
... print("Module readline not available.")
... else:
... import rlcompleter
... readline.parse_and_bind("tab: complete")
之后,我们应该激活此功能。现在,要导入其余的库,我们只需执行以下操作:
>>> from web3 import Web3
>>> import json
然后我们准备将Python连接到我们已经运行过的节点,我猜想。否则,我们从以下开始:
$ sudo service rsk start
连接对象按以下方式实例化:
>>> web3 = Web3(Web3.HTTPProvider("http://MACHINE:PORT"))
其中MACHINE
和PORT
是我们在node.conf
文件中指定的IP,名称和端口。默认情况下,它是localhost:4444
。
为了测试一切是否成功,我们检查Python解释器中的块编号,如下所示:
>>> web3.eth.blockNumber
现在,我们继续部署合约。
我们将基于OpenZeppelin库部署ERC20令牌合约。为了与我以前的文章保持一致,我像以前一样重命名这两个帐户,输入:
>>> acc0 = web3.eth.accounts[0]
>>> acc1 = web3.eth.accounts[1]
在另一个终端,我们转到合约代码所在的文件夹,然后我们使用Solc
编译它,如下所示:
$ solc CoinFabrikToken.sol --bin --abi --optimize -o Compiled/
在Compiled
文件夹中,我们不仅找到了合约的ABI和字节码,还找到了它的编译依赖项。然而,我们只需要主合约中的那些。
要将这两个文件导入Python VM
,我们可以这样做:
>>> with open("./Compiled/CoinFabrikToken.abi") as contract_abi_file:
... contract_abi = json.load(contract_abi_file)
>>> with open("./Compiled/CoinFabrikToken.bin") as contract_bin_file:
... contract_bytecode = '0x' + contract_bin_file.read()
然后,我们可以创建合约的实例,为它提供ABI和字节码:
>>> cfToken = web3.eth.contract(abi=contract_abi, bytecode=contract_bytecode)
之后,我们创建并部署合约输入:
>>> tx_hash = cfToken.constructor().transact(transaction=tx_args0)
我们保存交易的哈希有两个原因:检查状态,地址和更多参数,因为我们可以使用函数waitForTransactionReceipt
来知道合约何时被挖掘。
要计算合约的部署地址,我们需要用于部署合约的地址,acc0
和交易的nonce
。我们有两个东西,所以我们导入了几个库,然后我们将函数调用如下(感谢M. Stolarz的这个发现):
>>> import rlp
>>> from eth_utils import keccak, to_checksum_address
>>> contract_address = to_checksum_address('0x' + keccak(rlp.encode([bytes(bytearray.fromhex(acc0[2:])), web3.eth.getTransaction(tx_hash).nonce]))[-20:].hex())
地址在我们的实例中设置如下:
>>> cfToken = web3.eth.contract(address = contract_address, abi = contract_abi, bytecode = contract_bytecode)
之后,我们的合约将被写入区块链。
Python的一个功能是我们可以创建所有命令的脚本,然后像这样一起执行它们:
>>> exec(open("deploy_cfToken.py").read())
这意味着我们可以像Truffle一样在一行中部署合约(但知道它的作用!= D)。
我们部署的测试网络Token合约现在为0x7C0c436e1E8dCd270a7A306B5AE8A2996f6A25dD
。
image
在我们部署了代币之后,应该已经创建了一个实例来轻松调用它。要调用未修改区块链的函数,例如getter,我们会:
>>> cfToken.functions.FUNC_CALL().call()
其中FUNC_CALL
是不修改区块链的合约的可调用函数。
如果我们想修改区块链(设置值,进行计算等),正确的语法是:
>>> cfToken.functions.FUNC_SET(PARAMETERS).transact(TXARG)
其中FUNC_SET
是修改区块链的合约的函数,PARAMETERS
是函数采用的值,TXARG
是交易的参数,如下所示:
>>> txargs0 = {“from”: acc0 , “gasPrice”: 0, “gas”: 3000000}
我们可以检查我们名字的变量是否为空:
>>> cfToken.functions.getON().call() // ‘’
image
因此,和以前一样,如果我们尝试修改变量而不是所有者acc1
,则交易不成功。
>>> cfToken.functions.setON('Andrés Bachfischer').transact(txargs1)
image
提示:如果收到内部服务器错误,你的帐户可能会再次被锁定。它有一个超时。
因此,如果我们从acc0而不是acc1发送相同的交易,我们获得:
>>> cfToken.functions.setON('Andrés Bachfischer').transact(txargs0)
image
我们看到状态使我们成功运作。
现在我们将关注代币的功能,我们检查我们的帐户的原始余额输入:
>>> web3.fromWei(cfToken.functions.balanceOf(acc0).call(),'ether') // = 1000
>>> web3.fromWei(cfToken.functions.balanceOf(acc1).call(),'ether') // = 0
image
现在,我们通过执行以下操作从所有者帐户转移到我们的第二个帐户:
>>> cfToken.functions.transfer(acc1, web3.toWei(88.8, 'ether')).transact(txargs0)
我们得到了新的余额:
>>> web3.fromWei(cfToken.functions.balanceOf(acc0).call(),'ether') // = 911.2
>>> web3.fromWei(cfToken.functions.balanceOf(acc1).call(),'ether') // = 88.8
image
继续下一个函数,我们检查acc0没有allowance给acc1的余量:
>>> web3.fromWei(cfToken.functions.allowance(acc1, acc0).call(txargs0),'ether') // = 0
image
因此,要从acc1向acc0授予10个代币限制,你必须执行以下操作:
>>> cfToken.functions.approve(acc0, web3.toWei(10,'ether')).transact(txargs1)
image
我们代表acc1花费:
>>> cfToken.functions.transferFrom(acc1, acc0, web3.toWei(5,'ether')).transact(txargs0)
image
我们看到交易成功,正如预期的那样。
最后,我们向合约发送一个交易而不调用任何函数,这将激活回退函数(默认行为):
image
将警告我们错了或者该函数不存在。
要添加到上一篇文章的成就,在本教程中我们将学习如何:
我们看到两种工具的语法都很相似。truffle更容易从头开始使用,因为将合约代码放入Solidity足以使其可以从套件中部署。通过两个简单的命令,你的智能合约即可开始使用。但是因为我们在发送交易时遇到使用Truffle套件的问题,所以需要进行更改。
在撰写本文时,Web3.py
实现对于开发人员来说更好。它不仅从Truffle帐户中检索资金,而且还有更新版本的Web3,并允许执行特别的脚本。truffle的运行有时可能比必要的复杂。是的,也许你需要从一开始就设置更多的包和库,而不是考虑需要自己编译代码,但从长远来看,在我看来,这个工具比Truffle能更稳定地开发合约。
======================================================================
分享一些以太坊、EOS、比特币等区块链相关的交互式在线编程实战教程:
- java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
- python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
- php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
- 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
- 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
- C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
- EOS教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
- java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
- php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
- tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。
汇智网原创翻译,转载请标明出处。这里是原文Python使用Web3.py进行ERC20代币开发