-
Notifications
You must be signed in to change notification settings - Fork 886
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2020 from lizhecome/main
参加直播答疑_共学营+群里分享学习笔记_共学营+对外输出学习笔记_共学营
- Loading branch information
Showing
6 changed files
with
932 additions
and
5 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
# (十二)Move 语言学习笔记:妙趣横生的 “对象转移” 探秘 | ||
|
||
在区块链世界中,Move 语言作为一种灵活、高效的智能合约语言,其独特的设计理念和功能让人眼前一亮。今天我们将深入探讨一个核心功能——对象转移(Transfer to Object)。这一功能不仅解锁了 Move 语言在资产管理中的诸多潜力,也为实现复杂的业务逻辑提供了新的可能性。 | ||
|
||
## 一、对象转移的本质:从地址到对象 | ||
|
||
### 1. 对象与地址:一脉相承 | ||
|
||
在 Sui 网络中,对象 ID 和地址 ID 都是 32 字节长,且设计上不重叠。这种统一的设计使得对象 ID 可以直接用于接收转移对象,仿佛它是一个普通的地址。 | ||
|
||
```move | ||
// 将对象 b 转移到地址 0xADD | ||
sui::transfer::public_transfer(b, @0xADD); | ||
// 将对象 c 转移到对象 ID 为 0x0B 的对象 | ||
sui::transfer::public_transfer(c, @0x0B); | ||
``` | ||
|
||
无论转移的目标是地址还是对象,其结果都一致——转移后对象的所有者变成所指定的 ID。 | ||
|
||
### 2. “父子关系”与访问控制 | ||
|
||
当对象被转移到另一个对象后,两者之间形成了一种“父子认证”关系。接收对象的模块负责定义访问控制规则,限制子对象的访问权限。这一动态规则由父对象的 UID 在事务执行时实现。 | ||
|
||
- 子对象的所有权链可以是动态的,例如动态字段中的对象。 | ||
- 如果父对象是不可变的,无法将对象转移至其上。 | ||
|
||
## 二、转移对象的实际应用 | ||
|
||
### 1. 稳定的账户 ID | ||
|
||
通过将对象转移到其他对象或地址,可以保持账户或钱包的稳定 ID。无论该对象被转移、包装还是作为动态字段持有,其 ID 始终不变。 | ||
|
||
- 对象的子对象会随着父对象一起移动。 | ||
- 对象的地址始终保持一致。 | ||
|
||
### 2. 使用 JSON-RPC 查询对象所有权 | ||
|
||
Sui 的 JSON-RPC 接口支持查询特定地址或对象 ID 所拥有的对象。 | ||
|
||
```json | ||
// 查询地址 0xADD 所拥有的对象 | ||
{ | ||
"jsonrpc": "2.0", | ||
"id": 1, | ||
"method": "suix_getOwnedObjects", | ||
"params": ["0xADD"] | ||
} | ||
|
||
// 查询对象 ID 0x0B 所拥有的对象 | ||
{ | ||
"jsonrpc": "2.0", | ||
"id": 1, | ||
"method": "suix_getOwnedObjects", | ||
"params": ["0x0B"] | ||
} | ||
``` | ||
|
||
## 三、接收对象:从传递到使用 | ||
|
||
### 1. 接收机制的核心接口 | ||
|
||
Move 中,`sui::transfer::receive` 和 `sui::transfer::public_receive` 是接收对象的关键函数。 | ||
|
||
- `receive`: 只能在定义目标对象类型的模块内使用,适用于具有 key 能力的对象。 | ||
- `public_receive`: 可在任何模块中调用,适用于同时具备 key 和 store 能力的对象。 | ||
|
||
```move | ||
module sui::transfer { | ||
public native fun receive<T: key>(parent: &mut UID, object: Receiving<T>): T; | ||
public native fun public_receive<T: key + store>(parent: &mut UID, object: Receiving<T>): T; | ||
} | ||
// 接收类型为 Coin 的对象 | ||
let coin = sui::transfer::public_receive(&mut account.id, sent_coin); | ||
``` | ||
|
||
### 2. 自定义接收规则 | ||
|
||
通过对父对象模块中 UID 的访问权限控制,可以实现自定义接收规则。 | ||
|
||
- 限制特定地址才能接收对象。 | ||
- 对对象类型或状态施加动态约束。 | ||
|
||
```move | ||
module examples::shared_object_auth { | ||
struct SharedObject has key { | ||
id: object::UID, | ||
counter: u64, | ||
} | ||
const AuthorizedReceiverAddr: address = @0xB0B; | ||
public fun receive_object<T: key + store>(obj: &mut SharedObject, sent: Receiving<T>, ctx: &TxContext): T { | ||
assert!(tx_context::sender(ctx) == AuthorizedReceiverAddr, 0); | ||
transfer::public_receive(&mut obj.id, sent) | ||
} | ||
} | ||
``` | ||
|
||
## 四、案例:对象转移的多样化实现 | ||
|
||
### 1. 基本账户模型 | ||
|
||
通过动态字段实现账户余额管理。 | ||
|
||
- 接收不同类型的代币,并按类型存储。 | ||
- 支持余额查询和提现功能。 | ||
|
||
```move | ||
module examples::account { | ||
struct Account has key { | ||
id: object::UID, | ||
} | ||
struct AccountBalance<phantom T> has copy, drop, store { } | ||
public fun accept_payment<T>(account: &mut Account, sent: Receiving<Coin<T>>) { | ||
let coin = transfer::public_receive(&mut account.id, sent); | ||
if (df::exists_(&mut account.id, AccountBalance<T>{})) { | ||
let balance = df::borrow_mut(&mut account.id, AccountBalance<T>{}); | ||
coin::join(balance, coin); | ||
} else { | ||
df::add(&mut account.id, AccountBalance<T>{}, coin); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
### 2. “灵魂绑定”对象 | ||
|
||
通过自定义规则,实现一个必须“归还”的特殊对象。 | ||
|
||
- 收到对象时生成一个回执,必须在同一事务中销毁。 | ||
- 回执仅允许将对象转回原始父对象。 | ||
|
||
```move | ||
module examples::soul_bound { | ||
struct SoulBound has key { id: UID } | ||
struct ReturnReceipt { | ||
object_id: ID, | ||
return_to: address, | ||
} | ||
public fun get_object(parent: &mut UID, soul_bound_ticket: Receiving<SoulBound>): (SoulBound, ReturnReceipt) { | ||
let soul_bound = transfer::receive(parent, soul_bound_ticket); | ||
let receipt = ReturnReceipt { | ||
return_to: object::uid_to_address(parent), | ||
object_id: object::id(&soul_bound), | ||
}; | ||
(soul_bound, receipt) | ||
} | ||
public fun return_object(soul_bound: SoulBound, receipt: ReturnReceipt) { | ||
assert!(object::id(&soul_bound) == receipt.object_id, 0); | ||
sui::transfer::transfer(soul_bound, receipt.return_to); | ||
} | ||
} | ||
``` | ||
|
||
## 五、结语:对象转移的未来展望 | ||
|
||
对象转移功能是 Move 语言设计中的一颗明珠。它不仅带来了灵活的资产管理能力,还为去中心化应用的设计提供了无限可能。从账户模型到灵魂绑定对象,Move 的独特语言特性为开发者创造了全新的世界。 | ||
|
||
> **请用微信关注《HOH水分子》公众号,我们将持续分享和制作变成语言教程,让大家对编程产生化学反应。** | ||
![水分子社区](../images/HOH_QR.jpg) |
Oops, something went wrong.