Solidity 第一天
什么是智能合约?
简单地说,智能合约就是传统合约的数字化版本。它们是在区块链数据库上运行的计算机程序,可以在满足其源代码中写入的条件时自行执行。智能合约一旦编写好就可以被用户信赖,合约条款不能被改变,因此合约是不可更改的。
应用智能合约
现实世界是怎么样应用智能合约的呢?开发人员会为智能合约撰写代码。智能合约可用于交易和(或)两方/多方之间的任何交换行为。该代码包含一些会触发合约自动执行的条件。一旦编码完成,智能合约就会被上传到区块链网络上,即它们被发送到所有连接到网络的设备上。一旦将数据上传到所有设备上,用户就可以与执行程序代码的结果达成协议。然后更新数据库以记录合约的执行情况,并监督合约的条款以检查合规性。
MetaMask安装教程
MetaMask使用教程
Solidity编辑器vscode安装
solidity网页编辑器
什么是solidity?
solidity是一种语法类似JavaScript的高级语言,它被设计成以编译的方式生成以太坊虚拟机代码。在后续的内容中你将会发现,使用它很容易创建用于投票、众筹、封闭拍卖、多重签名钱包等等的合约。
1、合约结构
看看最简单的合约结构
pragma solidity ^0.4.14;
// 第一句声明此合约的版本内容,目前是向下兼容0.4.14的版本
contract HelloWold {
// 声明合约的关键字 contract, 后面跟的是合约名字
// 这就是最简单的合约,接下来再完成合约的内容
}
版本声明:pragma solidity ^0.4.14;
这段代码的声明表示,源文件不会被0.4.14以下版本的编译器编译。当然同时也不会被0.5.0以上版本的编译器起作用(这是由^符号来决定的)。如果0.4.0编译器有问题,可以将其调整为0.4.1。向上兼容的
2、注释
- 单行注释 : //
- 多行注释 : /* This is a */
- natspec注释
/**
@title(标题) 和 @author (作者)很直接了
@notice (须知)向 用户 解释这个方法或者合约是做什么的。 @dev (开发者) 是向开发者解释更多的细节。
@param (参数)和 @return (返回) 用来描述这个方法需要传入什么参数以及返回什么值
@dev 注释来解释每个方法是做什么的
*/
contract shapeCalculator {
/** @dev 求矩形表明面积与周长。
* @param w 矩形宽度。
* @param h 矩形高度。
* @return s 求得表面积。
* @return p 求得周长。
*/
function rectangle(uint w, uint h) returns (uint s, uint p) {
s = w * h;
p = 2 * (w + h);
}
}
3、定义变量(每一行代码结束后必须以;结尾,否则报错)
- 定义变量:变量类型 变量名; uint bb;
- 定义并且赋值变量: 变量类型 变量名 = 对应的值; uint aa = 10;
contract Example {
// 这个无符号整数将会永久的被保存在区块链中
uint myUnsignedInteger = 100;
}
4、变量类型
(1)bool(布尔类型)
和其他语言一样,只存在2个常量值(true, false)
操作符(Operators):
- ! 逻辑非
- && (logical conjunction, “and”) 逻辑与
- || (logical disjunction, “or”) 逻辑或
- == (equality) 相等
- != (inequality) 不等
bool a = true;
bool b = !a;
// a == b -> false
// a != b -> true
// a || b -> true
// a && b -> false
(2)Integers(整型)
整型分为有符号整型int和无符号整型uint,都有从int8~int256的类型,步长为8,eg:int8\int16\int24…\int256,int和uint分别是int256和uint256的别名
操作符(Operators):
- 比较操作符(Comparisons):<=, <, ==, !=, >=, >
- 位操作符(Bit operators):&, |, ^(按位异或),~(按位取反)
- 运算操作符(Arithmetic operators):++, –, *, /, %, **, +, -, >>, <<
pragma solidity ^0.4.14;
contract Math {
function mul(int a, int b) constant returns (int) {
int c = a * b;
return c;
}
function div(int a, int b) constant returns (int) {
int c = a / b;
return c;
}
function sub(int a, int b) constant returns (int) {
return a - b;
}
function add(int a, int b) constant returns (int) {
int c = a + b;
return c;
}
}
(3)地址类型(Address)
以太坊中的地址的长度为20字节,一字节等于8位,一共160位,所以address其实亦可以用uint160来声明
我的以太坊钱包的地址为0xc1ce4f401951cd996f2628935acc858647489eef,0x代表十六进制,一个16进制由4个二进制组成,它的二进制刚好160位
Address的属性 (property):
- balance 是一个uint256的数,成员属性
address x = 0xca35b7d915458ef540ade6068dfe2f44e8fa733c;
x.balance // x地址上的余额,单位 wei,1 ether = 10^18 wei;
- transfer 成员方法
地址的成员方法和属性先不讲,后面再看
(4)字符串类型(String Literals)
字符串可以通过""或者''来表示字符串的值,Solidity中的string字符串不像C语言一样以\0结束
pragma solidity ^0.4.14;
contract StringLiterals{
string _name = "Gao";
}
备注:string字符串不能通过length方法获取其长度。
(5)固定大小字节数组类型
固定大小字节数组可以通过 bytes1, bytes2, bytes3, …, bytes32来进行声明。byte的别名就是 bytes1
- bytes1只能存储一个字节,也就是二进制8位的内容。
- bytes2只能存储两个字节,也就是二进制16位的内容。
- bytes3只能存储三个字节,也就是二进制24位的内容。
pragma solidity ^0.4.4;
contract C {
byte a = 0x6c; // 0110 1100
bytes1 b = 0x6c; // 0110 1100
bytes2 c = 0x6c69; // 0110 1100 0110 1001
bytes3 d = 0x6c6979; // 0110 1100 0110 1001 0111 1001
//.length 返回字节的个数
function gByteLength() constant returns (uint) {
return a.length;
}
// a.length = length; 报错
// 内部字节不可修改
c[0] = b; // c是2个字节的,将第一个字节改为b
// 访问某个字节
c[1];
}
(6)动态大小字节数组类型
string 是一个动态尺寸的UTF-8编码字符串,它其实是一个特殊的可变字节数组,string是引用类型,而非值类型。
bytes 动态字节数组,引用类型。
在我们不确定字节数据大小的情况下,我们可以使用string或者bytes,而如果我们清楚的知道或者能够将字节书控制在bytes1 ~ bytes32,那么我们就使用bytes1 ~ bytes32,这样的话能够降低存储成本。
创建bytes字节数组
pragma solidity ^0.4.14;
contract C {
// 初始化一个两个字节空间的字节数组
bytes public name = new bytes(2);
// 设置字节数组的长度
function setNameLength(uint len) {
name.length = len;
}
// 返回字节数组的长度
function nameLength() constant returns (uint) {
return name.length;
}
// 往字节数组中添加字节
function pushAByte(byte b) {
name.push(b);
}
// 当字节数组的长度只有2时,如果你通过push往里面添加了一个字节,那么它的长度将变为3,当字节数组里面有3个字节,但是你通过length方法将其长度修改为2时,字节数组中最后一个字节将被从字节数组中移除。
}
(7)数组类型(Arrays)
- 固定长度的数组(Arrays)
pragma solidity ^0.4.14;
contract C {
// 数组的长度为6,数组里面的存储的值的类型为uint类型
uint [6] T = [1,2,3,4,5,6];
// 固定长度为2的静态数组:
uint[2] fixedArray;
// 固定长度为5的string类型的静态数组:
string[5] stringArray;
}
通过length方法获取数组长度遍历数组求总和
pragma solidity ^0.4.4;
contract C {
// 数组的长度为5,数组里面的存储的值的类型为uint类型
uint [5] T = [1,2,3,4,5];
// 通过for循环计算数组内部的值的总和
function numbers() constant public returns (uint) {
uint num = 0;
for(uint i = 0; i < T.length; i++) {
num = num + T[i];
}
return num;
}
}
声明数组时,一旦长度固定,将不能再修改数组的长度。
- 可变长度的Arrays
可变长度类型数组的声明
pragma solidity ^0.4.14;
contract C {
uint [] T = [1,2,3,4,5];
// uint [] T = [1,2,3,4,5],这句代码表示声明了一个可变长度的T数组,因为我们给它初始化了5个无符号整数,所以它的长度默认为5。
// 尝试通过push往T数组中添加值
function pushUintToT() public {
T.push(6);
}
}
对可变长度的数组而言,可随时通过length修改它的长度。
(8) 枚举类型(Enums)
ActionChoices就是一个自定义的整型,当枚举数不够多时,它默认的类型为uint8,当枚举数足够多时,它会自动变成uint16,下面的GoLeft == 0,GoRight == 1, GoStraight == 2, SitStill == 3。在setGoStraight方法中,我们传入的参数的值可以是0 - 3当传入的值超出这个范围时,就会中断报错。
pragma solidity ^0.4.14;
contract test {
// 定义枚举类型
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
ActionChoices _choice;
ActionChoices defaultChoice = ActionChoices.GoStraight;
function setGoStraight(ActionChoices choice) public {
_choice = choice;
}
function getChoice() constant public returns (ActionChoices) {
return _choice;
}
function getDefaultChoice() pure public returns (uint) {
return uint(defaultChoice);
}
}
(9) 结构体类型(Structs)
自定义结构体
pragma solidity ^0.4.14;
contract Students {
struct Person {
uint age;
string name;
}
// Person就是我们自定义的一个新的结构体类型,结构体里面可以存放定义类型的值。
}
初始化一个结构体
方法一:
pragma solidity ^0.4.14;
contract Students {
struct Person {
uint age;
string name;
}
Person _person = Person(22,"gao");
}
------------------------------------------------------------
方法二:
pragma solidity ^0.4.4;
contract Students {
struct Person {
uint age;
string name;
}
Person _person = Person({age:18,name:"liyuechun"});
}
(10) 字典类型(Mappings)
语法:mapping(_KeyType => _ValueType) 键值对存储关系
pragma solidity ^0.4.14;
contract MappingExample {
// 测试账号
// 0xc1ce4f401951cd996f2628935acc858647489eef
mapping(address => uint) balances;
function update(address a,uint newBalance) public {
balances[a] = newBalance;
}
}
4、值类型与引用类型
值类型包含:
- 布尔(Booleans)
- 整型(Integer)
- 地址(Address)
- 定长字节数组(fixed byte arrays)
- 有理数和整型(Rational and Integer Literals,String literals)
- 枚举类型(Enums)
- 函数(Function Types)
引用类型包含:
- 不定长字节数组(bytes)
- 字符串(string)
- 数组(Array)
- 结构体(Struts)