Solidity 是一个面向合约开发的高级语言,借鉴了其他一些高级语言,例如 Javascript 和 Python,的特性。它是一门静态类型语言,支持继承,支持各种库和用户自定义的类型。非常适合用来开发类似于投票,众筹,拍卖,多重签名钱包等各种功能。
有一定的编程基础非常好入门
测试可以直接在在线网址https://remix.ethereum.org上
CryptoZombies是一个很有趣的学习网址
注意solidity在后续版本0.5.0之后有较大变革,但下面学习内容依旧是根据0.4版本来进行的,是想先熟悉了再看改变了什么
简单举例
把一个数据保存到链上
// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.4.16 <0.9.0;contract SimpleStorage {uint storedData;function set(uint x) public {storedData = x;}function get() public view returns (uint) {return storedData;}}
// 是solidity中的注释
第一行是说明源代码是根据GPL 3.0版本授权的。
第二行的意思是告诉编译器源代码所适用的Solidity版本为>=0.4.16 及 <0.9.0 。
contract SimpleStorage
是指建立一个名为SimpleStorage的合约。
uint storedData
定义一个名为storedData的uint型数据。
function set(uint x) public {
建立一个名为set的、参数是一个uint型数的函数。此处的public
是一种solidity访问权限设定的一种,是公开的意思,将允许这个函数在合约外也能被调用
function get() public view returns (uint)
建立一个名为get、不需要参数、返回一个uint型数的函数。此处的view
是一种修饰符,意思是可以自由调用,但是它只能“查看”区块链的状态而不能够改变它,也就是说在这个函数中只能够查看函数外某参数的值,而当你试图改变这个变量时就不能做到。
以上代码,首先定义了一个uint型的数,然后用set函数,输入一个数对storedData进行赋值,这将使这个值被存储在区块链上面,让get函数是可以将这个storedData的值读出来的函数。
Remix IDE简单使用
左边建立一个文件,右边进行编写
点击compile examp进行编译,下一个选项中deploy实施部署
部署完成后点击下方函数名调用
上面可以查看账户余额
数据类型
int型:有符号整数,默认256位。也可以自己规定位数,比如想要一个8位的int型有符号整数numa,则int8 numa;
uint型:无符号整数,默认256位。同样可以自己规定位数
bool型:布尔型,有true、false两种。定义一个布尔型数,不赋值默认是false
bytes型:字节型数组,可自定义长度例如bytes1 public num1 = 0x12;
,可以通过num1.length
得到字节数组长度。这时数组长度是固定的,要想得到一个可变成长度的字节数组,定义方式为bytes arr1 = new bytes(3);
这就定义了一个长度为3的字节型,可以通过arr1.length=a;
来改变字节长度。注意,不能像int型那样不规定长度的定义。
另外,可以赋值的语句是arr1[0]=0x11;
,输出时可以一位一位的输出,也可以直接输出整个数组。arr1.push(0x56);
push函数可以在arr1后面追加一个字节的值,但是注意只能让长度加1,多了会报错。
注意,当你想再函数中改变数组的值时,不能对函数使用view修饰。
string型:字符型。定义变量方式string testword="helloworld";
,这里用单引号和双引号是一样的效果。这里不需要提前定义长度,默认就是可变的,想知道当前长度也不能有直接加length函数,而是应该先将类型转换为字节型bytes(testword).length
;改变值时依旧需要强制类型转换bytes(testword)[0]='A';
。返回值时,可以直接返回字符型,想知道16进制值时就可以将类型转换,同样bytes型输出时也可以强制转换为string型。
注意一个字符长度是1,一个汉字长度为3;储存中文和一些其他语言时,solidity使用的时UTF-8格式存储的。
数组:除了字节型数组外,还可以有数字型数组,语法跟bytes型一样,例如uint[3] testarr1;
定义一个长度为3的无符号型整数数组。这里想知道长度不需要转换类型。定义可变长度数组可以是uint[] testarr=[1,2,3,4,5];
;此时可以改变数组长度testarr.length=10;
变长之后后面默认置0,依旧支持push函数在数组后面追加一个数。
二维数组:首先要明确定义二维数组时,例如uint[i][j]
:代表的是有j个元素,每个元素包含i个值,这和其他许多语言相反。支持使用length函数获取长度,对数组直接用length函数得到的是j的值,也可以对uint[0]用length函数得到的是i的值。另外在对二维数组进行增删改等操作时又和其他语言一样了,即uint[i][j]
表示第i个元素的第j个值,注意不用于初始化的语法整反。
想要可变长度的数组时,同样可以用uint[][] testarr1=[[1,2],[3,4],[5,6]];
这样的语法来定义,跟一维数组不一样的是,二维不再支持push函数。依然支持对长度进行修改,但是注意未声明的值不能直接赋值,修改长度之后默认有值才可以,修改长度后未赋值的一样默认为0。
struct型:结构体,例如struct Person { uint age; string name; }
定义了一个名为Person类型的结构体,然后Person就可以像上面描述的类型一样被运用了。
常规运算
加减乘除:+ - * /
取余%
平方**
与或&& ||
按位与或非& | ~
否!
异或^
左移右移<>
注意:
关于赋值,solidity是先将赋值语句之中所有的都计算出来之后再进行赋值操作的,这样就保证了精确度。
另外要注意每种类型变量的长度,注意溢出问题
修饰符
solidity的四种可见度/访问权限
public:任何人都可以调用该函数,包括DApp的使用者。
private:只有合约本身可以调用该函数(在另一个函数中)。
internal:只有这份合同以及由此产生的所有合同才能称之为合同。
external:只有外部可以调用该函数,而合约内部不能调用。
solidity的三种修饰符
view: 可以自由调用,因为它只是“查看”区块链的状态而不改变它
pure: 也可以自由调用,既不读取也不写入区块链
payable:常常用于将代币发送给合约地址。
需要注意的小tip
运算中的类型转换
在数据进行运算时,有时你需要变换数据类型。例如:
uint8 a = 5;uint b = 6;uint8 c = a * b;// 将会抛出错误,因为 a * b 返回 uint, 而不是 uint8// 我们需要将 b 转换为 uint8:uint8 c = a * uint8(b);
上面, a * b 返回类型是 uint, 但是当我们尝试用 uint8 类型接收时, 就会造成潜在的错误。如果把它的数据类型转换为 uint8, 就可以了,编译器也不会出错。
伪随机数的一种
Ethereum 内部有一个散列函数keccak256,它用了SHA3版本。一个散列函数基本上就是把一个字符串转换为一个256位的16进制数字。
字符串的一个微小变化会引起散列数据极大变化。这在 Ethereum 中有很多应用。然后我们就可以根据这个思路来造一个伪随机数,尽管它是不安全的,却依然可以有一些地方可以使用。