《web3 solidity0.8.+版本(持续更新新版本内容) 基础到实战NFT开发》会及时更新新版本 solidity 内容,以及完成最终的 NFT 实战商业项目部分。
注:由于是付费专栏内容,若有错误请及时联系@1_bit,博客链接:https://blog.csdn.net/A757291228 ,或在文章下留言,收到后将会对错误进行改正,若是版本更新导致的问题也希望大家对错误进行提交,尽力去保证付费用户该得到的权益。
文章目录可查看:目录(文章更新中…)
更新内容将会在目录中更新…
友情提示:本系列文章读者最好学过一门编程语言,面向对象语言更佳,文章所有代码将会完整贴出。
一、字符串与 bytes
在 solidity 中 ,string 可以转化为 bytes,并且在转换时进行的是传址操作,例如:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract StringDemo{function StringChange()public pure returns(string memory){string memory str="Hello";bytes memory byteData;byteData=bytes(str);byteData[1]='H';return str;}
}
在以上合约中创建了一个方法 StringChange,返回 string 类型的数据,在方法中创建了一个 str 的 string 类型数据以及一个 bytes 类型的 byteData 数据,在接下来的代码中使用 bytes 对字符串进行了强转赋值给到 byteData,接着修改第 0 位的内容为 H,但是此时 return 的是转化之前的 str 变量,那么 str 字符串变量是否能够发生影响呢?
部署合约后我们可以查看结果:
二、循环
在 solidity 中可以使用 for 循环,for 循环的语法跟其他编程语言(例如C 等)语法相似在此不再讲解。
以下示例简单的释放了一个 for 循环的使用,由于过于简单不再赘述:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.0;
contract StringDemo{uint[] arr=[1,2,3,4,5];function ForDemo()public view returns(uint){uint sum=0;for(uint i=0;i<arr.length;i++){sum+=arr[i];}return sum;}
}
以上代码此需要注意的是,我们在 ForDemo 方法中的修饰是 view,若你写错了改成了 pure 之类的,那么将会报错,因为在你修饰成了 pure 那么就表示你不会读取状态变量,那么你即使用了 arr那么也会报错,例如:
三、传参怎么传数组
在一些方法中,可能需要传入的参数是数组,那么在 remix 中我们测试时该怎么传入对应的数组参数呢?
以下是一个 solidity 代码的示例:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.0;
contract StringDemo{function parameterDemo(uint[5] memory _arr)public pure returns(uint) { return _arr[1];}
}
以上的 parameterDemo 方法接收一个固长数组,在此部署后如何进行传参呢?
我们只需要传入一个 []
所包裹的值集合即可,记得一定要是长度为5的数组,例如传入数据 [1,3,2,5,9]
:
四、方法重载
solidity中支持重载,注意,是重载而不是重写 override。
在 solidity 中的同名函数,但参数不同的函数为函数的重载,例如以下示例:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract PayDemo{function OverLoading(address)public pure returns(string memory){return "address";}function OverLoading(uint256)public pure returns(string memory){return "uint256";}function OverLoading(uint256[] memory)public pure returns(string memory){return "int256[]";}
}
以上示例中分别创建了 3 个同名函数,但参数不同,通过不同的参数返回不同的值,部署合约后如下:
你会发现这样不就是体现了可以重名嘛,和传不同参数,本质上好像没啥区别。
这是因为这是重载在外部的可视化体现是这样的,若我们在合约中使用一个函数进行调用就不一样了,例如此时再合约中添加一个方法:
uint256[] u256Arr=[1,2,3,4,5,6];
function CallOverLoading(uint256 _c)public view returns(string memory){string memory res;if(_c==1){res = OverLoading(0x7C4e30a43ecC4d3231b5B07ed082329020D141F3);}else if(_c==2){res = OverLoading(125);}else if(_c==3){res = OverLoading(u256Arr);}return res;
}
此时为了等下的传入数组,在这里参加农历 uint256 的数组,随后创建一个 方法 CallOverLoading 接收一个参数 _c,并且在方法中判断这个 _c 的值,从而给 OverLoading 传入不同的参数,看看是否会返回不一样的值,注意,在这里需要把 public 改为 private 会比较舒服一点,当然你不改也可以:
改了之后部署就会显示一个 方法,这样看起来比较爽:
接着输入不同的值:
这样就舒服多了。
五、constant
constant 在 solidity 中常量的修饰符,通过使用 constant 对变量修饰后,变量转为常量且不可变,若修改将会报错:
六、函数修改器 modifier
在 solidity 中有一个函数修改器可作为前置、中置或者后置方法,有点像 ASP.NET 中的母版页(最起码差不多十年不碰了,不懂还有没有这个概念),又有点像 ThinkPHP 中的前置方法,可以在指定某个函数调用前、中执行该函数,下面是一个示例:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.6;
contract ModifierTest{modifier checkAge(uint val){require(val<10,"Age < 10");_;}modifier checkHeight(uint val){require(val>260,"Height < 260");_;}function osVal(uint age,uint height) external pure checkAge(age) checkHeight(height){age+=1;}
}
以上代码中使用 modifier 创建了函数修改器,modifier 之后是对应的函数修改器名称,可以接收参数或者不接收参数,其中的 “_;
” 表示使用这个修改器的函数代码位置,例如:
modifier checkHeight(uint val){require(val>260,"Height < 260");_;}
在被 osVal 方法调用后,osVal 方法中代码的位置就等于在“_;”
位置进行填充。在 osVal 中使用这些修改器只需要再其后说明即可,并且可以传入对应的参数,调用后效果如下:
“三明治”用法:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.6;
contract ModifierTest{uint public age=0;modifier sandwich(){age+=1;_;age+=1;}function osVal() external sandwich(){age+=1;}
}
三明治用法就是用于中间:
七、合约销毁
在 solidity 中,selfdestruct 是一个合约销毁方法,在部署时初始化函数中记录 msg.sender 后,通过一个方法使用 selfdestruct 传入 owner 即可对当前合约进行销毁:
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract selfdestructDemo{address owner;constructor () {owner = msg.sender;}function kill() public {require (msg.sender == owner);selfdestruct(payable(owner));}}
不过在此要注意,selfdestruct 传入 owner 参数时需要将 owner 通过 payable 类型强转,否则将会出现如下错误:
待完善补充 将 逐步完善(重要的知识点或在后面章节单章更新)
事件 /索引 indexed
自定义错误
abi.encode/abi.encodePacked
interface
keccak256