目录
注意事项
编译器选择
一些说明
1. 变量
1.1 状态变量
1.2 局部变量
2. 数据类型
2.1 值类型
2.1.1 布尔类型(Booleans):
2.1.2 整型(Integers):
2.1.3 定长浮点型(Fixed Point Numbers):
2.1.4 定长字节数组(Fixed-size byte arrays)
2.1.5 有理数和整型常量(Rational and Integer Literals)
2.1.6 枚举(Enums)
2.1.7 函数类型(Function Types)
修饰符
函数定义
函数返回值
构造函数
2.1.8 地址类型(Address)
基础知识
转账
2.2 引用类型
2.2.1 字符串
2.2.2 数组
2.2.3 结构体:
2.2.4 mapping:映射,
2.2.5 storage和memory
bytes1、bytes、string相互转换
最后
Solidity是一种智能合约高级语言,运行在Ethereum虚拟机(EVM)之上。Solidity是以太坊的首选语言,它内置了Serpent的所有特性,它的语法接近于Javascript,是一种面向对象的语言,这降低了学习门槛,易于被掌握和使用,因为JavaScript是Web开发者的常用语言。因此,Solidity充分利用了现有数以百万程序员已掌握JavaScript这一现状。
以太坊智能合约编程语言,语法简单,但是有不成熟不完善,有bug,没有多线程
注意事项
编译器选择
使用的是Remix IDE编译器 下载地址 —> Remix IDE下载地址
这个编译器对中文很不友好!吐槽一下!
一些说明
一个 contract 里面就是一个合约,没有main函数,只要合约部署就可以运行
一定要有头部版本号申明:pragma solidity 0.4.24;
每一行结尾得有分号(;)结束
注释:中文必须在外面写好然后拷贝,不能直接在里面写中文注释!对中文很不友好!
1. 变量
1.1 状态变量
定义在合约之内,但是在函数之外的变量,叫做状态变量,这些变量会上传到区块链保存的,默认是私有的,可以使用public和private修饰
pragma solidity 0.4.24; contract HelloWorld{ string public name; // 这个就是状态变量,使用public修饰 function hello(string memory text) public pure returns(string memory) { return text; } }
1.2 局部变量
在合约之内,在函数之内,局部变量不能使用public
pragma solidity 0.4.24; contract Hello{ function hello(string memory text) public pure returns(string memory) { string name = "FanOne"; // 这个就是局部变量 return text; } }
状态变量默认是私有的,可以使用public修饰
2. 数据类型
2.1 值类型
2.1.1 布尔类型(Booleans):
true或false,默认是false
!逻辑非
&& 逻辑与
|| 逻辑或
== 等于
!=不等于
pragma solidity 0.4.24; contract DataType { // bool public ok = true; bool public ok; // def is false function test() returns(string){ if (ok) { return "this is true"; }else { return "this is false"; } } }
2.1.2 整型(Integers):
int/uint: 表示有符号和无符号不同位数整数
以8位为区间,有int8,int16,int24,…,int256,int默认是int256,uint同理
int8 num; int256 total = 120;
举例:两个数相加的结果
pragma solidity 0.4.24; contract Add { int8 i1 = 10; int16 i2 = 11; function add() returns (int8){ return i1 + int8(i2); // 类型强转 }
2.1.3 定长浮点型(Fixed Point Numbers):
fixed/ufixed: 表示有符号和无符号的固定位浮点数
还不完全支持,它可以用来声明变量,但不可以用来赋值
2.1.4 定长字节数组(Fixed-size byte arrays)
关键字有:bytes1, bytes2, bytes3, …, bytes32。
byte 代表 bytes1。bytes1存储1个字节,即8位,bytes2存储2个字节,步长为1字节递增
.length:表示这个字节数组的长度(只读),返回的是定长字节数组类型的长度,而不是值的长度
长度不能修改
可以通过下标获取
元素值不可修改,只读
pragma solidity 0.4.24; contract TestBytes { bytes1 public b0; // 字节:0x00 bytes1 public b1 = "f"; // 0x66 bytes2 public b2 = "fa"; // 0x6661 bytes6 public b6 = "fanone"; bytes32 public b32 = "FanOne"; function getLen() returns(int256){ return b32.length; } function getByIndex() returns(bytes1){ return b1[0]; } }
2.1.5 有理数和整型常量(Rational and Integer Literals)
表达式中直接出现的数字常量:
整数,小数,科学计数都支持(9e30:6*200^10)
2.1.6 枚举(Enums)
自定义类型
至少要有一个元素,默认位uint8,不要忘了花括号
enum Gender { Male, FeMale }
// Gender为自定义类型,设置默认值
Gender default = Gender.Male
2.1.7 函数类型(Function Types)
状态变量:默认是private
函数:默认是public
修饰符
public:公有,拥有以太坊的账户都可以调用,可以修饰状态变量
private:私有,只有合约内部可以调用,可以修饰状态变量
view / constant:函数会读取但是不会修改任何合约的状态变量
pure:函数不适用任何合约的状态变量
payable:调用函数需要付钱,钱付给了智能合约的账户
returns:返回值函数声明中使用
external:仅合约外部可以调用,合约内部需要使用this调用
internal:仅合约内部和继承的合约可以调用
修饰符在returns声明的前面,可以有多个修饰符
view、constant、pure的区别:都是针对状态变量的
函数中访问了状态变量,但是没有修改,使用view或者constant
如果没有使用状态变量,则使用pure修饰
如果即访问了状态变量,又修改了,则不要修饰即可。
注意坑:constant修饰的函数中,修改了状态变量,编译器不会报错,但是运行是修改不成功的。
payable
想要转钱,修饰符必须是payable
payable的修饰符,转的钱到合约中了
function setMoney(string str) public payable returns(string) { return str; }
署的时候,交易金额给个值,会发现金额减少了,钱到了合约,注意交易金额的单位,用ether,不然看不到大的变化
获取合约中的钱
function getMoney() public view returns(uint256){ return this.balance; }
this代表当前合约本身,balance获取当前合约的余额
函数定义
function 函数名称(可选参数) 修饰符 返回值{
函数体
}
例:
function Add(a int8) public view returns(int8){ return a }
函数返回值
使用returns指定返回的类型
返回值声明一定要放在最后
多个返回值使用元组:使用括号括起来()
构造函数
进入合约就执行,一般设置一些初始化后不变的数据
constractor() public { owner = msg.sender; }
public:共有,可以修饰函数,可以修饰状态变量
provate:私有,可以修饰函数,可以修饰状态变量
view/constant:用了状态变量,但是没有修改状态变量,只能修饰函数
pure:没有使用状态变量,只能修饰函数
payable:只能修饰函数,转账的话必须使用payable,钱从账户过来,钱到合约
returns:在函数最后,返回值
状态变量在函数中修改了,就不要使用(view\constant\pure)修饰符
2.1.8 地址类型(Address)
基础知识
地址是所有合约的基础,所有合约都继承地址对象
通过合约的地址串,调用合约内的函数,本质是uint160,可以进行加减,需要强转
balance:获取余额
transfer:转账,推荐使用,谁调用就是给谁转
send:转账,不安全,不推荐使用,合约余额不够需要自己手动处理,不会报错
call:合约内部调用合约,调用底层代码,别用
callcode:调用底层代码,别用
delegatecall:调用底层代码,别用
this指合约本身
address(this),直接使用this会有warning
账户–>账户:不支持
账户–合约:paybable
合约–账户:transfer,谁调用就是给谁转
合约–合约 看高级用法
换算:1ether = 10**18wei (10^18),单位默认是wei
转账
pragma solidity 0.4.24; contract TransferDemo { uint256 public a; function constractGetMoney() public payable{ } function getConstractBalance() public { a = address(this).balance; } address to_addr = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c; function trans() public { to_addr.transfer(5 * 10 ** 18 ); //define is wei //need to transfer eth } }
这里有很多地址可选择
钱到哪去:向谁转钱,就用谁调用transfer
钱从哪来:合约的钱(payable),合约的钱不够transfer的时候会报错
2.2 引用类型
2.2.1 字符串
不支持索引
不支持length和push方法
可以修改,需要通过bytes转换
string me = "fanone";
转bytes,然后就可以使用bytes的特性了
bytes(me).length;
bytes转string
string(bytes)
不定长字节数组:bytes:
支持length,push(在最后追加)方法
可以修改
支持索引,如果未分配空间(new分配空间),使用下标会报角标越界,其他的会自动分配空间
以十六进制格式赋值
bytes me = "fanone" name.push("666")
2.2.2 数组
内置数组:string、bytes、bytes1…bytes32
自定义定长数组:长度不可变,支持length,不支持push
uint256[5] public nums = [1,2,3,4,5];
自定义不定长数组:长度可变,内容可修改,支持length,push方法
uint256[] public nums = [1,2,3,4,5]; nums.push(6) delete nums;
函数中使用new分配空间
uint8[] memory aa = new uint8[](10);// 10个长度的空间
2.2.3 结构体:
函数不支持返回结构体对象,可以把值放到元组中返回(按个放到()中,返回元组)
struct 结构体名称{ 类型 字段名; }
struct Person { string name; uint age; } // 指定字段名,必须用()括起来,里面是花括号 Person public p1 = Person({name:"hallen",age:18}); // 按顺序初始化值,注意是括号()不是花括号{} Person public p2 = Person("hallen",18); // 结构体不定长数组 Person[] persons; // 函数中可以往里面添加值,类型必须是结构体初始化对象 persons.push(p1);
2.2.4 mapping:映射,
无法判断是否存在某个key
不支持length
mapping(string=>string) map_data; // 函数中赋值 map_data["name"] = "hallen"; //获取指定的key的值 string storage aa = map_data["name"];
2.2.5 storage和memory
storage:数据永远保存,引用传递,只有引用类型的变量才可以显示的声明为storage。
memory:存在内存中,会被回收,数据会过期丢失,类似值类型
bytes1、bytes、string相互转换
bytes1转string要经过中间的bytes
角标用uint256类型,不然会类型不匹配
最后
小生凡一,期待你的关注。