目录
一 前言二 详情内容2.1 环境2.2 语法基础2.3 数组2.4 存储和内存2.5 事件/日志2.6 gas2.7 合约调合约2.8 合约升级相关2.9 遇到的问题2.10 安全相关2.11 web3相关三 推荐/参考
一 前言
总结这段时间以来所学到的区块链智能合约开发, 既是solidity语言开发
本文是适合有solidity基础但未实战过观看的,既是实际开发项目的时候. 对于区块链入门基础等将不进行详细说明, 若有需要的话可私.
文章主要是作为一个引子和总结, 读者要自行思考如何应用和辨别.
本章有不对或侵权之处请指出
二 详情内容
2.1 环境
基本上就是使用在线版的ide既是Remix进行开发(自行科学)
2.2 语法基础
- uit8(-1) == 255 // -1就是取uint8的最大值
- 属性默认访问是internal,使用public修饰的将会自动带有get函数
- solidity自带的全局函数
2.3 数组
增加:push,push后的返回值是新长度
删除:把数组长度减少,将把数组最后一个去掉(0.5版本)
创建定长数组:
1uint[5] memory arr = [0,1,2,3,4];
2address[] memory meetIncomeAccounts = new address[](arr.length);
2.4 存储和内存
存储(storage)既是将这个变量存储到区块链上的
内存(memory)既是这个变量是在本地机器运行的 (每个函数内的变量是有限的,具体搜索页面堆栈太深)
单独的内存操作函数(使用pure或view修饰的函数)是不需要进行gas消耗的, 但若是一个有存储和内存的函数(不可以使用pure或view修饰), 在计算gas的时候也是会把内存部分的进行计算进内的.
2.5 事件/日志
快速查找
若需要进行日志快速查找某个地址相关的, 可以使用索引关键字.
在合约A中显示合约B的日志
两个合约调用, A调用B, 要在A中打印出B日记, 需要在A中写B接口时候带上事件声明.
2.6 gas
以太的合约开发, 最值得考虑的点就是: 怎么使得能够满足业务的同时, gas尽可能的少.
对于其他的链开发合约, 可能是不需要消耗能量的或者是能量可以通过抵押得到, 故得看具体在何链上运行的合约. 不过以太肯定是一个大头的.
一般节省gas的思路:
当使用结构体的时候, 尽可能的根据当前变量的大小选用指定大小的变量类型, 例如一个uint类型声明的变量在整个业务范围内都不会超过200, 那么就应该声明为uint8变量类型, 这样能够达到节省gas.
另外: 看Uniswap源码中写到, 对于存储的变量, 在函数内将它赋值到一个内存变量进行操作将减少gas. (未验证)
2.7 合约调合约
调用另外一个合约上的函数
1contract Test {
2 function callHello(address test1Addresss) public pure returns(string memory) {
3 // 填入Test1的地址
4 Test1 test1 = Test1(test1Addresss);
5 return test1.hello1();
6 }
7}
8
9contract Test1 {
10 function hello1() public pure returns(string memory) {
11 return "hello1";
12 }
13}
14
15// 先进行部署Test1, 得到Test1的地址, 把Test1地址传入Test的callHello函数, 最终将会返回hello1.
特殊的调用(delegatecall), 既是使用另外一个合约的代码, 但不使用它的数据
1// delegatecall 调用合约(把另外一个合约的代码拿过来 自己进行执行)
2// 注意: 对于多参数调用, 在"joinTeamTest(address,address)" 里不允许出现空格, 既是joinTeamTest(address, address)是错误的.
3function joinTeamTest(address user, address superior) public returns (bool){
4 bool status;
5 bytes memory result;
6 (status, result) = upgradedAddress.delegatecall(abi.encodeWithSignature("joinTeamTest(address,address)", user, superior));
7 require(status, "Error: Call 'joinTeamTest' method error");
8 require(bytesToUint(result) == 1, "Error: Call 'joinTeamTest' method result error");
9 emit TestData(status, result);
10 return status;
11 }
2.8 合约升级相关
有两种方式
- 可参照USDT源码, 即可知道, 简单来说就是所有对外的接口都进行拦截 参考:
- 使用合约调合约的方式, 推荐的方式, 一个合约存储数据, 一个合约做为实现代码. 具体实现参照合约调合约的delegatecall特殊调用 参考: 在0.6.8版本的solidity中使用delegatecall进行合约升级
2.9 遇到的问题
- 若遇到堆栈太深, 说明槽位不够, 减少局部变量 详情讲解
- 同一合约在不同链上生成同样的合约地址 使用一个未发起转账过的用户在不同链上进行部署此合约, 要求都是第一次部署(同次?) 此说法博主未进行验证
2.10 安全相关
2.11 web3相关
abi编码(abi.encodePacked)和哈希(keccak256)计算
- abi编码其实就是把参数转为16进, 并进行补长, 对应的web3为:web3.eth.abi.encodeParameter
- 哈希计算就是sha3, 对应的web3: web3.utils.keccak256