diff --git a/pages/_meta.json b/pages/_meta.json index c76d40c..4de190f 100644 --- a/pages/_meta.json +++ b/pages/_meta.json @@ -2,11 +2,11 @@ "index": "What is Movement?", "aptos": "What is Aptos?", "movement": "Movement Technical Details", - "movement_framework" : "Movement Framework (Coming Soon)", - "interoperability_security": "Interoperability & Security (Coming Soon)", "move_solidity" : "Move vs Solidity", "move_language_basic" : "Move Language Basic", "move_language_advanced" : "Move Language Advanced", + "aptos_move" : "Aptos Move", + "swap_contract" : "Swap Contract", "rakiapp": { "title": "Movement with Aptos Workshop ↗", "type": "page", diff --git a/pages/aptos_move/_meta.json b/pages/aptos_move/_meta.json new file mode 100644 index 0000000..8645ea4 --- /dev/null +++ b/pages/aptos_move/_meta.json @@ -0,0 +1,5 @@ +{ + "aptos_account" : "Aptos Account", + "aptos_coin" : "Aptos Coin", + "object" : "Object" +} diff --git a/pages/aptos_move/aptos_account.mdx b/pages/aptos_move/aptos_account.mdx new file mode 100644 index 0000000..9293f0b --- /dev/null +++ b/pages/aptos_move/aptos_account.mdx @@ -0,0 +1,64 @@ +# Aptos Account +## Cấu trúc Address + +Address trong Aptos là một chuỗi 32-byte, thường được biểu diễn dưới dạng 64 ký tự hex. Mỗi ký tự hex đại diện cho một nibble (4 bit). + +### Ví dụ: +- Alice: `0xeeff357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175b` +- Bob: `0x19aadeca9388e009d136245b9a67423f3eee242b03142849eb4f81a4a409e59c` + +## Tiền tố và số 0 đứng đầu +1. address có thể có tiền tố `0x` để chỉ ra rằng đó là một số hex. +2. Các số 0 đứng đầu có thể được bỏ qua khi hiển thị, nhưng vẫn là một phần của address 32-byte đầy đủ. + +### Ví dụ với số 0 đứng đầu: +- Dan: `0000357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175b` +- Dan: `0x0000357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175b` +- Dan: `0x357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175b` + +Tất cả các biểu diễn trên đều chỉ cùng một address. + +## Tạo address +address tài khoản được tạo từ khóa xác thực ban đầu, theo quy trình sau: + 1. Tạo cặp khóa công khai/riêng tư. + 2. Kết hợp khóa công khai với scheme chữ ký để tạo khóa xác thực 32-byte. + 3. Sử dụng khóa xác thực này làm address tài khoản. + +## Xử lý address trong code + +Khi làm việc với address trong code, nhà phát triển nên lưu ý: + +1. Luôn xử lý address dưới dạng 32-byte đầy đủ. +2. Khi hiển thị cho người dùng, có thể bỏ qua các số 0 đứng đầu để dễ đọc hơn. +3. Khi nhận đầu vào từ người dùng, hãy chấp nhận cả dạng đầy đủ và dạng rút gọn, sau đó chuẩn hóa về dạng 32-byte. + +## Ví dụ xử lý address trong Move + +```move +use std::address; + +fun process_address(addr: address) { + // address luôn là 32-byte trong Move + // Không cần xử lý đặc biệt +} + +fun display_address(addr: address): String { + // Chuyển đổi address thành chuỗi và loại bỏ số 0 đứng đầu + let addr_str = address::to_string(addr); + // Lưu ý: Đây chỉ là ví dụ, Move không có kiểu String nguyên thủy + // Bạn cần implement hàm remove_leading_zeros + remove_leading_zeros(addr_str) +} +``` + +## Address Short +Aptos cũng hỗ trợ address ngắn hơn 32-byte. Trong trường hợp này: +- address sẽ được tự động điền thêm số 0 ở đầu để đạt đủ 32-byte. +- Ví dụ: 0x1 sẽ được xử lý như 0x0000000000000...01 + +Nhà phát triển nên cẩn thận khi xử lý address ngắn và đảm bảo rằng chúng được chuẩn hóa đúng cách trước khi sử dụng. + +## Bảo mật và address +- address không phải là private, nhưng nó là định danh duy nhất của tài khoản. +- Không nên sử dụng address làm seed để tạo khóa riêng tư. +- Luôn xác minh address khi nhận từ đầu vào người dùng để tránh các cuộc tấn công liên quan đến address không hợp lệ. diff --git a/pages/aptos_move/aptos_coin.mdx b/pages/aptos_move/aptos_coin.mdx new file mode 100644 index 0000000..71012fd --- /dev/null +++ b/pages/aptos_move/aptos_coin.mdx @@ -0,0 +1,171 @@ +# Aptos Coin + +[Coin](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/coin.move) cung cấp một framework tiêu chuẩn, an toàn về kiểu cho các token hoặc coin fungible đơn giản. + +## Structure + +### Reusability + +Một coin được định nghĩa trong Move như sau: + +```rust +struct Coin has store { + /// Số lượng coin mà địa chỉ này có. + value: u64, +} +``` + +Coin sử dụng `CoinType` để hỗ trợ tái sử dụng framework Coin cho các Coin riêng biệt. Ví dụ, `Coin` và `Coin` là hai coin khác nhau. + +### Kho lưu trữ toàn cục +Coin cũng hỗ trợ một resource để lưu trữ coin trong kho lưu trữ toàn cục: + +```rust +struct CoinStore has key { + coin: Coin, + frozen: bool, + deposit_events: EventHandle, + withdraw_events: EventHandle, +} +``` + +Thông tin hoặc metadata của coin được lưu trữ trong global storage dưới tài khoản của người tạo coin: +```rust +struct CoinInfo has key { + name: string::String, + /// Ký hiệu của coin, thường là phiên bản ngắn hơn của tên. + /// Ví dụ, Singapore Dollar là SGD. + symbol: string::String, + /// Số lượng số thập phân được sử dụng để hiển thị cho người dùng. + /// Ví dụ, nếu `decimals` bằng `2`, số dư `505` coin sẽ + /// được hiển thị cho người dùng là `5.05` (`505 / 10 ** 2`). + decimals: u8, + /// Số lượng của loại coin này đang tồn tại. + supply: Option, +} +``` + +## Tạo một CoinType mới + +Người tạo coin có thể publish lên một account on-chain một module mới định nghĩa một struct để đại diện cho một `CoinType` mới. Người tạo coin sau đó sẽ gọi `coin:initialize` từ tài khoản đó để đăng ký nó như một coin hợp lệ, và nhận lại các struct cho phép gọi các function để đốt(burn) và tạo(mint) coin cũng như đóng băng (freeze) `CoinStore`. Những struct này cần được lưu trữ trong global storage bởi người tạo để quản lý việc sử dụng coin. + +```rust +public fun initialize( + account: &signer, + name: string::String, + symbol: string::String, + decimals: u8, + monitor_supply: bool, +): (BurnCapability, FreezeCapability, MintCapability) { +``` + +- Ba tham số đầu tiên (`name`, `symbol`, `decimals`) chỉ là metadata và không ảnh hưởng đến các ứng dụng on-chain. Một số ứng dụng có thể sử dụng decimal để quy đổi một Coin đơn vị thành phân số coin. +- Theo dõi nguồn cung (`monitor_supply`) giúp theo dõi tổng số coin trong lưu thông. Tuy nhiên, do cách thức hoạt động của bộ thực thi song song, bật tùy chọn này sẽ ngăn chặn bất kỳ việc thực thi song song nào của mint và burn. Nếu coin sẽ được tạo hoặc đốt thường xuyên, hãy cân nhắc tắt `monitor_supply`. + +## Tạo Coin (Mint) +Nếu người tạo hoặc quản lý muốn tạo coin, họ phải lấy tham chiếu đến `MintCapability` của họ, được tạo ra trong `initialize`, và gọi: + +```rust +public fun mint( + amount: u64, + _cap: &MintCapability, +): Coin acquires CoinInfo { +``` + +Điều này sẽ tạo ra một struct Coin mới chứa giá trị được xác định bởi `amount`. + +## Đốt Coin (Burn) +Nếu người tạo hoặc quản lý muốn đốt coin, họ phải lấy tham chiếu đến `BurnCapability` của họ, được tạo ra trong `initialize`, và gọi: + +```rust +public fun burn( + coin: Coin, + _cap: &BurnCapability, +) acquires CoinInfo { +``` + +Người tạo hoặc quản lý cũng có thể đốt coin từ một `CoinStore`: + +```rust +public fun burn_from( + account_addr: address, + amount: u64, + burn_cap: &BurnCapability, +) acquires CoinInfo, CoinStore { +``` + +## Đóng băng tài khoản (Freeze) + +Nếu người tạo hoặc quản lý muốn đóng băng một `CoinStore` trên một tài khoản cụ thể, họ phải lấy tham chiếu đến `FreezeCapability` của họ, được tạo ra trong `initialize`, và gọi: + +```rust +public entry fun freeze_coin_store( + account_addr: address, + _freeze_cap: &FreezeCapability, +) acquires CoinStore { +``` + +## Gộp Coin (Merge) +Hai coin cùng loại có thể được gộp thành một struct Coin duy nhất đại diện cho tổng giá trị của hai coin độc lập bằng cách gọi: + +```rust +public fun merge( + dst_coin: &mut Coin, + source_coin: Coin, +) { +``` + +## Trích xuất Coin (Extract) +Một Coin có thể bị trừ giá trị để tạo ra một Coin khác bằng cách gọi: + +```rust +public fun extract( + coin: &mut Coin, + amount: u64, +): Coin { +``` + +## Rút Coin từ CoinStore (Withdraw) +Người nắm giữ `CoinStore` có thể trích xuất một Coin với giá trị được chỉ định bằng cách gọi: + +```rust +public fun withdraw( + account: &signer, + amount: u64, +): Coin acquires CoinStore { +``` + +## Gửi Coin vào CoinStore (Deposit) +Bất kỳ thực thể nào cũng có thể gửi coin vào `CoinStore` của một tài khoản bằng cách gọi: + +```rust +public fun deposit( + account_addr: address, + coin: Coin, +) acquires CoinStore { +``` + +## Chuyển Coin (Transfer) +Người nắm giữ `CoinStore` có thể trực tiếp chuyển coin từ tài khoản của họ sang `CoinStore` của tài khoản khác bằng cách gọi: + +```rust +public entry fun transfer( + from: &signer, + to: address, + amount: u64, +) acquires CoinStore { +``` + +## Sự kiện (Event) + +```rust +struct DepositEvent has drop, store { + amount: u64, +} +``` + +```rust +struct WithdrawEvent has drop, store { + amount: u64, +} +``` diff --git a/pages/aptos_move/object.mdx b/pages/aptos_move/object.mdx new file mode 100644 index 0000000..4f3f0a4 --- /dev/null +++ b/pages/aptos_move/object.mdx @@ -0,0 +1,86 @@ +# Object + +## Mô hình Object + +Mô hình Object cho phép Move biểu diễn một kiểu dữ liệu phức tạp như một tập hợp các tài nguyên được lưu trữ trong một địa chỉ duy nhất. Nó cung cấp một mô hình khả năng phong phú, cho phép kiểm soát tài nguyên chi tiết và quản lý quyền sở hữu linh hoạt. + +## Các đặc điểm của mô hình Object + +1. Giao diện lưu trữ đơn giản hóa: Hỗ trợ lưu trữ một tập hợp các tài nguyên không đồng nhất cùng nhau. Điều này cho phép các kiểu dữ liệu chia sẻ một lớp dữ liệu cơ bản chung (ví dụ: tokens), trong khi vẫn có thể mở rộng phong phú hơn (ví dụ: vé concert, thanh kiếm). + +2. Mô hình dữ liệu và quyền sở hữu có thể truy cập toàn cầu: Cho phép người tạo và nhà phát triển quyết định việc áp dụng và vòng đời của dữ liệu. + +3. Mô hình lập trình có thể mở rộng: Hỗ trợ cá nhân hóa các ứng dụng người dùng tận dụng framework cốt lõi, bao gồm cả tokens. + +4. Hỗ trợ phát sự kiện trực tiếp: Cải thiện khả năng phát hiện các sự kiện liên quan đến objects. + +5. Tối ưu hóa hiệu suất hệ thống: Sử dụng nhóm tài nguyên để tối ưu hóa gas, tránh chi phí deserialization và serialization đắt đỏ, và hỗ trợ khả năng xóa. + +Object là một primitive cốt lõi trong Aptos Move và được tạo thông qua module object tại địa chỉ 0x1::object. + +## Ví dụ mã + +Dưới đây là một ví dụ về cách sử dụng Object trong Aptos Move: + +```move +module my_addrx::MyFriends +{ + use std::vector; + use aptos_std::object::{Self,Object}; + use std::signer; + use aptos_framework::account; + + struct MyFriends has key + { + friends: vector>, + } + + // Hàm tạo danh sách bạn bè + public entry fun create_friends(caller: &signer, list:vector> ) : Object + { + let myfriend_constructor_ref = object::create_object_from_account(caller); + let myfriend_signer = object::generate_signer(&myfriend_constructor_ref); + move_to(&myfriend_signer, MyFriends{ friends:list }); + let obj = object::object_from_constructor_ref(&myfriend_constructor_ref); + return obj + } + + // Hàm chuyển quyền sở hữu object + public entry fun transferring_of_ownership(from: &signer,to: address,obj: Object) : address + { + object::transfer(from,obj,to); // Chuyển quyền sở hữu của object + let new_owner_of_the_object = object::owner(obj); // Quyền sở hữu được theo dõi trên chính object + return new_owner_of_the_object + } + + // Hàm kiểm tra + #[test(owner = @0x123)] + public entry fun test_flow(owner: signer) + { + account::create_account_for_test(signer::address_of(&owner)); + + // Tạo danh sách bạn bè + let list = vector::empty>(); + vector::push_back(&mut list, b"John"); + vector::push_back(&mut list, b"Harry"); + vector::push_back(&mut list, b"Gwen"); + let obj = create_friends(&owner,list); + + assert!(signer::address_of(&owner) == @0x123,1); + + // Chuyển quyền sở hữu của object từ tài khoản chủ sở hữu sang tài khoản 0x345 + let new_owner_address = transferring_of_ownership(&owner,@0x345,obj); + + assert!(new_owner_address == @0x345,1); + } +} +``` + +Trong ví dụ này: + +1. Chúng ta định nghĩa một struct `MyFriends` để lưu trữ danh sách bạn bè. +2. Hàm `create_friends` tạo một Object mới chứa danh sách bạn bè. +3. Hàm `transferring_of_ownership` cho phép chuyển quyền sở hữu của Object từ một tài khoản sang tài khoản khác. +4. Hàm `test_flow` kiểm tra quá trình tạo Object và chuyển quyền sở hữu. + +Mô hình Object trong Aptos Move cung cấp một cách linh hoạt và mạnh mẽ để quản lý dữ liệu phức tạp và quyền sở hữu trong các ứng dụng blockchain. diff --git a/pages/interoperability_security.mdx b/pages/interoperability_security.mdx deleted file mode 100644 index e75c927..0000000 --- a/pages/interoperability_security.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Interoperability & Security - -.. Coming Soon diff --git a/pages/interoperability_security/_meta.json b/pages/interoperability_security/_meta.json deleted file mode 100644 index 4d99d89..0000000 --- a/pages/interoperability_security/_meta.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "m1_shared_decentralized_sequencer" : "M1 Shared Decentralized Sequencer", - "multi_asset_staking" : "Multi Asset Staking" -} diff --git a/pages/interoperability_security/m1_shared_decentralized_sequencer.mdx b/pages/interoperability_security/m1_shared_decentralized_sequencer.mdx deleted file mode 100644 index b51e896..0000000 --- a/pages/interoperability_security/m1_shared_decentralized_sequencer.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# M1 Shared Decentralized Sequencer - -... Coming Soon diff --git a/pages/interoperability_security/multi_asset_staking.mdx b/pages/interoperability_security/multi_asset_staking.mdx deleted file mode 100644 index 8b196ef..0000000 --- a/pages/interoperability_security/multi_asset_staking.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Multi-Asset Staking - -.. Coming Soon diff --git a/pages/move_language_advanced/_meta.json b/pages/move_language_advanced/_meta.json index 7c7c98e..1d14e4d 100644 --- a/pages/move_language_advanced/_meta.json +++ b/pages/move_language_advanced/_meta.json @@ -1,14 +1,9 @@ { "global_storage_structure" : "Global Storage Structure", - "global_storage_operations" : "Global Storage Operations", + " +global_storage_operations" : "Global Storage Operations", "phantom_type_parameters" : "Phantom Type Parameters", - "timestamps" : "Timestamps", "ownership" : "Ownership", "move_coding_conventions" : "Move Coding Conventions", "view_function" : "View Function", - "aptos_account" : "Aptos Account", - "aptos_coin" : "Aptos Coin", - "aptos_token_nft" : "Aptos Token (NFT)", - "object" : "Object", - "token_v2" : "Token V2" } diff --git a/pages/move_language_advanced/ownership.mdx b/pages/move_language_advanced/ownership.mdx new file mode 100644 index 0000000..c479047 --- /dev/null +++ b/pages/move_language_advanced/ownership.mdx @@ -0,0 +1,60 @@ +# Ownership trong Move + +## Khái niệm cơ bản + +Ownership (quyền sở hữu) trong ngôn ngữ lập trình Move là một khái niệm được sử dụng để quản lý bộ nhớ và tài nguyên. Nó dựa trên ý tưởng rằng mỗi tài nguyên chỉ có thể có một chủ sở hữu tại một thời điểm, và quyền sở hữu có thể được chuyển giao từ chủ sở hữu này sang chủ sở hữu khác. + +Điều này cho phép Move: +- Thực thi tính an toàn về bộ nhớ +- Ngăn chặn các cuộc đua dữ liệu (data races) +- Cho phép quản lý bộ nhớ hiệu quả + +## Cách hoạt động + +1. **Borrow checker**: Move sử dụng borrow checker để đảm bảo rằng một tài nguyên không được sử dụng sau khi nó đã được di chuyển hoặc mượn. + +2. **Linear Typed System**: Move có một hệ thống kiểu tuyến tính, nghĩa là tài nguyên chỉ có thể được tiêu thụ một lần và phải được di chuyển hoặc mượn theo một thứ tự cụ thể. + +3. **Phạm vi sở hữu**: Chủ sở hữu là một phạm vi sở hữu một biến. Biến có thể được định nghĩa trong phạm vi này (ví dụ: với từ khóa `let`) hoặc được truyền vào phạm vi dưới dạng đối số. Trong Move, phạm vi duy nhất là hàm. + +4. **Quy tắc một chủ sở hữu**: Mỗi biến chỉ có một chủ sở hữu. Khi một biến được truyền vào hàm dưới dạng đối số, hàm này trở thành chủ sở hữu mới, và biến không còn thuộc sở hữu của hàm đầu tiên nữa. + +## Di chuyển và Sao chép + +### Di chuyển (Move) + +Khi một biến được truyền vào một hàm khác, nó được di chuyển và sử dụng OpCode `MoveLoc`. Ví dụ: + +```rust +script { + use {{sender}}::M; + + fun main() { + let a : Module::T = Module::create(10); + + M::value(move a); // biến a được di chuyển + + // biến cục bộ a bị hủy + } +} +``` + +### Sao chép (Copy) +Nếu bạn cần truyền một giá trị vào hàm (nơi nó sẽ bị di chuyển) và lưu một bản sao của biến của bạn, bạn có thể sử dụng từ khóa copy: + +```rust +script { + use {{sender}}::M; + + fun main() { + let a : Module::T = Module::create(10); + + // chúng ta sử dụng từ khóa copy để sao chép cấu trúc + // có thể được sử dụng như `let a_copy = copy a` + M::value(copy a); + M::value(a); // không bị lỗi, a vẫn còn ở đây + } +} +``` + +**Lưu ý: Việc sao chép một giá trị sẽ nhân đôi nó và tăng kích thước bộ nhớ của chương trình. Trong blockchain, mỗi byte đều có giá và ảnh hưởng đến chi phí thực thi, vì vậy việc sử dụng copy quá nhiều có thể tốn kém về mặt bộ nhớ.** diff --git a/pages/move_language_advanced/phantom_type_parameters.mdx b/pages/move_language_advanced/phantom_type_parameters.mdx new file mode 100644 index 0000000..3374cc0 --- /dev/null +++ b/pages/move_language_advanced/phantom_type_parameters.mdx @@ -0,0 +1,49 @@ +# Original Phantom Type Parameters trong Move + +## Định nghĩa + +Original phantom type parameters là một loại tham số đặc biệt trong định nghĩa struct của ngôn ngữ Move. Chúng được đánh dấu bằng từ khóa `phantom` và có một số đặc điểm riêng biệt. + +## Mục đích sử dụng + +Original phantom type parameters giúp: +- Tránh phải chú thích khả năng (ability) không cần thiết khi sử dụng các kiểu generic +- Cho phép khai báo một tham số kiểu mà không ảnh hưởng đến khả năng của struct + +## Cách sử dụng + +### Khai báo +Thêm từ khóa `phantom` trước tham số kiểu trong định nghĩa struct. + +Ví dụ: +```move +struct S { ... } +``` + +### Quy tắc quan trọng +Original phantom type parameters chỉ có thể được sử dụng ở "vị trí phantom". Điều này có nghĩa là chúng chỉ có thể: +- Không được sử dụng trong định nghĩa struct, hoặc +- Chỉ được sử dụng làm đối số cho một original phantom type parameter khác + +Ví dụ: +- Hợp lệ: +```move +struct S1 { f: u64 } // OK: T1 không được sử dụng +struct S2 { f: S1 } // OK: T1 ở vị trí phantom +``` + +- Không hợp lệ +```move +struct S1 { f: T } // Lỗi: T không ở vị trí phantom +struct S2 { f: T } +struct S3 { f: S2 } // Lỗi: T không ở vị trí phantom +``` + +## Ảnh hưởng tới abilities của Struct +Khi khởi tạo một struct, các đối số cho original phantom type parameters không ảnh hưởng đến khả năng của struct đó. + +Ràng buộc khả năng +- Original phantom type parameters vẫn có thể có ràng buộc khả năng. Khi sử dụng, đối số phải thỏa mãn ràng buộc này, dù là original phantom type parameter. + +## Kết luận +Original phantom type parameters là một công cụ hữu ích trong Move để linh hoạt hơn trong việc định nghĩa các struct generic mà không ảnh hưởng không cần thiết đến khả năng của chúng. diff --git a/pages/move_language_advanced/view_function.mdx b/pages/move_language_advanced/view_function.mdx new file mode 100644 index 0000000..1c024f2 --- /dev/null +++ b/pages/move_language_advanced/view_function.mdx @@ -0,0 +1,39 @@ +# View Functions trong Aptos Blockchain + +## Định nghĩa + +View function là một hàm truy xuất dữ liệu từ blockchain mà không thực hiện bất kỳ thay đổi nào. Nó được sử dụng để đọc và hiển thị dữ liệu được lưu trữ trên blockchain. + +## Tầm quan trọng + +View functions quan trọng trong Aptos blockchain vì: + +1. Cho phép các ứng dụng bên ngoài truy cập và hiển thị dữ liệu trên blockchain mà không cần truy cập trực tiếp vào blockchain. +2. Cải thiện hiệu quả và bảo mật của mạng blockchain. + +## Lợi ích + +1. Tạo ra cấu trúc API GET để hiển thị trạng thái phức tạp của smart contracts. +2. Đơn giản hóa quy trình truy xuất dữ liệu phức tạp, tiết kiệm thời gian và tài nguyên. +3. Cải thiện đáng kể khả năng sử dụng của Aptos blockchain. +4. Làm cho blockchain dễ tiếp cận hơn với các nhà phát triển. + +## Cách sử dụng + +Sử dụng decorator `#[view]` để định nghĩa một view function: + +```move +#[view] +public fun get_todos(todo_address: address): vector acquires TodoStore { + borrow_global(todo_address).todos +} +``` +## Ưu điểm + +Truy xuất trạng thái phức tạp từ smart contract một cách hiệu quả hơn. +Định nghĩa các hàm trả về dữ liệu cụ thể từ smart contract. +Cung cấp API đơn giản cho các invoker bên ngoài để truy xuất dữ liệu từ blockchain. +Nhận dữ liệu cụ thể cần thiết thay vì toàn bộ cơ sở dữ liệu mỗi lần truy vấn. + +# Kết luận +View functions là một bổ sung quan trọng cho Aptos blockchain, cải thiện đáng kể khả năng sử dụng và tiếp cận của nó. Chúng giúp các nhà phát triển tạo ra các ứng dụng hiệu quả hơn bằng cách đơn giản hóa quá trình truy xuất dữ liệu từ blockchain. diff --git a/pages/movement_framework.mdx b/pages/movement_framework.mdx deleted file mode 100644 index 29a372d..0000000 --- a/pages/movement_framework.mdx +++ /dev/null @@ -1,11 +0,0 @@ -# Movement Framwork - -Movement network được xây dựng trên các robust framework cho phép khởi tạo (creation), triển khải (deployment), và quản lý các rollups dựa trên Move. Các framework này bao gồm: - -- MoveStack -- Move Arena -- Move Rollup Framework - -``` -Mỗi Framework được xây dựng và thiết kế để nâng cao hiệu suất, bảo mật và khả năng tương tác -``` diff --git a/pages/movement_framework/_meta.json b/pages/movement_framework/_meta.json deleted file mode 100644 index 235a80e..0000000 --- a/pages/movement_framework/_meta.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "move_stack" : "Move Stack", - "move_arena" : "Move Arena", - "move_rollup_framework" : "Move Rollup Framework", - "transaction_lifecycle" : "Transaction Lifecycle" -} diff --git a/pages/movement_framework/move_arena.mdx b/pages/movement_framework/move_arena.mdx deleted file mode 100644 index 5bc58bc..0000000 --- a/pages/movement_framework/move_arena.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Move Arena - -... Coming Soon diff --git a/pages/movement_framework/move_rollup_framework.mdx b/pages/movement_framework/move_rollup_framework.mdx deleted file mode 100644 index 9e39b2e..0000000 --- a/pages/movement_framework/move_rollup_framework.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Move Rollup Framework - -... Comming Soon diff --git a/pages/movement_framework/move_stack.mdx b/pages/movement_framework/move_stack.mdx deleted file mode 100644 index 24e733d..0000000 --- a/pages/movement_framework/move_stack.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Move Stack - -... Coming Soon diff --git a/pages/movement_framework/move_stack.org b/pages/movement_framework/move_stack.org deleted file mode 100644 index 606525f..0000000 --- a/pages/movement_framework/move_stack.org +++ /dev/null @@ -1 +0,0 @@ -* Move Stack diff --git a/pages/movement_framework/transaction_lifecycle.mdx b/pages/movement_framework/transaction_lifecycle.mdx deleted file mode 100644 index 2acda54..0000000 --- a/pages/movement_framework/transaction_lifecycle.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Transaction Lifecycle - -... Coming Soon diff --git a/pages/swap_contract/_meta.json b/pages/swap_contract/_meta.json new file mode 100644 index 0000000..1ccdb71 --- /dev/null +++ b/pages/swap_contract/_meta.json @@ -0,0 +1,5 @@ +{ + "constant_product_formular": "Constant Product Formular - CPF", + "math_safe" : "Math Safe", + "swap_contract" : "Swap Contract" +} diff --git a/pages/swap_contract/constant_product_formular.mdx b/pages/swap_contract/constant_product_formular.mdx new file mode 100644 index 0000000..083e207 --- /dev/null +++ b/pages/swap_contract/constant_product_formular.mdx @@ -0,0 +1,76 @@ +# Công thức Constant Product trong DEX +## Tổng quan + +Công thức constant product là nền tảng của nhiều sàn giao dịch phi tập trung (DEX) như Uniswap. Nó được sử dụng để xác định tỷ lệ trao đổi giữa hai token trong một pool thanh khoản. + +## Nguyên lý + +Công thức dựa trên nguyên tắc rằng tích của số lượng hai token trong pool luôn phải không đổi trước và sau mỗi giao dịch: + +``` +x * y = k +``` + +Trong đó: +- `x` là số lượng của token A trong pool +- `y` là số lượng của token B trong pool +- `k` là hằng số không đổi + +## Hàm tính toán số lượng token đầu ra + +```move +public fun get_amount_out(amount_in: u128, in_reserve: u128, out_reserve: u128): u128 { + let amount_in_with_fee = amount_in * 997; + let numerator = amount_in_with_fee * out_reserve; + let denominator = in_reserve * 1000 + amount_in_with_fee; + numerator / denominator +} +``` + +### Tham số + +- `amount_in`: Số lượng token đầu vào mà người dùng muốn trao đổi. +- `in_reserve`: Số lượng token đầu vào hiện có trong pool. +- `out_reserve`: Số lượng token đầu ra hiện có trong pool. + +### Giải thích + +1. **Phí giao dịch**: + ```move + let amount_in_with_fee = amount_in * 997; + ``` + Áp dụng phí giao dịch 0.3% (3/1000) bằng cách nhân `amount_in` với 997. + +2. **Tính toán số lượng đầu ra**: + ```move + let numerator = amount_in_with_fee * out_reserve; + let denominator = in_reserve * 1000 + amount_in_with_fee; + ``` + Đây là phần triển khai của công thức constant product, đảm bảo rằng `x * y = k` được duy trì sau giao dịch. + +3. **Kết quả**: + ```move + numerator / denominator + ``` + Chia tử số cho mẫu số để có được số lượng token đầu ra. + +## Lưu ý + +- Hàm này sử dụng số nguyên 128-bit (`u128`) để tính toán, giúp tăng độ chính xác và tránh tràn số. +- Phí giao dịch 0.3% được tích hợp trực tiếp vào công thức. +- Kết quả được làm tròn xuống do sử dụng phép chia số nguyên. + +## Ví dụ sử dụng + +```move +let amount_in = 100000; // 100,000 token A +let reserve_a = 1000000; // 1,000,000 token A trong pool +let reserve_b = 500000; // 500,000 token B trong pool + +let amount_out = get_amount_out(amount_in, reserve_a, reserve_b); +// amount_out sẽ là số lượng token B mà người dùng nhận được +``` + +## Kết luận + +Công thức constant product đảm bảo tính thanh khoản của pool bằng cách điều chỉnh giá tự động dựa trên cung và cầu. Khi số lượng một token trong pool giảm, giá của nó sẽ tăng lên, và ngược lại, tạo ra một cơ chế cân bằng tự nhiên. diff --git a/pages/swap_contract/math_safe.mdx b/pages/swap_contract/math_safe.mdx new file mode 100644 index 0000000..e1667ca --- /dev/null +++ b/pages/swap_contract/math_safe.mdx @@ -0,0 +1,85 @@ +# MathSafe Module + +## Tổng quan + +MathSafe là một module cung cấp các phép toán số học an toàn cho các phép tính liên quan đến tiền tệ và tỷ lệ trong các ứng dụng DeFi (Tài chính phi tập trung). Module này được thiết kế để xử lý các phép tính với số nguyên lớn một cách chính xác và tránh tràn số, đặc biệt quan trọng trong các giao dịch tài chính. + +```rust +module moveview::Math { + public fun mul_div(a: u128, b: u128, denominator: u128): u128 { + let result = (a as u256) * (b as u256) / (denominator as u256); + (result as u128) + } + + public fun sqrt(y: u128): u64 { + if (y < 4) { + if (y == 0) { + 0u64 + } else { + 1u64 + } + } else { + let z = y; + let x = y / 2 + 1; + while (x < z) { + z = x; + x = (y / x + x) / 2; + }; + (z as u64) + } + } + + public fun min(a: u128, b: u128): u128 { + if (a < b) a else b + } +} +``` + +## Chức năng + +MathSafe cung cấp các hàm sau: + +1. `mul_div`: Nhân hai số và chia kết quả cho một số thứ ba. +2. `sqrt`: Tính căn bậc hai của một số. +3. `min`: Trả về giá trị nhỏ nhất trong hai số. + +## Tại sao cần MathSafe? + +### 1. Xử lý số nguyên lớn + +Trong các ứng dụng DeFi, chúng ta thường phải làm việc với số lượng token rất lớn (ví dụ: 10^18 đơn vị cho 1 token). Các phép tính thông thường có thể dẫn đến tràn số, gây ra kết quả không chính xác hoặc lỗi runtime. + +### 2. Độ chính xác trong tính toán tài chính + +Các giao dịch tài chính yêu cầu độ chính xác cao. Ngay cả sai số nhỏ cũng có thể dẫn đến mất mát đáng kể khi xử lý số lượng lớn. + +### 3. Tránh lỗi tràn số + +Phép nhân hai số lớn có thể dễ dàng vượt quá giới hạn của kiểu dữ liệu u128. MathSafe sử dụng kỹ thuật để tránh tràn số trong quá trình tính toán. + +### 4. Tính toán tỷ lệ chính xác + +Trong các pool thanh khoản, việc tính toán tỷ lệ token cần phải chính xác để đảm bảo công bằng cho người dùng và duy trì cân bằng của pool. + +### 5. Tối ưu hóa gas + +Bằng cách sử dụng các phép toán hiệu quả, MathSafe giúp tối ưu hóa chi phí gas cho các giao dịch trên blockchain. + +## Ví dụ sử dụng + +```move +use moveview::MathSafe; + +// Tính lượng token output trong một swap +let amount_out = MathSafe::mul_div(amount_in, reserve_out, reserve_in); + +// Tính lượng liquidity khi thêm vào pool +let liquidity = MathSafe::sqrt(amount_a * amount_b); + +// Chọn giá trị nhỏ hơn để tránh slippage +let amount = MathSafe::min(desired_amount, max_amount); +``` + +## Kết luận + +MathSafe là một công cụ quan trọng trong việc phát triển các ứng dụng DeFi an toàn và chính xác. Bằng cách sử dụng module này, các nhà phát triển có thể tránh được nhiều lỗi phổ biến liên quan đến tính toán số học, đảm bảo tính toàn vẹn của dữ liệu tài chính và nâng cao độ tin cậy của ứng dụng. diff --git a/pages/swap_contract/swap_contract.mdx b/pages/swap_contract/swap_contract.mdx new file mode 100644 index 0000000..3a98c9f --- /dev/null +++ b/pages/swap_contract/swap_contract.mdx @@ -0,0 +1,287 @@ +# Swap Contract + +```rust +module moveview::Swap { + // Import required modules and libraries + use aptos_framework::coin::{Self, Coin, MintCapability, BurnCapability}; + use std::string; + use std::string::String; + use std::option; + use moveview::Math::{sqrt, min}; + use std::signer::address_of; + use moveview::Math; + + // Constant for minimum liquidity required in LP tokens + const MINIMUM_LIQUIDITY: u64 = 1000; + + // Define a phantom struct LP with generic types X and Y to represent LP tokens for token pair X-Y + struct LP {} + + // Define a struct Pair with generic types X and Y representing a token pair with its related data + struct Pair has key { + x_coin: Coin, + y_coin: Coin, + lp_locked: Coin>, + lp_mint: MintCapability>, + lp_burn: BurnCapability>, + } + + // Function to generate LP token name symbol for a given token pair X-Y + public fun generate_lp_name_symbol(): String { + let lp_name_symbol = string::utf8(b""); + string::append_utf8(&mut lp_name_symbol, b"LP"); + string::append_utf8(&mut lp_name_symbol, b"-"); + string::append(&mut lp_name_symbol, coin::symbol()); + string::append_utf8(&mut lp_name_symbol, b"-"); + string::append(&mut lp_name_symbol, coin::symbol()); + lp_name_symbol + } + + // Function to create a new pool for token pair X-Y + public entry fun create_pool(sender: &signer) { + // Check if the pair already exists (a pair for X-Y or Y-X) + assert!(!pair_exist(@moveview), 1000); + + // Generate LP token name and symbol for the token pair X-Y + let lp_name_symbol = generate_lp_name_symbol(); + + // Initialize LP token and get its mint and burn capabilities + let (lp_burn, lp_freeze, lp_mint) = coin::initialize>( + sender, + lp_name_symbol, + lp_name_symbol, + 6, // Number of decimal places for the LP token + true, // LP token is fungible + ); + + // Remove the freeze capability to prevent freezing LP tokens + coin::destroy_freeze_cap(lp_freeze); + + // Create a new Pair for token pair X-Y and store it in the global storage + move_to( + sender, + Pair { + x_coin: coin::zero(), + y_coin: coin::zero(), + lp_locked: coin::zero>(), + lp_mint, + lp_burn, + }, + ); + } + + // Function to add liquidity for a given token pair X-Y + public entry fun add_liquidity(sender: &signer, x_amount: u64, y_amount: u64) + acquires Pair + { + // Make sure the pair exists + assert!(exists>(@moveview), 1000); + + // Borrow the Pair data from global storage + let pair = borrow_global_mut>(@moveview); + + // Convert the amounts to u128 to prevent overflow during calculations + let x_amount = (x_amount as u128); + let y_amount = (y_amount as u128); + + // Get the current reserves for token X and Y + let x_reserve = (coin::value(&pair.x_coin) as u128); + let y_reserve = (coin::value(&pair.y_coin) as u128); + + // Calculate the optimal amount of Y to be added given the amount of X + let y_amount_optimal = quote(x_amount, x_reserve, y_reserve); + + // Choose the smaller of the actual Y amount and the optimal Y amount + if (y_amount_optimal <= y_amount) { + y_amount = y_amount_optimal; + }else{ + let x_amount_optimal = quote(y_amount,y_reserve,x_reserve); + x_amount = x_amount_optimal; + }; + + // Withdraw X and Y tokens from the sender's account + let x_amount_coin = coin::withdraw(sender, (x_amount as u64)); + let y_amount_coin = coin::withdraw(sender, (y_amount as u64)); + + // Deposit the withdrawn tokens into the Pair + coin::merge(&mut pair.x_coin, x_amount_coin); + coin::merge(&mut pair.y_coin, y_amount_coin); + + // Calculate the liquidity to be minted and mint LP tokens accordingly + let liquidity; + let total_supply = *option::borrow(&coin::supply>()); + if (total_supply == 0){ + liquidity = sqrt(((x_amount * y_amount) as u128)) - MINIMUM_LIQUIDITY; + let lp_locked = coin::mint(MINIMUM_LIQUIDITY, &pair.lp_mint); + coin::merge(&mut pair.lp_locked, lp_locked); + } else { + liquidity = (min( + Math::mul_div(x_amount, total_supply, x_reserve), + Math::mul_div(y_amount, total_supply, y_reserve), + ) as u64); + }; + + // Mint the liquidity and deposit it into the sender's account + let lp_coin = coin::mint>(liquidity, &pair.lp_mint); + let addr = address_of(sender); + if (!coin::is_account_registered>(addr)) { + coin::register>(sender); + }; + coin::deposit(addr, lp_coin); + } + + // Function to remove liquidity for a given token pair X-Y + public entry fun remove_liquidity(sender: &signer, liquidity: u64) acquires Pair { + // Make sure the pair exists + assert!(exists>(@moveview), 1000); + + // Borrow the Pair data from global storage + let pair = borrow_global_mut>(@moveview); + + // Withdraw LP tokens from the sender's account + let liquidity_coin = coin::withdraw>(sender, liquidity); + coin::burn(liquidity_coin, &pair.lp_burn); + + // Get the total supply of LP tokens, and the current reserves for token X and Y + let total_supply = *option::borrow(&coin::supply>()); + let x_reserve = (coin::value(&pair.x_coin) as u128); + let y_reserve = (coin::value(&pair.y_coin) as u128); + + // Calculate the amounts of X and Y to be removed based on the liquidity + let x_amount = Math::mul_div((liquidity as u128), x_reserve, total_supply); + let y_amount = Math::mul_div((liquidity as u128), y_reserve, total_supply); + + // Extract the amounts of X and Y tokens from the Pair + let x_amount_coin = coin::extract(&mut pair.x_coin,( x_amount as u64)); + let y_amount_coin = coin::extract(&mut pair.y_coin,( y_amount as u64)); + + // Deposit the extracted tokens into the sender's account + coin::deposit(address_of(sender), x_amount_coin); + coin::deposit(address_of(sender), y_amount_coin); + } + + // Function to swap token X for token Y + public entry fun swap_x_to_y(sender: &signer, amount_in: u64) acquires Pair { + // Make sure the pair exists + assert!(exists>(@moveview), 1000); + + // Borrow the Pair data from global storage + let pair = borrow_global_mut>(@moveview); + + // Withdraw the input token X from the sender's account + let coin_in = coin::withdraw(sender, amount_in); + + // Register the sender's account for token Y if not already registered + if (!coin::is_account_registered(address_of(sender))) { + coin::register(sender); + }; + + // Get the current reserves for token X and Y + let in_reserve = (coin::value(&pair.x_coin) as u128); + let out_reserve = (coin::value(&pair.y_coin) as u128); + + // Calculate the amount of token Y to be received for the given amount of X + let amount_out = get_amount_out((amount_in as u128), in_reserve, out_reserve); + + // Merge the input token X into the Pair and extract the output token Y from the Pair + coin::merge(&mut pair.x_coin, coin_in); + let amount_out_coin = coin::extract(&mut pair.y_coin, (amount_out as u64)); + + // Deposit the received token Y into the sender's account + coin::deposit(address_of(sender), amount_out_coin); + } + + // Function to check if a Pair exists for the token pair X-Y or Y-X + public fun pair_exist(addr: address): bool { + exists>(addr) || exists>(addr) + } + + // Function to calculate the optimal amount of Y given X, X reserve, and Y reserve + public fun quote(x_amount:u128,x_reserve:u128,y_reserve:u128):u128{ + Math::mul_div(x_amount,y_reserve,x_reserve) + } + + // Function to calculate the amount of output token for a given amount of input token + public fun get_amount_out(amount_in:u128,in_reserve:u128,out_reserve:u128):u128{ + let amount_in_with_fee = amount_in * 997; + let numerator = amount_in_with_fee * out_reserve; + let denominator = in_reserve * 1000 + amount_in_with_fee; + numerator / denominator + } + + // Function to get the current reserves of token X and Y in the Pair + public fun get_coin():(u64,u64) acquires Pair { + let pair = borrow_global>(@moveview); + (coin::value(&pair.x_coin),coin::value(&pair.y_coin)) + } +} +``` + +## Tổng quan + +Swap Contract là một smart contract được viết bằng Move language, triển khai trên nền tảng Aptos. Contract này cung cấp các chức năng cơ bản của một sàn giao dịch phi tập trung (DEX), cho phép người dùng tạo pool thanh khoản, thêm và rút thanh khoản, cũng như thực hiện các giao dịch swap token. + +## Cấu trúc dữ liệu + +### LP `` +Đại diện cho token LP (Liquidity Provider) của cặp token X-Y. + +### Pair `` +Lưu trữ thông tin về một cặp token, bao gồm: +- `x_coin`: Số lượng token X trong pool +- `y_coin`: Số lượng token Y trong pool +- `lp_locked`: Token LP bị khóa +- `lp_mint`: Khả năng tạo mới token LP +- `lp_burn`: Khả năng đốt token LP + +## Hằng số + +- `MINIMUM_LIQUIDITY`: Số lượng tối thiểu của token LP cần được khóa trong pool (1000). + +## Chức năng chính + +- `create_pool` +Tạo một pool mới cho cặp token X-Y. + +- `add_liquidity` +Thêm thanh khoản vào pool X-Y. + +- `remove_liquidity` +Rút thanh khoản từ pool X-Y. + +- `swap_x_to_y` +Thực hiện giao dịch swap từ token X sang token Y. + +## Hàm hỗ trợ +- `generate_lp_name_symbol` +Tạo tên và ký hiệu cho token LP của cặp X-Y. + +- `pair_exist` +Kiểm tra xem pool cho cặp token X-Y đã tồn tại chưa. + +- `quote` +Tính toán số lượng token Y tối ưu dựa trên số lượng token X và dự trữ hiện tại. + +- `get_amount_out` +Tính toán số lượng token đầu ra dựa trên số lượng token đầu vào và dự trữ hiện tại. + +- `get_coin` +Lấy thông tin về số lượng token X và Y hiện có trong pool. + +## Cách sử dụng + +1. Tạo pool: Gọi `create_pool` để tạo một pool mới cho cặp token X-Y. +2. Thêm thanh khoản: Sử dụng `add_liquidity` để thêm token X và Y vào pool. +3. Swap token: Gọi `swap_x_to_y` để đổi token X lấy token Y. +4. Rút thanh khoản: Sử dụng `remove_liquidity` để rút token từ pool. + +## Lưu ý quan trọng + +- Contract sử dụng module Math để thực hiện các phép tính an toàn và chính xác. +- Phí giao dịch được tính trực tiếp trong hàm `get_amount_out` (0.3%). +- Khi tạo pool lần đầu, một lượng nhỏ token LP sẽ bị khóa vĩnh viễn để tránh lỗi chia cho 0. + +## Bảo mật + +- Contract sử dụng các assertion để đảm bảo tính hợp lệ của các thao tác. +- Các phép tính được thực hiện với độ chính xác cao để tránh lỗi làm tròn và tràn số.