《web3 solidity0.8.+版本(持续更新新版本内容) 基础到实战NFT开发》会及时更新新版本 solidity 内容,以及完成最终的 NFT 实战商业项目部分。
注:由于是付费专栏内容,若有错误请及时联系@1_bit,博客链接:https://blog.csdn.net/A757291228 ,或在文章下留言,收到后将会对错误进行改正,若是版本更新导致的问题也希望大家对错误进行提交,尽力去保证付费用户该得到的权益。
文章目录可查看:目录(文章更新中…)
更新内容将会在目录中更新…
友情提示:本系列文章读者最好学过一门编程语言,面向对象语言更佳,文章所有代码将会完整贴出。
在 solidity 中交易是核心知识点,交易贯穿了几乎大部分的智能合约操作。咱们在正式学习交易之前,首先了解一下如何给合约转账以及如何查看合约中的余额。
以下是一个有关查看合约地址余额和给合约地址转账的sol 代码示例:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract PayDemo{
function payToContract() public payable{
}
function getBalance() public view returns(uint256){
return address(this).balance;
}
}
以上合约 PayDemo 中,payToContract 方法是一个空函数,并且接收合约转账的方法,因为在其中使用了 payable 对其进行修饰。payable 修饰后的方法可以让方法在调用时接收附带的 ether,那如何附带 ether 呢?这个暂时先放一下,等下讲解完所有 sol 代码后再讲解如何操作,并让方法接收附带的 ether。
此时我们可以查看 getBalance 方法,在这个方法中 使用了 return 返回 address(this).balance;,在这里 this 表示本身地址,但在 0.8 版本中需要使用 address 函数对 this 进行强转,强转之后才能调用 balance 获取余额,那么 getBalance 的作用就是返回余额。
接下来开始部署合约,部署完毕之后如下(红色的按钮表示 payable function):

首先我们可以调用 getBalance 查看当前的合约余额:

接着我们开始往合约中传入 ether,此时我们可以选择需要支付的合约:

选择完毕之后在 VALUE 中输入你要传入的多少 ether,当然你也要选择对应的单位:

输入完毕后调用 payToContract 方法:

此时我们点击 getBalance 后可以查看到余额:

并且选择的虚拟地址的 ether 也相对应的减少了:

在 solidity 中我们可以通过 transfer 对合约进行转账、对某地址进行转账以及对合约中的余额进行提现。
我们继续使用第一点中的合约,在合约中添加方法实现 transfer 的操作。
首先我们实现对某个合约进行转账,此时方法编写如下:
//合约给某个地址转 ether
function toEther(address payable _toAdrr)public payable{
_toAdrr.transfer(msg.value);
}
此时这个 toEther 方法接收一个参数 _toAdrr,这个 _toAdrr 表示接收方需要使用 payable 进行修饰,注意这个方法是一个 payable 的方法。
接着在这个方法中编写了这么一条语句: _toAdrr.transfer(msg.value);
其中 transfer 是转账的方法,其参数是 msg.value 表示转账的金额,_toAdrr 为接收转账的地址,那么这个余额是怎么来的呢?
还记得第一点中的 VALUE 吗:

这个 VALUE 就是这个 msg.value,表示我们调用合约时所在此处添加的 VALUE,那么这就很好理解了,在这里填入数值后进行方法调用,传入对应的接受地址,那么就可以对该地址进行转账。
查询某地址余额就很容易了,直接接收一个参数为地址,通过这个地址取出 balances 就ok了,这个方法如下:
//查询某地址 balances
function getAdrrBalance(address _adrr)public view returns(uint256){
return address(_adrr).balance;
}
不过一定要注意,在调用 balance 之前需要对应的为其强转 address。
在第一点中我们还需要一点补充,那就是将余额付给合约后,那没有取款的方法那不是很惨了?
所以在这里我们添加一个方法,取出这个合约中的余额:
//取款
function withdraw()public payable{
payable(msg.sender).transfer(address(this).balance);
}
以上是一个取款方法,记得需要使用 payable进行修饰,其实看到这里大家应该明白了,只要是涉及转账、接收的函数那么就需要使用 payable进行修饰,并且在调用转账方法前,也需要对某一个地址进行payable 修饰,在函数体重代码为 payable(msg.sender).transfer(address(this).balance);,也对 msg.sender 进行了修饰,msg.sender 表示当前的调用合约的人,就是一个地址,进行了 payable 修饰后,对这个人进行转账,这个月就是当前地址的余额。
接下来我们部署合约,先设置一下 msg.value 的值,我们往这个合约中添加余额:

之后调用第一点中的 payTo 方法,此时当前合约已经有了 10ETH 了:

接着我们选择一个虚拟账户,复制一下他的地址:

往这个合约中转10个 ether(记得切换回来对应的付款地址):

在此一定要注意设置 msg.value 的值:

接着调用方法发现虚拟账户中一个账户余额变少了一个账户余额变多了:

也可以复制地址参数使用方法进行查询:

接着使用取款按钮取出最开始给合约的 10个 ether:

此时余额发生改变:

并且对应的合约余额也无了:

第二点完整 solidity 代码:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract PayDemo{
//给合约 ether
function payToContract() public payable{
}
//查看 balance
function getBalance() public view returns(uint256){
return address(this).balance;
}
//合约给某个地址转 ether
function toEther(address payable _toAdrr)public payable{
_toAdrr.transfer(msg.value);
}
//查询某地址 balances
function getAdrrBalance(address _adrr)public view returns(uint256){
return address(_adrr).balance;
}
//取款
function withdraw()public payable{
payable(msg.sender).transfer(address(this).balance);
}
}
在 solidity 中可以手动设置对应的转账数额,单位有 weg、gwei、ether 等,在此使用 ether 作为示例。
修改 toEther 方法:
//合约给某个地址转 ether
function toEther(address payable _toAdrr)public payable{
_toAdrr.transfer(10 ether);
}
接下来我会给另一个账户(120ether 账户)转账:

此时复制了这个地址作为 toEther 方法的参数,并且设置了 VALUE 值:

此时是大于了 10 ether的,那么将会发生什么情况?
调用方法后,发现接收方的地址多了 10个 ether:

那剩下的 10个 ether在哪了呢?此时这 10 个ether 被转入了当前合约之中:

在提现的时候不可能随便任何一个人可以提现,在此我们需要便携一个条件,只有合约拥有者可以提现:
//取款
function withdraw()public payable{
require(owner==msg.sender,"not allow withdraw");
payable(msg.sender).transfer(address(this).balance);
}
以上代码中使用了 require(owner==msg.sender,"not allow withdraw"); 对合约拥有者进行判断,require 将会判断 msg.sender 当前调用者是否等于 owner,owner 则是当前合约者,如果等于则继续往下执行,否则将会报错 “not allow withdraw”。
此时编写一个方法接收 ether:
function pay()public payable{
}
那么这个 owner 怎么来呢?直接使用构造函数在部署的时候就传入部署者即可:
address owner;
constructor(){
owner=msg.sender;
}
接着部署完毕后,设置 VALUE 后使用 pay 方法传入 ether:

接着切换一个账户:

使用提现方法:

此时将会报错,这时再切换成部署合约的地址:

提现成功操作:


该小点完整代码:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract PayDemo{
address owner;
constructor(){
owner=msg.sender;
}
function pay()public payable{ }
//取款
function withdraw()public payable{
require(owner==msg.sender,"not allow withdraw");
payable(msg.sender).transfer(address(this).balance);
}
}
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po