| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 区块链 -> 使用Brownie开发Fund Me智能合约 -> 正文阅读 |
|
[区块链]使用Brownie开发Fund Me智能合约 |
在「Solidity入门-开发众筹智能合约」一文中,实现了名为Fund Me的众筹智能合约,但开发过程还是比较粗糙的,本文使用Brownie框架将其完善一下,主要涉及内容如下:
因为智能合约发布后,便不可以更改,所以在发布前,通常需要进行大量的测试,测试代码一般比业务代码多,所以如何优雅的实现单元测试就很重要。 此外,相比于传统的开发,智能合约在开发时也会更加麻烦一些,比如我们需要使用外部的智能合约,而外部的智能合约却在主网上,此时就需要使用Mock或Fork的方式来解决,从而实现本地的调试。 项目代码:https://github.com/ayuLiao/brownie-fund-me 玩得开心😁 Brownie基本使用创建名为【brownie-fund-me】的文件夹,然后 通过 与Remix在线IDE不同,Remix看到代码中有@符号的import会自动从npm中下载,但brownie不能,但brownie可以从github中下载相应的内容,通常外部的智能合约除了上传到npm还会上传到github中,我们可以新增brownie-config.yaml配置文件,新增如下内容:
配置中,通过remappings关联@chainlike与对于的github项目。 后续brownie遇到@chainlink便会将其替换成smartcontractkit/chainlink-brownie-contracts@1.1.1。 随后,我们在对合约进行编译,便可以正常编译。 使用brownie部署合约时,brownie默认会部署到本地的区块链网络中(由ganache-cli提供),但FundMe合约使用了外部的智能合约,这些外部的智能合约必然不会在本地区块链网络中,所以这里直接部署到rinkeby。 跟之前一样,我们使用infer作为我们的节点提供商,从而快速实现将合约部署到不同网络的操作,infer使用的细节可以看「Brownie 开发智能合约(入门使用)」一文。 简单而言,注册infer,在infer上新建项目,从而获得相应的project_id和对应的私钥。 将需要使用私钥,我们已经放在.env文件中,在brownie-config.yaml中使用一下:
yaml配置文件通常是要被git托管的,而私钥等信息,我们不希望被传到github中,所以我们创建.env然后将配置写到.env中,而yarm配置文件中也相应的填写了「dotenv:.env」 .env如下:
在scripts目录中,创建deploy.py文件,写入如下代码,进行合约的部署。 部署代码:
代码逻辑非常简单,通过get_account()方法获得部署合约时需要使用的账户,然后调用FundMe的deploy方法,部署合约是改变区块的行为,属于交易行为,需要通过account进行签名。 get_account()方法代码如下:
get_account()方法逻辑简单,如果当前区块链网络环境为development(brownie默认使用的本地环境)则直接返回accounts中的账号。brownie默认会通过ganache-cli在本地构建区块链网络,并默认初始化10个账号供于测试使用。 通过 部署完后,可以看到合约的地址 通过https://rinkeby.etherscan.io/可查看,点击contract部分,发现都是字节码,目前很多项目所谓的智能合约开源只是开源字节码,通过字节码,可以获得操作码(Opcodes),但Opcodes与源码在阅读理解上,还是有很大的差异的,所以研究区块链安全,逆向solidity是必不可少的(后面会写文章分享,已经在学了)。 这里,我们将FundMe.sol的合约源码直接放到etherscan中,方便他人浏览。 放源码最简单的方式,就是在etherscan中直接操作,点击 Verify and Publish,将合约代码以可阅读的方式开源到Etherscan上。 通过上图的形式,我们可以手动将合约的明文代码直接复制到etherscan中(当然,这个过程需要账户授权,所以通常只有合约创建者才有权限修改)。 因为solidity中,import操作其实是将相应的solidity代码复制到当前文件的过程,所以在复制代码到etherscan时,我们也需要将import对于的solidity文件复制进去。 通过brownie可以自动实现上述操作。 在etherscan.io上注册账号,然后进入账号设置页,点击API-KEYs,然后创建一个api-keys, brownie可以通过这个keys1与etherscan交互,从而实现将合约代码明文部署上去的操作。 配置一下.env文件,其中新增的ETHERSCAN_TOKEN,其实就是我们在Etherscan中创建的Api-Key。
然后我们修改一个deploy.py中代码,如下:
在使用FundMe.deploy方法时,新增publish_source参数,便可以实现将合约源码提交到Etherscan中,再次部署,如下图: 从上图可以看出,brownie与api-rinkeby.etherscan.io交互的过程。在rinkeby.etherscan可看到源码 此外,还给出了读合约和写合约的方法。 Mocks
相比于将智能合约发布到rinkeby进行调试的方式,本地调试更快也更方便,但FundMe.sol中的问题便是,外部智能合约无法在本地区块链网络中使用。 我们可以通过Mock来解决。 chainlink无法在本地区块链网络中使用,可以通过mock功能解决。 Mock在传统的前后端开发中也很常见,在后端没有提供完整功能的接口前,前端可以通过Mock的方式模拟后端完整接口返回的数据,从而实现前端功能的开发。这里也是类似的,我们可以在本地区块链网络中实现与外部智能合约返回相同结果的方法,然后在本地使用时,直接替换成Mock的合约。 需要注意,Mock智能合约并不是要你完全实现一个具有相同功能的合约,而是确保同名函数可以返回与真实函数具有相同格式的值则可。 回到FundMe.sol,我们需要在本地Mock出AggregatorV3Interface.sol中的功能,从而提供假数据 幸运的是,我们可以直接使用chainlink-mix项目为我们写好的mock 项目代码:https://github.com/smartcontractkit/chainlink-mix/blob/master/contracts/test/MockV3Aggregator.sol 在contracts目录中创建test命令,然后将MockV3Aggregator.sol复制过去。 deploy.py修改后的代码为:
deploy_fund_me()方法会判断当前的网络情况,如果不是本地区块网络,则通过deploy_mocks()方法部署MockV3Aggregator.sol。 部署完后,直接通过 这里有点奇怪的是,在本文前面的内容中,FundMe.deploy方法是不需要传入外部合约地址的,这因为我们在FundMe.sol中已经硬编码写死了,而此时因为我们Mock了外部的合约,所以不能使用硬编码的形式,而是需要我们使用外部传参的形式,通过修改FundMe.sol合约构造函数的方式做到这点: 接着,看一下utils.py中deploy_mocks方法的代码:
因为Mock后的外部合约,其内容是不会改变的,所以只需要部署一次,部署过就不再需要部署了。 实现Mock后,通过 添加新网络
brownie network list 可以查看当前所有的network,我们可以新增任何EVM的网络到brownie的network中。 新增区块链网络的原因:每次运行brownie,brownie都会通过ganache-cli在本地构建一个新的区块链网络,这样,之前的操作在brownie重新运行时,就会消失。可以通过新增本地网络的形式,通过ganache-cli构建本地网络,然后新增的网络会去链接它,这样就避免brownie每次运行都去新建。 首先,通过ganache-cli启动一个本地区块链网络。
效果如图: 然后将这个网络添加到Ethereum中,新的网络名为ganache-local,命令如下(注意这是个错误命令,我在这里爬了一段时间坑):
命令效果如下: 然后看networks,可以发现Ethereum中多了一个ganache-local,似乎一切都很正常。 然后我们让brownie使用ganache-local时,命令如下:
运行命令后,会报RPC或HTTP无法连接的错误,这是因为ganache-local的host不是一个完整的连接,我们需要修改一下:
注意host等于http://127.0.0.1:8545,不能缺少http前缀。 再次让brownie使用ganache-local运行区块链网络,效果就正常了。 ganache-cli不要关闭,不然上述命令会报错,我们看到ganache-cli中也会有相应的日志输出。 部署后,build/deployments会有1337目录,存放着abi。 使用合约
在FundMe.sol中新增getEntranceFee方法
智能合约改变后需要再次编译和部署,不然我们使用的依旧是旧合约,而旧合约中是没有getEntranceFee方法的:
在scripts中创建fund_and_withdraw.py,在其中写入与FundMe.sol合约进行交互的逻辑,代码如下:
通过brownie运行
单元测试
智能合约部署后,便无法修改,出现bug了,通常也是切换到新的智能合约上,而旧的合约会一直留在相应的区块中(这有利于我们学习恶意bug,因为旧合约一直都在,我们可以基于这些有问题的旧合约进行学习和恶意bug的利用复现) 为了尽量避免合约有bug,被恶意利用,我们需要写大量的单元测试代码,通常单元测试代码会多于合约的逻辑代码。 在test命令下创建新的py文件,然后写下如下测试代码:
智能合约的单元测试与常规软件开发的单元测试没有太大差别。 上述代码中的test_only_owner_can_withdraw方法需要注意,我们希望测试时出现异常,所以使用pytest.raises捕获了相应的异常。 进行单元测试时,将本地运行着的ganache-cli停掉,使用 关停ganache-cli,然后再测试,如下图,图中使用了-k参数,指定只测试其中的一个方法: 测试所有单元测试: 在rinkeby测试链上测试合约: brownie默认运行的网络是development,你可以通过修改brownie-config.yaml来修改brownie默认运行的网络,这里还是选择development。 fork
因为DeFi的兴起,现在很多智能合约都需要调用外部的合约,这就给本地开发智能合带来了一点麻烦,因为你本地的区块链是没有这些外部的智能合约的。在前面,我们使用Mock的方式解决过这个问题,但如果你调用的外部智能合约比较多,Mock起来也会有点麻烦。 解决这个问题的最佳方式是使用ganache-cli的fork功能,brownie也兼容了ganache-cli的fork功能,让我们在开发时,可以无感的使用。 fork的另外一个好处是,我们调用的外部合约与主网的情况是一致的,因为很多智能合约在测试网络中的情况与主网是有差异的,此时如果你直接上线,结果就很坑。 通过fork,我们可以构建一条与主网相同的区块链网络,它具有主网中的数据,这也就意味着我们fork的区块链网络已经自带了这个我们需要的外部智能合约了,而且与真实的合约是一致的。 与我们熟知的fork不同,比如我们在Github fork一个项目,这个项目的数据会完全同步一份到自己的github账号,而区块链主网数据其实挺大的,如果fork时将数据完全同步到本地,也挺麻烦的。 infer之类的服务帮我们简化了这步,即通过这类服务,它知道我们需要fork一份主网,但它会帮我们做完数据的fork操作,我们只需要通过http或rpc的方式与之交互便可以实现与主网交互同样的效果,而且这类交互还不需要花费真实的金钱。 这样,我们操作本地区块链中数据时,与操作真实的区块链没有啥区别。 这里我们使用https://www.alchemy.com/,alchemy与infer类似,都是节点提供商,两者拥有相似的功能。我们在alchemy中创建账号,然后创建一个app,主要创建的app其network选择以太坊的主网。 创建完后,我们就会获得HTTP的链接地址。 我们通过brownie将这个地址以fork形式添加到networks中,具体命令如下:
上述命令添加名为mainnet-fork-dev的区块链网络到development中,我们使用ganache-cli作为创建本地区块链的后端,其原理就是利用了ganache-cli的fork功能。 在mainnet-fork-dev网络中进行部署。
在mainnet-fork-dev网络中进行单元测试
在brownie中使用fork功能获得一个与主网相同的开发环境还是很简单的。 结尾后续我会将业余时间花在智能合约安全以及dApp开发上,我们下篇文章见。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/28 19:14:52- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |