Solidity 基础知识 | 以太坊智能合约编程语言
Posted 小生凡一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Solidity 基础知识 | 以太坊智能合约编程语言相关的知识,希望对你有一定的参考价值。
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
类型,不然会类型不匹配
最后
小生凡一,期待你的关注。
以上是关于Solidity 基础知识 | 以太坊智能合约编程语言的主要内容,如果未能解决你的问题,请参考以下文章