目录
-
-
-
- 一、版本指令:pragma solidity ^x.x.xx;
- 二、合约创建:contract xxx { ... }
- 三、状态变量
- 四、无符号整数:uint
- 五、数学运算(加减乘除、乘方)
- 六、结构体:struct
- 七、数组
- 八、定义函数
- 九、使用结构体和数组
- 十、私有 / 公共函数
- 十一、返回值:returns
- 十二、函数的修饰符:view
- 十三、函数修饰符:pure
- 十四、散列函数Keccak256:字符串转256位16进制数字
- 十五、类型转换
- 十六、事件:event
- 十七、Web3.js
- 十八、地址:Address
- 十九、映射:mapping
- 二十、Msg.sender
- 二十一、Require
- 二十二、继承(Inheritance)
- 二十三、引入(Import)
- 二十四、Storage(永久存储在区块链的变量)与Memory(临时变量)
- 二十五、函数可见性(internal 和 external)
- 二十六、与其他合约的交互(接口)
- 二十七、处理多返回值
- 二十八、if语句
- 二十九、构造函数
- 三十、modifier修饰符
-
-
一、版本指令:pragma solidity ^x.x.xx;
pragma solidity >=0.5.0 <0.6.0;
//在本示例的范围内,我们希望能够使用0.5.0(包括)到 0.6.0(不包括)范围内的任何编译器版本来编译我们的智能合约。
所有 Solidity 源代码都应该以“版本编译指示”开头——该代码应该使用的 Solidity 编译器版本的声明。这是为了防止未来编译器版本的问题可能会引入会破坏您的代码的更改。
总而言之,这是一个基本的起始合同——每次开始一个新项目时你要写的第一件事。
二、合约创建:contract xxx { … }
contract HelloWorld {
....
}
Solidity的代码都封装在contracts中。contract是以太坊应用程序的基本构建块,所有变量和函数都属于一个合约,这将是你所有项目的起点。
三、状态变量
contract Example {
//这将永久存储在区块链中
uint myUnsignedInteger = 100;
}
状态变量永久存储在合约存储中。这意味着它们被写入以太坊区块链。把它们想象成写数据库。
在示例中,定义 myUnsignedInteger 为 uint 类型并将其设置为 100。
四、无符号整数:uint
uint 无符号数据类型, 指其值不能是负数,对于有符号的整数存在名为 int 的数据类型。
注: Solidity中, uint 实际上是 uint256代名词, 一个256位的无符号整数。你也可以定义位数少的无符号整数 — uint8, uint16, uint32, 等…… 但一般来讲你愿意使用简单的 uint, 除非在某些特殊情况下,这我们后面会讲。
五、数学运算(加减乘除、乘方)
加法:x+y
减法:x-y
乘法:x*y
除法:x/y
Solidity 还支持 乘方操作 (如:x 的 y次方) // 例如: 5 ** 2 = 25
uint x = 5 ** 2; // equal to 5^2 = 25
六、结构体:struct
struct Person {
uint age;
string name;
}
结构体允许你生成一个更复杂的数据类型,它有多个属性。
注:我们刚刚引进了一个新类型, string。 字符串用于保存任意长度的 UTF-8 编码数据。 如: string greeting = “Hello world!”。
七、数组
如果你想建立一个集合,可以用数组这样的数据类型. Solidity 支持两种数组: 静态数组和动态数组:
静态数组
// 固定长度为2的静态数组:
uint[2] fixedArray;
// 固定长度为5的string类型的静态数组:
string[5] stringArray;
// 动态数组,长度不固定,可以动态添加元素:
uint[] dynamicArray;
动态数组
你也可以建立一个 结构体类型的数组 例如,(六、结构体中提到的) Person:
Person[] people; // 这是动态数组,我们可以不断添加元素
记住:状态变量被永久保存在区块链中。所以在你的合约中创建动态数组来保存成结构的数据是非常有意义的。
公共数组
你可以定义 public 数组, Solidity 会自动创建 getter 方法. 语法如下:
Person[] public people;
其它的合约可以从这个数组读取数据(但不能写入数据),所以这在合约中是一个有用的保存公共数据的模式。
八、定义函数
function eatHamburgers(string _name, uint _amount) {
}
这是一个名为 eatHamburgers 的函数,它接受两个参数:一个 string类型的 和 一个 uint类型的。现在函数内部还是空的。
注:: 习惯上函数里的变量都是以(_)开头 (但不是硬性规定) 以区别全局变量。我们整个笔记都会沿用这个习惯。
调用函数示例:
eatHamburgers("vitalik", 100);
九、使用结构体和数组
struct Person {
uint age;
string name;
}
Person[] public people;
现在我们创建新的 Person 结构,然后把它加入到名为 people 的数组中.
// 创建一个新的Person:
Person satoshi = Person(172, "Satoshi");
// 将新创建的satoshi添加进people数组:
people.push(satoshi);
你也可以两步并一步,用一行代码更简洁:
people.push(Person(16, "Vitalik"));
注:array.push() 在数组的 尾部 加入新元素 ,所以元素在数组中的顺序就是我们添加的顺序, 如:
uint[] numbers;
numbers.push(5);
numbers.push(10);
numbers.push(15);
// numbers is now equal to [5, 10, 15]
十、私有 / 公共函数
Solidity 定义的函数的属性默认为public。 这就意味着任何一方 (或其它合约) 都可以调用你合约里的函数。
显然,不是什么时候都需要这样,而且这样的合约易于受到攻击。 所以将自己的函数定义为private是一个好的编程习惯,只有当你需要在外部调用它时才将它设置为public。
如何定义一个私有的函数呢?
uint[] numbers;
function _addToArray(uint _number) private {
numbers.push(_number);
}
这意味着只有我们合约中的其它函数才能够调用这个函数,给 numbers 数组添加新成员。
可以看到,在函数名字后面使用关键字 private 即可。和函数的参数类似,私有函数的名字用(_)起始。
十一、返回值:returns
Solidity 里,函数的定义里可包含返回值的数据类型(如本例中 string)。
string greeting = "What's up dog";
function sayHello() public