Move语言笔记
快速创建一个 Sui package 框架⚓︎
sui move new <PACKAGE NAME>
这条指令创建了:
- 项目根文件夹
hello_world
Move.toml
配置文件- 用于存放 Sui Move 智能合约的
sources
子文件夹
Move.toml
包含三个部分:
[package]
声明了该 package 的命名和版本数[dependencies]
声明了该 package 依赖的其他 packages, 包括 Sui 标准库和其他第三方依赖库[addresses]
声明了该 packages 源代码中地址的别名
基本数据类型⚓︎
Integers
(u8, u64, u128), boolean
and address
.
即整型、布尔型、地址型。
Integer types 整数类型⚓︎
u8
表示一个无符号的 8 位整数,也就是一个字节。u64
表示一个无符号的 64 位整数,也就是 8 字节。u128
表示一个无符号的 128 位整数,也就是 16 字节。
这些类型后面的数字表示整数分配的内存空间的大小。所以,u8 表示的是 1 个字节的内存空间大小,u64 表示的是 8 个字节的内存空间大小,而 u128 表示的是 16 个字节的内存空间大小。
定义方式:
Boolean 布尔类型⚓︎
Address 地址⚓︎
地址是区块链中发送者(或钱包)的标识符。需要地址类型的最基本的操作是发送硬币和导入模块(module)。
数值比较⚓︎
使用运算符 as 将整数变量转换为另一个大小:
同等大小类型的整数才可以比较
注释⚓︎
初始化变量⚓︎
使用 let
在当前范围内创建新变量,并选择性地使用 value
初始化此变量let <VARIABLE> : <TYPE>;
or let <VARIABLE> = <EXPRESSION>
下划线——未使用⚓︎
在 Move 中,必须使用每个变量(否则您的代码将无法编译),因此您不能初始化一个变量并保持其不变。虽然您有一种方法可以将变量标记为故意未使用 - 通过使用下划线 _
。
Move 允许您定义相同的变量两次,但有一个限制 - 它仍然需要使用。
块表达式与作用域⚓︎
块是一个表达式;它标有大括号 - {}
。块可以包含其他表达式(和其他块)。
在定义块时,您实际上定义了一个范围。
变量的生命周期⚓︎
变量仅存在于定义它的作用域(或块)内。当其作用域结束时,变量将死亡。
块返回值⚓︎
控制流⚓︎
if表达式⚓︎
if (<bool_expression>) <expression> else <expression>;
- 分支兼容性:两个分支必须返回兼容(相同)类型
if
可以单独使用 - 没有else
- 没有
else
分支的表达式不能用于赋值
条件while循环⚓︎
while (<bool_expression>) <expression>;
无限loop循环⚓︎
break与continue⚓︎
关于分号。如果 break 和 continue 是块中的最后一个关键字,则不能在它们后面加上分号,因为 after 之后的任何代码都不会被执行。
有条件的中止abort⚓︎
assert条件中止⚓︎
内置 assert!(<bool expression>, <code>)
方法已经包装了 abort + 条件
,并且可以在代码中的任何位置访问。左边的条件必须为真,否则执行右边。assert()
当不满足条件时将中止执行,或者在相反的情况下将不执行任何操作。
模块module⚓︎
模块以 module
关键字开头,后跟模块名称和大括号 - 其中放置了模块内容。
默认情况下,您的模块将从您的地址编译和发布。但是,如果您需要在本地使用某些模块(例如用于测试或开发)或想在模块文件中指定您的地址,请使用 address <ADDR> {}
语法
导入模块或标准库⚓︎
- 您可以直接在代码中按模块的地址使用模块:
在此示例中,我们从地址0x1
(标准库)导入了模块Offer
并使用了它的方法
- 关键字导入
use <Address/Alias>::<ModuleName>;
<Address>
是发布者的地址,也是 <ModuleName>
模块的名称。
- 成员导入:可以扩展
import
语句 - 您可以指定要导入的模块的哪些成员: - 用于
Self
将模块与其成员一起导入 - 使用关键字
as
更改导入模块的名称。use <Address>::<ModuleName> as <Alias>;
常量⚓︎
函数⚓︎
定制类型⚓︎
Structure 使用关键词 struct 声明。一个 structure 最多拥有 4 项能力。
四类能力特性:
函数可见性⚓︎
- private: 作为函数可见性的默认设置;只允许同一 module 内的函数获取
- public: 该函数既可以被同一 module 内的函数获取,也可以被其他 module 定义的函数获取
- public(friend): 该函数既可以被同一 module 内的函数获取,同时也可以被该 module 的 friends 清单上包含的 module 所定义的函数获取。
Entry 函数⚓︎
在 Sui Move 中,entry 函数可以被交易 transactions 直接调用。它们需要满足下面三个条件:
- 被关键词 entry 标注
- 没有返回值
- (可选) 最后一个参数是 TxContext 类型实例的可变引用
部署智能合约⚓︎
sui client publish --path <absolute local path to the Sui Move package> --gas-budget 100000000
(要是提示gas不够就多加几个0)
- 获取测试币
Win:(Powershell中执行)
PowerShell | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
PowerShell | |
---|---|
1 |
|
- 跳过版本检查:
--skip-fetch-latest-git-deps
- 跳过依赖性检查:
--skip-dependency-verification
- 输出中文
Text Only | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
再次发布智能合约
sui client publish --gas-budget 100000000 --skip-fetch-latest-git-deps --skip-dependency-verification
调用函数,传入参数args
sui client call --function mint --module hello --package 0x0379266c1b772298bd93d0da5f8f684f30f9c5eb2be5af36d9f06f5ee7c47179 --args "你好,世界" --gas-budget 10000000
在sui explorer上查看相关信息,输入
Transaction Effects
下的 Created Objects ID
可以看到text信息
Sui Objects 所有权⚓︎
在 Sui Move 中总共有四种类型的所有权。
被拥有的 Objects⚓︎
- 被一个地址拥有:使用transfer方法将一个object转移到一个地址
(transfer的函数方法调用会完全消耗掉object,即transfer之后object在当前交易中是不能再次被获取的)
之后对object的读写操作都必须由object所有者发起交易use sui::transfer
transfer::transfer(obj, recipient);
被另一object拥有的object(子object)⚓︎
使用dynamic_object_field
方法创建的object
不可变的共享object(不能被修改和删除,也不能解冻)⚓︎
可变的共享object⚓︎
可被任何人读写transfer::share_object(obj);
参数传递与删除Object⚓︎
结构体嵌套(Object Wrapping)⚓︎
实现成绩单信息的请求和解包
用与权限管理的Capability模式⚓︎
把带有管理员权限的能力也设计成一个Object并赋予给特定账户,同时限定需要管理员运行的函数方法
增加传入的参数TeacherCap
,并用下划线将它标注为未使用的变量或参数
添加管理员
日志(Events)⚓︎
要引用use sui::event;
在函数中添加发送events信息
泛型⚓︎
泛型是具体类型或其他属性的抽象替代品。