Solidity - 02 - 基本语法

元素的可见性

private 修饰的函数为私有的,只有合约内部可以调用

Public修饰的函数为共有的,合约内外都可以调用

public/private 可以修饰状态变量

状态变量默认是私有的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
pragma solidity ^0.4.24;


contract Test {
//状态变量
//类型不匹配时需要显示转换类型
//返回值需要使用returns描述

//public/private 可以修饰状态变量
//状态变量默认是私有的
uint256 public ui256 = 100;

int8 private i10 = -10;


//private 修饰的函数为私有的,只有合约内部可以调用
function add() private view returns(uint256) {
return ui256 + uint256(i10);
}


function isEqueal() public view returns(bool) {
return ui256 == uint256(i10);
}

//Public修饰的函数为共有的,合约内外都可以调用
function Add() public view returns(uint256){
return add();
}
}

View,Constant,Pure介绍

==//在constant/view 修饰函数的函数中,如果去修改了状态变量,编译器不会报错,但是赋值不会成功(坑!!!!)==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
pragma solidity ^0.4.24;


contract Test {
//状态变量
//类型不匹配时需要显示转换类型
//返回值需要使用returns描述



//public/private 可以修饰状态变量
//状态变量默认是私有的
uint256 public ui = 100;

int8 private i10 = 10;


// 1. 如果函数中没有用到状态变量:(既没有读也没有写),就修饰为pure
// 2. 如果读了,但是没写,修饰为view、constant
// 3. 如果写了,那么不修饰即可

function add() public constant returns(uint256) {
return ui + uint256(i10);
}

function test() public pure returns(string) {
return "hello";
}

function setValue(uint256 num) public {
ui = num;
}

//在constant/view 修饰函数的函数中,如果去修改了状态变量,编译器不会报错,但是赋值不会成功(坑!!!!)
function setValue1(uint256 num) public constant {
ui = num;
}

function isEqueal() public view returns(bool) {
return ui == uint256(i10);
}

}

payable关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
pragma solidity ^0.4.24;


contract Test {

string public str ;

//修饰为payable的函数才可以接收转账
//不指定payable无法接收
function test1(string src) public payable {
str = src;
}

function test2(string src) public {
str = src;
}

function getbalance() public view returns(uint256) {
//this代表当前合约本身
//balance方法,获取当前合约的余额
return this.balance;
}
}

地址获取余额balance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
pragma solidity ^0.4.24;


contract Test {


address public addr1 = 0x0014723a09acff6d2a60dcdf7aa4aff308fddc160c;

//地址address类型本质上是一个160位的数字

//可以进行加减,需要强制转换
function add() public view returns(uint160) {
return uint160(addr1) + 10;
}


//1. 匿名函数:没有函数名,没有参数,没有返回值的函数,就是匿名函数
//2. 当调用一个不存在的方法时,合约会默认的去调用匿名函数
//3. 匿名函数一般用来给合约转账,因为费用低
function () public payable {

}


function getBalance() public view returns(uint256) {
return addr1.balance;
}


function getContractBalance() public view returns(uint256) {
//this代表当前合约本身
//balance方法,获取当前合约的余额
return address(this).balance;
}

}

地址转账

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
pragma solidity ^0.4.24;


contract Test {


address public addr0 = 0x00ca35b7d915458ef540ade6068dfe2f44e8fa733c;
address public addr1 = 0x0014723a09acff6d2a60dcdf7aa4aff308fddc160c;


//1. 匿名函数:没有函数名,没有参数,没有返回值的函数,就是匿名函数
//2. 当调用一个不存在的方法时,合约会默认的去调用匿名函数
//3. 匿名函数一般用来给合约转账,因为费用低
function () public payable {

}

function getBalance() public view returns(uint256) {
return addr1.balance;
}

function getContractBalance() public view returns(uint256) {
return address(this).balance;
}

//由合约向addr1 转账10以太币
function transfer() public {
//1. 转账的时候单位是wei
//2. 1 ether = 10 ^18 wei (10的18次方)
//3. 向谁转钱,就用谁调用tranfer函数
//4. 花费的是合约的钱
//5. 如果金额不足,transfer函数会抛出异常
addr1.transfer(10 * 10 **18);
}

//send转账与tranfer使用方式一致,但是如果转账金额不足,不会抛出异常,而是会返回false
function sendTest() public {
addr1.send(10 * 10 **18);
}
}

