主要是学习solidity基础
web3学习笔记(二)
1.合约
Solidity 的代码都包裹在合约里面, 一份合约就是以太应币应用的基本模块, 所有的变量和函数都属于一份合约。
// 表示代码所使用的软件许可(license)
// SPDX-License-Identifier: MIT
// 表示使用的Solidity版本,这里`^0.8.21`表示的是不小于0.8.21版本
pragma solidity ^0.8.21;
// contract创建合约,并命名为`HelloWeb3`
contract HelloWeb3{
// 声明了一个字符串,赋值为`Hello Web3!`
string public _string = "Hello Web3!";
}
2.状态变量和整数
上一步,我们做了一个合约的外壳,下面学习怎么使用变量
状态变量是被永久地保存在合约中。也就是说它们被写入以太币区块链中,想象成写入一个数据库。
contract Example {
// 这个无符号整数将会永久的被保存在区块链中
// 定义了a的类型为uint,赋值100
uint a = 100;
}
2.1.uint
uint
无符号数据类型, 指其值不能是负数。
对于有符号的整数存在名为 int
的数据类型。
uint
实际上是unint256
的简写,所以我们后面也会用到unint8
,unint16
等等。
3.数学运算
在 Solidity 中,数学运算很直观明了,与其它程序设计语言相同:
- 加法:
x + y
- 减法:
x - y
, - 乘法:
x * y
- 除法:
x / y
- 取模 / 求余:
x % y
(例如,13 % 5
余3
, 因为13除以5,余3) - 乘方:
x**y
pragma solidity ^0.4.19;
contract HelloWeb3 {
uint a = 16;
uint b = 10 ** a;
}
4.结构体
如果需要更加复杂的数据类型,就需要使用到结构体,个人感觉类似JS中或者其他语言中的类和对象。
struct Person {
uint age;
string name;
}
5.数组
跟其他语言一样,solidity
也有数组,不过分两种:静态数组和动态数组。
// 固定长度为2,类型为uint
uint[2] array1;
// 固定长度为5,类型为string
string[5] array2;
// 动态数组,可以动态添加元素
uint[] array3;
// 甚至还有机构体数组
Person[] array4;
5.1.公共数组
可以使用public
修饰数组,其他合约可以从这个数组读取数据,但是不能写入数据。
struct Person {
uint age;
string name;
}
Person[] public people;
6.定义函数
// 这里变量用了_做开头,但这个不是语法要求,是一种习惯
function foo(string _name, uint _age){
}
7.使用结构体和数组
struct Person {
uint age;
string name;
}
Person[] public peopleList;
// 创建一个新的Person:
Person person1 = Person(172, "zs");
// 将新创建的person1添加进people数组:
peopleList.push(person1);
当然也可以把创建和push
合为一步
peopleList.push(Person(172,"zs"))
结合一下上面写的函数,定义一个函数,函数里面创造了一个People
,然后在peopleList
的尾部加入这个People
。
function foo(string _name, uint _age){
// 创建的People的参数由函数传入
peopleList.push(Person(_age,_name))
}
8.私有/公共函数
在合约中定义的函数默认为public
的,也就是公共的。这就意味着其他的合约也可以调用这个函数,这样是不安全的。所以要有一个习惯,这个函数确定是公共的才把他设置为public
。
公共的对立面就是私有,那么如何定义一个私有的函数呢?
uint[] numbers;
// 在函数名字后面使用private关键字,就能把他设置为私有
// 私有函数的名字用_开头,这是一种习惯
function _addToArray(uint _number) private {
numbers.push(_number);
}
9.函数的更多属性
9.1.返回值
// 函数如果有返回值,有语法规定
// returns 定义了返回值的类型为 string
string str = "hello";
function sayHello() public returns (string) {
return str;
}
9.2函数的修饰符
上面的sayHello
没有改变任何状态,他只是返回了str
,这种情况下我们可以把函数定义为view
,这个意思就是他只能读取状态而不能改变状态。
function sayHello() public view returns (string) {
return str;
}
此外,还有另一个修饰符pure
,这个表示函数没有读取也没有修改状态。
function _multiply(uint a, uint b) private pure returns (uint) {
return a * b;
}
10.Keccak256 和 类型转换
10.1.Keccak256
// 有一个方法是把一个字符串转换为一个256位的16进制数字
keccak256("aaab");
//6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5
不过需要注意的是,在区块链中安全地产生一个随机数是很困难的事情,这个方法是不安全的。
10.2.类型转换
uint8 a = 5;
uint b = 6;
// 这样写会报错,因为a * b返回的是uint。
// 这个类似TS中的类型报错一样
uint8 c = a * b;
// 转换一下b的类型,这样就可以了
uint8 c = a * uint8(b);
11.事件
事件是合约和区块链通讯的一种机制。前端要监听某些事件然后做出处理。
// 使用event建立事件
event AddEvent(uint x, uint y, uint res);
function add(uint _x, uint _y) public {
uint res = _x + _y;
// 触发事件
AddEvent(_x, _y, res);
return res;
}
// 然后前端就可以监听这个事情,做出一些处理
YourContract.AddEvent(function(err,res)){
}