前言:前面我们将了solidity的一些常用方法,接下来我们来讲一下,我们编写合约经常要用的一些功能;
一,modifier修饰符
在Solidity合约中,修饰符(modifier)是一种用于修改函数行为的特殊函数。通过使用修饰符,我们可以在执行函数之前、之后或中途对函数进行某些操作或检查。我们通常会和异常一起使用;
详细代码如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract text{
//案例一:
address public owner;//初始值为0X000000000...
constructor(){
//定义一个构造函数,初始值为合约部署者的地址
owner = msg.sender;
}
//定义一个修饰符,这个修饰符的意思是只能是合约部署者才能执行,其他地址的用户执行会抛出异常
modifier Onlyowner(){
require(msg.sender==owner, "you are not owner");
_;//这行代表我们要引用方法的语句,写在什么位置,就在什么地方去执行
}
//定义一个修饰符,这个修饰符的意思是合约不能为空,否者抛出异常
modifier Vali(address add){
require(add != address(0) , "Not valid address");
_;
}
//方法中,后面接着就是我们的修饰符
function modifowner(address newowner)public Onlyowner Vali(newowner){
owner = newowner;
}
//案例二:
uint public x =10;
bool public locked; //初始值为false
//定义一个修饰符,这个修饰符的作用是,执行期间抛出异常,就不会执行。防止死循环
//我们可以看到“_;”在中间,我们首先会把locked 赋值为真,再执行被调用的方法,又会把locked重新赋值为假
modifier noReentrancy{
require(!locked, "No reentrancy");
locked = true;
_;
locked = false;
}
function decrement(uint i)public noReentrancy{
x -= i;
if(i > 1){
decrement(i-1);
}
}
}
2,Event事件
当我们写合约的时候,为了更好和前端交互,且减少更多gas的消耗,我们常常会用到事件来处理;他更是存储着我们的日志文件;
-
合约状态变化通知:当合约的状态发生重要变化时,可以使用 Event 来通知外部观察者。例如,当合约转移资产所有权,发生交易,或者某个权限被更改时,可以通过 Event 向外部发送通知。外部观察者可以监听合约中定义的 Event,并做出相应的处理或响应。
-
DApp 触发和反应:在分布式应用程序中,Event 是 DApp 与合约之间的重要接口。DApp 可以监听合约中定义的 Event,以便触发某些操作或更新界面。当合约状态发生变化时,Event 可以通过 DApp 反馈给用户,提供实时的状态更新和交互。
-
历史记录和审计:Event 可以用于记录合约执行过程中的重要事件。通过记录 Event,可以在之后进行审计或查看历史记录。例如,在一个众筹合约中,可以使用 Event 记录每次捐款的细节,以便后续审计捐款阶段的数据。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract Event{
//事件参数最多只能有3个,下面我们定义了两个参数的事件和一个参数的事件;
event Log(address indexed sender , string message);
//在Solidity合约中,indexed 是一个用于声明事件参数的关键字。
//使用 indexed 可以使得事件参数具有索引功能,从而提供更高效的事件过滤和查询。
event AnotherLog();
//这里我们定义了一个方法调用我们的事件
function test() public {
//emit要对应上面我们定义的事件
emit Log(msg.sender, "Hello World");
emit Log(msg.sender, "Hello Event");
emit AnotherLog();
}
}
部署完合约以后,我们点击debug边上的下拉箭头,可以看到我们的日志信息
3,调用其他合约
创建两个contract合约或者是使用import引用其它合约中的数据;类似于java一样,需要实例化,也就是new一个对象出来;
这段代码我们就沿用上面写的程序;主要是下面的contract;
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract Event{
//事件参数最多只能有3个,下面我们定义了两个参数的事件和一个参数的事件;
event Log(address indexed sender , string message);
//在Solidity合约中,indexed 是一个用于声明事件参数的关键字。
//使用 indexed 可以使得事件参数具有索引功能,从而提供更高效的事件过滤和查询。
event AnotherLog();
//这里我们定义了一个方法调用我们的事件
function test() public {
//emit要对应上面我们定义的事件
emit Log(msg.sender, "Hello World");
emit Log(msg.sender, "Hello Event");
emit AnotherLog();
}
}
contract constructorsolidity{
//这里我们调用上面的合约,
Event public eve;
function Creat() public {
eve = new Event();
}
}
运行的时候,我们选择下面的合约部署;至此我们简单的调用其他合约就成功了;
接下里介绍第二种方法使用import调用。当使用import
关键字导入合约时,需要提供合约文件的路径。路径可以是绝对路径,也可以是相对路径。绝对路径是相对于项目根目录或源文件的根目录,而相对路径是相对于当前合约文件的路径。
我们可以清晰的看到,代码量减少了很多,提高了代码的可复用性;
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
//用import引用外部sol文件
import "./three.sol";
contract constructorsolidity{
//这里我们调用上面的合约,创建一个Event对象;
Event public eve;
//给eve对象实例化;这样就拥有里面的数据了;
function Creat() public {
eve = new Event();
}
}
当我们想引用别的合约的数据的时候,用 . 来引用就行了。
4,继承is标签
在Solidity中,合约之间可以通过继承来建立关系。一个合约可以继承另一个合约,并继承合约的属性(状态变量)和方法(函数)。被继承的合约称为父合约或基合约,继承它的合约称为子合约或派生合约。
通过继承,子合约可以继承父合约的属性和方法,从而拥有父合约的行为和功能。这样做可以实现代码的重用和模块化,提高代码的可读性、可维护性和可扩展性。
在Solidity中,使用is
关键字来声明继承关系。例如,定义一个名为ChildContract
的子合约继承自ParentContract
的父合约,可以使用如下语法:
contract ParentContract {
// 父合约的属性和方法
}
contract ChildContract is ParentContract {
// 子合约的属性和方法
}
子合约继承父合约后,可以访问父合约的属性和方法。子合约也可以重写父合约的方法,并且可以使用super
关键字来调用父合约的方法。
需要注意的是,Solidity中只支持单继承,即一个合约只能继承一个父合约。但是一个合约可以被多个合约继承,从而形成更复杂的继承关系。
继承是Solidity中实现代码重用和模块化的重要机制。通过继承,可以在合约中扩展已有的功能和属性,避免重复编写代码,提高代码的复用性和可维护性。
5,编写第一个Dapp(捐款系统)
代码的解释我在文档有注释,先说一些,界面使用问题吧!
选择多个账户,这里每个账户都有100以太坊;
文章来源地址https://www.toymoban.com/news/detail-843747.html
更换货币符号
直接转账到我们的目标账户
文章来源:https://www.toymoban.com/news/detail-843747.html
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract FundMe{
//部署一个用户地址,用immutable,减少gas的消耗
address immutable public ower ;
address[] public funder;
mapping (address => uint) public map;
constructor(){
ower = msg.sender;
}
//有payable意思是,可以往里面存以太坊
function Fund()public payable {
//设置一个异常,捐款不能小于一个以太坊
require(msg.value >= 1e17, "The amount is too small, please enter a suitable amount");
//把我捐款的地址放到地址数组中,方便后续查找,有那些人捐款过
funder.push(msg.sender);
//把金额放到mapping中,方便查询用户存款的金额
map[msg.sender] = msg.value;
}
function count() public view returns(uint){
return funder.length;
}
//设置,只允许部署合约者,提款
modifier onlyOwer{
require(msg.sender == ower, "not adderss contract!");
_;
}
//直接转钱过来的两个功能,及时只转账,也会记录转账人的地址和金额
receive() external payable {
Fund();
}
fallback() external payable {
Fund();
}
function withdraw() public onlyOwer {
//方法一,已经淘汰了的,偏向与底层代码,定义一个bool类型的值,获得账户的地址,将账户提现到自己账户上;
// bool sendSuccess = payable(msg.sender).send(address(this).balance);
// require(sendSuccess, "transation failed");
//方法二,差不多也被淘汰了,只有少部分人在用
// payable(msg.sender).transfer(address(this).balance);
//方法三,现在用的比较多的方法,他的限制比较少,第二种方法,他会有很多限制
(bool callSuccess,) = payable(msg.sender).call{value:address(this).balance}("");
require(callSuccess, "fail transaction");
//当把账户提款到自己账号上时,把捐款地址,金额全部清空;
for(uint i = 0 ; i < funder.length ; i++){
map[funder[i]] = 0;
}
//赋值一个新的空mapping数组
funder = new address[](0);
}
}
到了这里,关于solidity(智能合约)零基础教学(3)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!