bytes1:内置的固定长度的字节数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
pragma solidity ^0.4.24;


contract Test {

bytes1 b1 ="h";

bytes20 b10 = "helloworld";

function getLen() public view returns(uint256) {
return b10.length;
}

function setValue() private pure {
//1. 固定长度数组可以通过下标访问
//2. 只能读取,不能写
//b10[0] = v;
}

//3. 存储的时候是ascii值存储
function getValue(uint256 i) public view returns(byte) {
return b10[i];
}
}

bytes动态字节数组

  1. 可以不分空间,直接进行字符串赋值,会自动分配空间

  2. 如果未分配过空间,使用下标访问会访问越界报错

  3. 可以设置长度,自动分配对应空间,并且初始化为0

  4. 可以通过下标进行数据修改

  5. 支持push操作,在bytes最后面追加元素

注意的坑:

旧版本的remix可以直接在remix中使用”helloworld”形式给bytes赋值,新版本不允许,必须使用0x格式

例如,如果函数类型为:byte b1, 那么赋值时需要输入的格式为: “h”(旧版本), 0x68(新版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
pragma solidity ^0.4.24;


contract Test {

bytes public name;


function getLen() public view returns(uint256) {
return name.length;
}

//1. 可以不分空间,直接进行字符串赋值,会自动分配空间
function setValue(bytes input) public {
name = input;
}

//2. 如果未分配过空间,使用下标访问会访问越界报错
function getByIndex(uint256 i) public view returns(byte) {
return name[i];
}

//3. 可以设置长度,自动分配对应空间,并且初始化为0
function setLen(uint256 len) public {
name.length = len;
}


//4.可以通过下标进行数据修改
function setValue2(uint256 i) public {
name[i] = 'h';
}

//5. 支持push操作,在bytes最后面追加元素
function pushData() public {
name.push('h');
}

}

string

  • 动态尺寸的UTF-8编码字符串,是特殊的可变字节数组
  • 引用类型
  • 不支持下标索引
  • 不支持length、push方法
  • 可以修改(需通过bytes转换)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pragma solidity ^0.4.24;


contract Test {

string public name = "lily";


function setName() public {
bytes(name)[0] = "L";
}

function getLength() public view returns(uint256) {
return bytes(name).length;
}

function setLength(uint256 i) public {
bytes(name).length = i;

bytes(name)[i - 1] = 'H';
}
}

storageVsMemory关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
pragma solidity ^0.4.24;


contract Test {
string public name = "lily";
uint256 public num = 10;



function call1() public {
setName(name);
}


//对于引用类型数据,作为函数参数时,默认是memory类型(值传递)
//function setName(string input) private {
function setName(string memory input) private {
num = 20;
bytes(input)[0] = "L";
}

function call2() public {
setName2(name);
}

//2. 如果想引用传递,那么需要明确指定为stroage类型
function setName2(string storage input) private {
num = 30;
bytes(input)[0] = "L";
}

//如果局部变量是string,数组,结构体类型数据,默认情况下是storage类型
function localTest() public {
//string tmp = name;
string storage tmp = name;
num = 40;
bytes(tmp)[0] = "L";
}

function localTest1() public {

//也可以明确设置为memory类型
string memory tmp = name;
num = 50;
bytes(tmp)[0] = "L";
}
}

byte1BytesString相互转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
pragma solidity ^0.4.24;


contract Test {

bytes10 public b10 = 0x68656c6c6f776f726c64; //helloworld

bytes public bs10 = new bytes(b10.length);

//将固定长度数组的值赋值给不定长度数组
function fixedByteToBytes() public {
//bs10 = b10;
for (uint256 i = 0; i < b10.length; i++) {
bs10[i] = b10[i];
}
}




//将bytes转成string
string public str1;

function bytesToString() public {
fixedByteToBytes();
str1 = string(bs10);
}



//将string转成bytes
bytes public bs20;

function stringToBytes() public {
bytesToString();
bs20 = bytes(str1);
}
}

自定义定长数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
pragma solidity ^0.4.24;


contract Test {

//Type[Len] name

uint256[10] public numbers = [1,2,3,4,5,6,7,8,9, 10];

uint256 public sum;

// - 类型T,长度K的数组定义为T[K],例如:uint [5] numbers, byte [10] names;
// - 内容可变
// - 长度不可变,不支持push
// - 支持length方法

function total() public returns(uint256) {
for (uint256 i = 0; i < numbers.length; i++) {
sum += numbers[i];
}

return sum;
}

function setLen() public {
//numbers.length = 10;
}

function changeValue(uint256 i , uint256 value) public {
numbers[i] = value;
}

//++++++++++++++++++++++++++++++++++

bytes10 public helloworldFixed = 0x68656c6c6f776f726c64;

byte[10] public helloworldDynamic = [byte(0x68), 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64];

bytes public b10;

function setToBytes() public returns (string){
for (uint256 i=0; i< helloworldDynamic.length; i++) {
byte b1 = helloworldDynamic[i];
b10.push(b1);
}

return string(b10);
}
}

自定义不定长数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
pragma solidity ^0.4.24;


contract Test {

//第一种创建方式,直接赋值
uint8[] numbers = [1,2,3,4,5,6,7,8,9,10];

function pushData(uint8 num) public {
numbers.push(num);
}

function getNumbers() public view returns(uint8[]) {
return numbers;
}


//使用new关键字进行创建,赋值给storage变量数组
uint8[] numbers2;

function setNumbers2() public {
numbers2 = new uint8[](7);
numbers2.length = 20;
numbers2.push(10);
}

function getNumbers2() public view returns(uint8[]) {
return numbers2;
}

function setNumbers3() public {
//使用new创建的memory类型数组,无法改变长度
//uint8[] memory numbers3 = new uint8[](7);
uint8[] memory numbers3;

//numbers3.push(10);
}
}

结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
pragma solidity ^0.4.24;
//pragma experimental ABIEncoderV2;

contract Test {
//定义结构之后无分号,与枚举一致
struct Student {
string name;
uint age;
uint score;
string sex;
}

Student[] public Students;


//两种赋值方式
Student public stu1 = Student("lily", 18, 90, "girl");
Student public stu2 = Student({name:"Jim", age:20, score:80, sex:"boy"});

function assign() public {
Students.push(stu1);
Students.push(stu2);

stu1.name = "Lily";
}

// function returnStudent() public view returns(Student) {
// return stu1;
// }

//使用圆括号包裹起来的类型叫做元组“tuple”
//特性:1. 不可修改,2.可以容纳不同类型的数据
function returnStudent() public view returns(string, uint, uint, string) {
return (stu1.name, stu1.age, stu1.score, stu1.sex);
}
}

mapping

  1. 相同的key对应的值会被覆盖
  2. 所有key都有值,不会抛异常,如果没有设置过某个key,会返回默认值
    1. bool : false
    2. int:0
    3. string : “”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pragma solidity ^0.4.20;


contract Test {
//id -> name
mapping(uint => string) public id_names;



//构造函数:
//1. 对象在创建的时候,自动执行的函数,完成对象的初始化工作
//2. 构造函数仅执行一次

// function Test() public {

// }

constructor() public{
id_names[1] = "lily";
id_names[2] = "Jim";
id_names[3] = "Lily";
id_names[3] = "Tom";
}

function getNameById(uint id) public returns (string){
//加上storage如何赋值?
string memory name = id_names[id];
return name;
}

function setNameById(uint id) public returns (string){
// mapping(uint => string) memory id_name = id_names;
// var ids = id_names;
id_names[id] = "Hello";
}


// function getMapLength() public returns (uint){
// return id_names.length;
// }

}
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

请我喝杯咖啡吧~

支付宝
微信