【笔记】Solidity智能合约

前言

Solidity智能合约学习笔记

开发工具

通过RemixIDE在线编辑器

通过IDEA插件高亮Solidity代码

编写智能合约

  • 创建智能合约,定义状态变量,定义函数
  • Solidity代码以.sol结尾,需要部署在区块链上执行
  • 智能合约名必须与文件名相同
  • 文件第一行// SPDX-License-Identifier: GPL-3.0定义开源协议
  • 通过pragma solidity ^0.8.0;定义Solidity编译器版本
  • 通过constructor定义构造方法,构造方法在智能合约被部署时执行1次
contracts/智能合约名.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract 智能合约名 {
数据类型 状态变量名;
数据类型 权限修饰符 状态变量名;

constructor() {
...
}

function 函数名(数据类型 数据存储位置标识 形参名, 数据类型 形参名) 权限修饰符 {
状态变量名 = 形参名;
状态变量名 = 形参名;
}

function 函数名() public 函数类型标识 returns (返回值类型 数据存储位置标识, 返回值类型) {
return (返回值, 返回值);
}
}

上链时燃料费(Gas)的付费方式

  • 如果是开发环境
    • 如果配置文件没有指定支付账号,则由测试链第一个账号支付燃料费
    • 如果配置文件指定了支付账号,则由该账号支付燃料费
  • 如果是真实环境,则由调用智能合约者支付燃料费

变量的作用域

  • 状态变量:智能合约内、函数外的变量都是状态变量,所有合约内的函数都能访问,存储在链上,燃料费消耗高
  • 局部变量:函数内的变量都是局部变量,局部变量仅在函数执行过程中有效,函数执行结束后无效,局部变量的数据存储在内存中,不上链,燃料费消耗低
  • 全局变量:Solidity预留的变量
    • msg.sender:连接账号的公钥(地址)
    • block.number:区块的编号
    • msg.sender:发起交易的人的钱包公钥

数据类型

基本数据类型 备注
uint8 8位无符号整型
uint16 16位无符号整型
uint32 32位无符号整型
uint64 64位无符号整型
uint128 128位无符号整型
uintuint256 256位无符号整型
address 区块链地址类型
引用数据类型 备注
string 字符串

权限修饰符

  • 权限修饰符可以标识函数或状态变量
标识符 是否外部智能合约可以调用 是否内部智能合约可以调用 是否子智能合约可以调用
external
public
internal
private

标识状态变量

  • 状态变量如果设置为公有的,会自动添加Getter方法,并赋值给该状态变量
contracts/智能合约名.sol
1
2
3
4
5
6
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract 智能合约名 {
数据类型 权限修饰符 状态变量名;
}
  • 以函数的形式调用该状态变量即可获得状态变量的值
1
2
truffle(development)> const obj = await 智能合约名.deployed();
truffle(development)> obj.状态变量名();

标识数组类型的状态变量

contracts/智能合约名.sol
1
2
3
4
5
6
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract 智能合约名 {
数据类型[] 权限修饰符 状态变量名;
}
  • 以函数的形式调用该状态变量,并且传递下标,即可获得数组类型状态变量中指定下标的值
1
2
truffle(development)> const obj = await 智能合约名.deployed();
truffle(development)> obj.状态变量名(索引);

标识函数

1
2
3
function 函数名() 权限修饰符 {
...
}

数据存储位置

  • 基本类型不需要设置数据存储位置

数据存储位置

storage:缺省值,上链,状态变量存在storage中
memary:不上链,函数的参数和临时变量可以存在memory中,变量可以修改,消耗燃料费少
calldata:不上链,函数的参数和临时变量可以存在calldata中,变量不能修改,消耗燃料费少

1
2
3
function  函数名(string 数据存储位置 形参名, uint 形参名) 权限修饰符 {
...
}

函数类型

函数类型

无标识:缺省值,上链,函数内对状态变量可读写

1
2
3
function 函数名() 权限修饰符 {
状态变量名 = 值;
}

函数类型

view:不上链,函数内对状态变量只读
pure:不上链,函数内对状态变量不可读写

1
2
3
function 函数名() 权限修饰符 函数类型 returns (返回值类型) {
return (返回值);
}

结构体

  • 定义并实例化结构体
contracts/智能合约名.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract 智能合约名 {
struct 结构体名 {
数据类型 结构体属性名1;
数据类型 结构体属性名2;
}

function 函数名() public {
结构体名 变量名 = 结构体名(属性值1, 属性值2);
}
}

数组

声明数组

1
数据类型[数组长度] 数组变量名;

声明动态数组

1
数据类型[] 数组变量名;

向数组末尾追加数据

1
数组变量名.push(值);

获取数组长度

1
数组变量名.length;

映射

声明映射

1
mapping(键数据类型 => 值数据类型) 映射变量名;

检测是否满足条件

  • 满足条件程序会继续执行,不满足条件程序会终止并报错
1
require(布尔表达式);

完成

参考文献

哔哩哔哩——千锋教育